Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,13 @@ cd ~/Documents
zmk init
```

Follow the instructions it gives you. If you already have a ZMK config repo, you can enter its URL when prompted, for example:
Follow the instructions it gives you. If you already have a ZMK config repo, select "Clone an existing repo" and enter the repo's URL, for example:

```
Repository URL: https://github.com/myusername/zmk-config
```

Otherwise, leave this first prompt blank and press <kbd>Enter</kbd>, and it will walk you through creating a new repo.
Otherwise, select "Create a new ZMK config repo" and it will walk you through creating a new repo.

Once you finish following all the instructions, you will have a copy of the repo stored on your computer. All `zmk` commands will run on this repo (unless the working directory is inside a different repo). If you ever forget where the repo is located, you can run `zmk cd` to find it.

Expand Down
43 changes: 27 additions & 16 deletions zmk/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from ..build import BuildMatrix
from ..config import Config, get_config, set_context_repo
from ..exceptions import FatalError
from ..menu import show_menu
from ..prompt import UrlPrompt
from ..repo import Repo, find_containing_repo, is_repo
from .keyboard.add import keyboard_add
Expand Down Expand Up @@ -139,41 +140,51 @@ def _check_for_existing_repo(cfg: Config):

if cfg.home_path and is_repo(cfg.home_path):
rich.print(f'You already have a ZMK config repo at "{cfg.home_path}".')
if not Confirm.ask("Create a new repo?", default=False):
if not Confirm.ask("Initialize a new repo?", default=False):
raise typer.Exit()

rich.print()

def _get_repo_url():
rich.print(
"If you already have a ZMK config repo, enter its URL here. "
"Otherwise, leave this blank to create a new repo."
)

url = Prompt.ask("Repository URL")
if url:
return url
_CREATE_NEW_REPO = "Create a new ZMK config repo"
_CLONE_REPO = "Clone an existing repo"


def _get_repo_url():
console = rich.get_console()

response = show_menu(title=None, items=[_CREATE_NEW_REPO, _CLONE_REPO])

if response == _CLONE_REPO:
console.print("Enter the URL of your ZMK config repo.")
return UrlPrompt.ask("Repository URL")

console.print(
"\n"
"To create your ZMK config repo, we will open a GitHub page in your "
"To create your ZMK config repo, we will open a GitHub page in your web "
"browser to create a repo from a template. Log in to GitHub if necessary, "
"then click the green [green]Create repository[/green] button. "
"then click the green [green]Create repository[/green] button."
"\n\n"
"Once it finishes creating the repo, Click the green [green]<> Code[/green] "
"button, then copy the HTTPS URL and paste it here. "
"Press [green]Enter[/green] to when you're ready.",
width=TEXT_WIDTH,
)
input()
webbrowser.open(TEMPLATE_URL)

url = UrlPrompt.ask("Repository URL")
return url
if not webbrowser.open(TEMPLATE_URL):
console.print(
"[yellow]Failed to open a browser. Please open the following link in a web browser:"
)
console.print("")
console.print(TEMPLATE_URL)
console.print("")

return UrlPrompt.ask("Repository URL")


def _get_directory_name(url: str):
default = urlparse(url).path.split("/")[-1]
# Default name is the last path component of the URL without any ".git" suffix
default = urlparse(url).path.split("/")[-1].removesuffix(".git")

return Prompt.ask("Enter a directory name", default=default)

Expand Down
31 changes: 18 additions & 13 deletions zmk/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

from collections.abc import Callable, Iterable
from contextlib import contextmanager
from typing import Any, Generic, TypeVar
from typing import Generic, TypeVar

import rich
from rich.console import Console
from rich.console import Console, RenderableType
from rich.highlighter import Highlighter
from rich.style import Style
from rich.text import Text
Expand Down Expand Up @@ -50,7 +50,7 @@ class TerminalMenu(Generic[T], Highlighter):
}
)

title: Any
title: RenderableType | None
items: list[T]
default_index: int

Expand All @@ -67,7 +67,7 @@ class TerminalMenu(Generic[T], Highlighter):

def __init__(
self,
title: Any,
title: RenderableType | None,
items: Iterable[T],
*,
default_index=0,
Expand Down Expand Up @@ -101,9 +101,13 @@ def __init__(
self._focus_index = 0
self._scroll_index = 0

title_lines = self.console.render_lines(self.title, pad=False)
self._num_title_lines = len(title_lines)
self._last_title_line_len = 1 + sum(s.cell_length for s in title_lines[-1])
if self.title:
title_lines = self.console.render_lines(self.title, pad=False)
self._num_title_lines = len(title_lines)
self._last_title_line_len = 1 + sum(s.cell_length for s in title_lines[-1])
else:
self._num_title_lines = 0
self._last_title_line_len = 0

if self._get_display_count() == self._max_items_per_page:
self._top_row = 1
Expand Down Expand Up @@ -202,11 +206,12 @@ def _apply_filter(self):
self._clamp_focus_index()

def _print_menu(self):
self.console.print(
f"[title]{self.title}[/title] [filter]{self._filter_text}[/filter]",
justify="left",
highlight=False,
)
if self.title:
self.console.print(
f"[title]{self.title}[/title] [filter]{self._filter_text}[/filter]",
justify="left",
highlight=False,
)

display_count = self._get_display_count()

Expand Down Expand Up @@ -404,7 +409,7 @@ def _erase_controls(self):


def show_menu(
title: str,
title: RenderableType | None,
items: Iterable[T],
*,
default_index=0,
Expand Down