Skip to content

Commands

sereto.cli.commands

WorkingDir

Helper class for REPL implementing the cd command.

Attributes:

Name Type Description
old_cwd Path

The previous working directory.

Source code in sereto/cli/commands.py
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
class WorkingDir(metaclass=Singleton):
    """Helper class for REPL implementing the `cd` command.

    Attributes:
        old_cwd: The previous working directory.
    """

    old_cwd: Path = Field(default_factory=Path.cwd)

    def change(self, dst: Path, /) -> None:
        """Change the current working directory to the new location.

        Also saves the previous location for future reference.

        Args:
            dst: The new working directory

        Raises:
            SeretoPathError: If the provided path is not an existing directory.
        """
        if not dst.is_dir():
            raise SeretoPathError(f"Directory '{dst}' does not exist.")

        cwd = Path.cwd()
        os.chdir(dst)
        self.old_cwd = cwd

    def go_back(self) -> None:
        """Change the current working directory to the previous location."""
        self.change(self.old_cwd)

change(dst)

Change the current working directory to the new location.

Also saves the previous location for future reference.

Parameters:

Name Type Description Default
dst Path

The new working directory

required

Raises:

Type Description
SeretoPathError

If the provided path is not an existing directory.

Source code in sereto/cli/commands.py
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def change(self, dst: Path, /) -> None:
    """Change the current working directory to the new location.

    Also saves the previous location for future reference.

    Args:
        dst: The new working directory

    Raises:
        SeretoPathError: If the provided path is not an existing directory.
    """
    if not dst.is_dir():
        raise SeretoPathError(f"Directory '{dst}' does not exist.")

    cwd = Path.cwd()
    os.chdir(dst)
    self.old_cwd = cwd

go_back()

Change the current working directory to the previous location.

Source code in sereto/cli/commands.py
75
76
77
def go_back(self) -> None:
    """Change the current working directory to the previous location."""
    self.change(self.old_cwd)

_get_repl_prompt()

Get the prompt for the Read-Eval-Print Loop (REPL).

Source code in sereto/cli/commands.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def _get_repl_prompt() -> list[tuple[str, str]]:
    """Get the prompt for the Read-Eval-Print Loop (REPL)."""
    # Determine if the current working directory is a project directory
    project_id: TypeProjectId | None = None
    if is_project_dir(cwd := Path.cwd()):
        # Load the project to get the ID (this can be different from the directory name)
        project = Project.load_from(cwd)
        project_id = project.config.last_config.id

    final_prompt: list[tuple[str, str]] = []

    if os.environ.get("DEBUG", "0") == "1":
        final_prompt += [("class:debug", "DEBUG ")]

    if project_id is not None:
        final_prompt += [
            ("class:bracket", "("),
            ("class:project_id", f"{project_id}"),
            ("class:bracket", ") "),
        ]

    final_prompt += [("class:sereto", "sereto")]
    final_prompt += [("class:gt", " > ")]

    return final_prompt

repl_cd(project_id)

Switch the active project in the REPL.

Parameters:

Name Type Description Default
project_id TypeProjectId | Literal['-']

The ID of the project to switch to. Use '-' to go back to the previous working directory.

required

Raises:

Type Description
SeretoValueError

If the project ID is invalid.

SeretoPathError

If the project's path does not exist.

Source code in sereto/cli/commands.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
@click.command(name="cd")
@click.argument("project_id", type=str)
@validate_call
def repl_cd(project_id: TypeProjectId | Literal["-"]) -> None:
    """Switch the active project in the REPL.

    Args:
        project_id: The ID of the project to switch to. Use '-' to go back to the previous working directory.

    Raises:
        SeretoValueError: If the project ID is invalid.
        SeretoPathError: If the project's path does not exist.
    """
    project: Project = get_current_context().obj
    wd = WorkingDir()

    # `cd -` ... Go back to the previous working directory
    if project_id == "-":
        wd.go_back()
        return

    # Check if the project's location exists
    # TODO: Should we iterate over all projects and read the config to get the correct path?
    project_path = project.settings.projects_path / project_id
    if not is_project_dir(project_path):
        raise SeretoPathError(f"project '{project_id}' does not exist. Use 'ls' to list all projects")

    # Change the current working directory to the new location
    wd.change(project_path)

repl_exit()

Exit from the Read-Eval-Print Loop (REPL).

Source code in sereto/cli/commands.py
138
139
140
141
@click.command(name="exit")
def repl_exit() -> None:
    """Exit from the Read-Eval-Print Loop (REPL)."""
    click_repl_exit()

repl_toggle_debug()

Toggle the debug mode.

Source code in sereto/cli/commands.py
144
145
146
147
148
149
150
@click.command(name="debug")
def repl_toggle_debug() -> None:
    """Toggle the debug mode."""
    if os.environ.get("DEBUG", "0") == "1":
        del os.environ["DEBUG"]
    else:
        os.environ["DEBUG"] = "1"

sereto_ls(settings)

List all projects in the user's projects directory.

Print a table with the details to the console.

Parameters:

Name Type Description Default
settings Settings

The Settings object.

required
Source code in sereto/cli/commands.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@validate_call
def sereto_ls(settings: Settings) -> None:
    """List all projects in the user's projects directory.

    Print a table with the details to the console.

    Args:
        settings: The Settings object.
    """
    project_paths: list[Path] = [d for d in settings.projects_path.iterdir() if is_project_dir(d)]
    table = Table("ID", "Name", "Location", title="Projects", box=box.MINIMAL)

    for dir in project_paths:
        try:
            project_name = Project.load_from(dir).config.last_config.name
        except (RuntimeError, SeretoValueError):
            project_name = "n/a"

        table.add_row(dir.name, project_name, f"[link {dir.as_uri()}]{dir}")

    Console().print(table, justify="center")

sereto_repl(cli)

Start an interactive Read-Eval-Print Loop (REPL) session.

Parameters:

Name Type Description Default
cli Group

The main CLI group.

required
Source code in sereto/cli/commands.py
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
def sereto_repl(cli: Group) -> None:
    """Start an interactive Read-Eval-Print Loop (REPL) session.

    Args:
        cli: The main CLI group.
    """
    Console().log(r"""
  ____       ____     _____
 / ___|  ___|  _ \ __|_   _|__
 \___ \ / _ \ |_) / _ \| |/ _ \
  ___) |  __/  _ <  __/| | (_) |
 |____/ \___|_| \_\___||_|\___/

Welcome to [blue]SeReTo Interactive Mode[/blue]!
-------------------------------------------
Type 'exit' or press 'Ctrl+D' to quit.
Use 'cd <ID>' to change the active project.
Type '-h'/'--help' to see available commands.
    """)

    # Add REPL specific commands
    cli.add_command(repl_cd)
    cli.add_command(repl_exit)
    cli.add_command(repl_toggle_debug)

    # Define the prompt style
    prompt_style = Style.from_dict(
        {
            "debug": "red",
            "sereto": "#02a0f0 bold",
            "bracket": "#8a8a8a",
            "project_id": "#00ff00",
            "gt": "#8a8a8a bold",
        }
    )

    prompt_kwargs = {
        "message": _get_repl_prompt,
        "history": FileHistory(Path(get_app_dir(app_name="sereto")) / ".sereto_history"),
        "style": prompt_style,
    }
    repl(click.get_current_context(), prompt_kwargs=prompt_kwargs)