Skip to content
Open
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 AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
- `try worktree dir [name]`: Same as above but explicit CLI, useful without the shell wrapper.
- `try clone <git-uri> [name]`: Clones into the root. Default name is `YYYY-MM-DD-user-repo` (strips `.git`). Optional `name` overrides.
- Flags: `--path PATH` (for `cd`/`clone`) overrides the root for that call; `--help` prints global help.
- Environment: `TRY_PATH` sets the default root when not using `--path`. `TRY_PROJECTS` sets the graduate destination (default: parent of `TRY_PATH`).
- UI keys: `↑/↓` or `Ctrl-P/N` navigate, `Enter` select, `Backspace` delete char, `Ctrl-D` delete dir (requires typing `YES`), `Ctrl-G` graduate (promote try to project), `Ctrl-R` rename, `ESC` cancel.
- Environment: `TRY_PATH` sets the default root when not using `--path`. `TRY_PROJECTS` sets one or more graduate parents, separated by `:` (default: parent of `TRY_PATH`).
- UI keys: `↑/↓` or `Ctrl-P/N` navigate, `Enter` select, `Backspace` delete char, `Ctrl-D` delete dir (requires typing `YES`), `Ctrl-G` graduate (promote try to project), `Ctrl-R` rename, `ESC` cancel. In the graduation dialog, `↑/↓` cycle configured parents.

### Shorthands and Worktrees
- `try .`: Creates a new date-prefixed directory using the current working directory’s basename. If inside a Git repo, a detached worktree is added; otherwise this is a plain directory.
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ automatically removed from URLs when generating directory names.
- `Enter` - Select or create
- `Backspace` - Delete character
- `Ctrl-D` - Delete directory (with confirmation)
- `Ctrl-G` - Graduate a try into a project
- `ESC` - Cancel
- Just type to filter

Expand All @@ -206,7 +207,11 @@ Set `TRY_PATH` to change where experiments are stored:
export TRY_PATH=~/code/sketches
```

Default: `~/src/tries`
`TRY_PROJECTS` optionally sets colon-separated graduation parent directories,
for example `$HOME/src/projects:$HOME/src/client-work`. It defaults to the
parent of `TRY_PATH`.

Default `TRY_PATH`: `~/src/tries`

## Nix

Expand Down
3 changes: 3 additions & 0 deletions spec/command_line.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ When `HERDR_ENV=1` and `HERDR_PANE_ID` are present, the script includes a guarde
| Variable | Description |
|----------|-------------|
| `HOME` | Used to resolve default tries path (`$HOME/src/tries`) |
| `TRY_PATH` | Overrides the tries directory |
| `TRY_PROJECTS` | One or more graduation parent directories, separated by the platform path separator |
| `SHELL` | Used by `init` to detect shell type |
| `NO_COLOR` | If set, disables colors (equivalent to `--no-colors`) |
| `HERDR_ENV`, `HERDR_PANE_ID`, `HERDR_WORKSPACE_ID` | Identify the current Herdr panel and workspace for renaming |
Expand All @@ -202,6 +204,7 @@ When `HERDR_ENV=1` and `HERDR_PANE_ID` are present, the script includes a guarde
- **Tries directory**: `~/src/tries`
- **Date format**: `YYYY-MM-DD`
- **Directory naming**: `YYYY-MM-DD-<name>`
- **Graduation parent**: first `TRY_PROJECTS` entry, or the parent of `TRY_PATH`

## Color Output

Expand Down
50 changes: 50 additions & 0 deletions spec/graduate_spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Graduation Specification

`Ctrl-G` opens a confirmation dialog for promoting the selected try to a
permanent project directory.

## Destination defaults

The project name is the try name with a leading `YYYY-MM-DD-` removed. The
default destination is:

1. the first path in `TRY_PROJECTS`, when it is set;
2. otherwise the parent directory of `TRY_PATH`.

`TRY_PROJECTS` may contain one or more absolute or `~`-relative parent paths,
separated by the platform path separator (`:` on Unix-like systems). Existing
single-path configurations remain valid. Parent paths are expanded and empty
entries are ignored.

## Graduation dialog

The dialog shows the destination path in an editable input field. Paths
inside the user's home directory are displayed with a `~` prefix when
possible, while the actual expanded path is used for graduation.

- Left/right arrows and the line-editing keys move and edit the destination.
- With multiple configured parents, Up/Down arrows cycle through them.
- Cycling parents preserves the current project basename, including a basename
manually typed into the destination field.
- Parent selection wraps at the beginning and end of the configured list.
- Enter confirms; Esc or Ctrl-C cancels.

When multiple parents are configured, the dialog lists every parent in a
centered, aligned block whose path columns line up with the destination field.
The shared directory prefix is dimmed and the
non-shared suffix is bold for each entry; the active entry is marked with `→`.
Below the list, contextual help shows bold `↑↓` and `←→` icons with the labels
`select parent, edit`. Enter/Esc confirmation help is shown separately in the
footer. The destination parent must already exist and the complete destination
must not already exist.

## Result

On confirmation, the shell script:

1. moves the try to the selected destination;
2. leaves a symlink at the original try path;
3. prints a graduation message; and
4. changes the shell to the new project directory.

Git worktrees use `git worktree move`; regular directories use `mv`.
69 changes: 68 additions & 1 deletion spec/tests/test_37_graduate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,71 @@ else
fail "Should strip YYYY-MM-DD- prefix from various dates" "year-end" "$output" "graduate"
fi

rm -rf "$GRAD_DIR" "$PROJ_DIR" "$NO_DATE_DIR" "$WT_DIR" "$EDIT_DIR" "$E2E_DIR" "$E2E_DEST" "$REG_DIR" "$MULTI_DIR"
# Test: Arrow keys cycle through a configured TRY_PROJECTS path list
PARENT_ONE=$(mktemp -d)
PARENT_TWO=$(mktemp -d)
LIST_DIR=$(mktemp -d)
mkdir -p "$LIST_DIR/2025-06-01-list-selection"
output=$(TRY_PROJECTS="$PARENT_ONE:$PARENT_TWO" try_run --path="$LIST_DIR" --and-keys='CTRL-G,DOWN,ENTER' exec 2>/dev/null)
if echo "$output" | grep -q "$PARENT_TWO/list-selection"; then
pass
else
fail "Down arrow should select the next configured graduation parent" "$PARENT_TWO/list-selection" "$output" "graduate"
fi

# Test: Graduation dialog lists all configured parents
ui_output=$(TRY_PROJECTS="$PARENT_ONE:$PARENT_TWO" try_run --path="$LIST_DIR" --and-keys='CTRL-G,ESC' exec 2>&1)
if echo "$ui_output" | grep -Fq "$(basename "$PARENT_ONE")" && echo "$ui_output" | grep -Fq "$(basename "$PARENT_TWO")"; then
pass
else
fail "Graduation dialog should show every configured parent" "$PARENT_ONE and $PARENT_TWO" "$ui_output" "graduate"
fi

# Test: The non-shared parent path portion is bold
if printf '%s' "$ui_output" | grep -q $'\033\\[1m'; then
pass
else
fail "Graduation dialog should bold the distinct parent path portion" "ANSI bold sequence" "$ui_output" "graduate"
fi

# Test: Contextual parent help uses bold arrow icons
if echo "$ui_output" | grep -q "↑↓.*select parent,.*←→.*edit"; then
pass
else
fail "Graduation dialog should show parent selection and editing help" "↑↓ select parent, ←→ edit" "$ui_output" "graduate"
fi

# Test: Old parent label and counter wording are gone
if echo "$ui_output" | grep -qE "Project parents|Parent [0-9]+/[0-9]+|↑/↓: Parent|←/→: Edit"; then
fail "Graduation dialog should not show the old parent label or counters" "no old parent wording" "$ui_output" "graduate"
else
pass
fi

# Test: Confirm/cancel help remains in the footer
if echo "$ui_output" | grep -q "Enter: Confirm.*Esc: Cancel"; then
pass
else
fail "Graduation dialog should keep confirm and cancel help" "Enter: Confirm Esc: Cancel" "$ui_output" "graduate"
fi

# Test: Paths under HOME use a compact ~ display form
HOME_TEST=$(mktemp -d)
HOME_LIST_DIR=$(mktemp -d)
mkdir -p "$HOME_TEST/products" "$HOME_TEST/js" "$HOME_LIST_DIR/2025-06-01-home-display"
home_ui=$(HOME="$HOME_TEST" TRY_PROJECTS="$HOME_TEST/products:$HOME_TEST/js" try_run --path="$HOME_LIST_DIR" --and-keys='CTRL-G,ESC' exec 2>&1)
if echo "$home_ui" | grep -Fq "products" && echo "$home_ui" | grep -Fq "js"; then
pass
else
fail "Graduation dialog should abbreviate HOME paths" "~/products and ~/js" "$home_ui" "graduate"
fi

# Test: Parent cycling preserves a manually edited project name
output=$(TRY_PROJECTS="$PARENT_ONE:$PARENT_TWO" try_run --path="$LIST_DIR" --and-keys="CTRL-G,CTRL-A,CTRL-K,TYPE=custom-name,DOWN,ENTER" exec 2>/dev/null)
if echo "$output" | grep -q "$PARENT_TWO/custom-name"; then
pass
else
fail "Changing parent should preserve the edited project name" "$PARENT_TWO/custom-name" "$output" "graduate"
fi

rm -rf "$GRAD_DIR" "$PROJ_DIR" "$NO_DATE_DIR" "$WT_DIR" "$EDIT_DIR" "$E2E_DIR" "$E2E_DEST" "$REG_DIR" "$MULTI_DIR" "$PARENT_ONE" "$PARENT_TWO" "$LIST_DIR" "$HOME_TEST" "$HOME_LIST_DIR"
2 changes: 2 additions & 0 deletions spec/tui_spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ Tokens are preserved intact - never split a `{b}...{/b}` pair.
| Enter | Select current entry |
| Esc / Ctrl-C | Cancel selection |
| Ctrl-D | Delete selected directory |
| Ctrl-G | Open the graduation dialog |

### Line Editing (in search input)
| Key | Action |
Expand Down Expand Up @@ -243,6 +244,7 @@ Selection can result in three action types:
| CD | Select existing directory | Navigate to directory |
| MKDIR | Select "[new]" entry | Create and navigate to new directory |
| DELETE | Press Ctrl-D on entry | Show delete confirmation dialog |
| GRADUATE | Press Ctrl-G | Move the selected try to a project directory and leave a symlink |
| CANCEL | Press Esc | Exit without action |

## New Directory Creation
Expand Down
Loading