try-cli 1.9.3 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +14 -4
- data/VERSION +1 -1
- data/lib/tui.rb +2 -2
- data/try.rb +79 -10
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2886940b1f4b531eac99e082e57083e26e0aedc60f073355868870fc364118c7
|
|
4
|
+
data.tar.gz: 64712394de4b5d48535ce8dc31abb2f50da33e446aed3d01ec465640191c6b0e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a13726660cb156fde7e39a351b439d3a64870fcc637a4fe4189c54a0b3a2ad417f3685ec9a010ed65b7b1f254ee26b46e6b20f1c25ff8ca1caf5ae0d1b1852f1
|
|
7
|
+
data.tar.gz: 448bb7c503410c82052e93ce8dc6b22922be70c80dd1a8c0a9f8c7e84e7f50bc0efa4d435c8c8bec4c0578cb8969185cc624fcd3169e9421eead312aa84f4223
|
data/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Ever find yourself with 50 directories named `test`, `test2`, `new-test`, `actua
|
|
|
10
10
|
|
|
11
11
|
**try** is here for your beautifully chaotic mind.
|
|
12
12
|
|
|
13
|
-
# What it does
|
|
13
|
+
# What it does
|
|
14
14
|
|
|
15
15
|

|
|
16
16
|
|
|
@@ -155,6 +155,10 @@ try clone https://github.com/tobi/try.git my-fork
|
|
|
155
155
|
# Shorthand syntax (no need to type 'clone')
|
|
156
156
|
try https://github.com/tobi/try.git
|
|
157
157
|
# Creates: 2025-08-27-tobi-try
|
|
158
|
+
|
|
159
|
+
# Paste a GitHub pull request URL to clone and check out that PR
|
|
160
|
+
try https://github.com/tobi/try/pull/124
|
|
161
|
+
# Creates: 2025-08-27-tobi-try
|
|
158
162
|
```
|
|
159
163
|
|
|
160
164
|
Supported git URI formats:
|
|
@@ -162,8 +166,14 @@ Supported git URI formats:
|
|
|
162
166
|
- `git@github.com:user/repo.git` (SSH GitHub)
|
|
163
167
|
- `https://gitlab.com/user/repo.git` (GitLab)
|
|
164
168
|
- `git@host.com:user/repo.git` (SSH other hosts)
|
|
169
|
+
- `ssh://git@host.com:port/user/repo.git` (SSH other hosts with custom port)
|
|
170
|
+
- `user@host:path/to/repo.git` (nested SCP-style SSH URLs)
|
|
171
|
+
- `https://github.com/user/repo/pull/123` (GitHub pull requests)
|
|
165
172
|
|
|
166
|
-
|
|
173
|
+
A GitHub pull request URL clones the main repository, fetches the PR ref, and
|
|
174
|
+
checks it out in detached HEAD state. The directory name is based on the main
|
|
175
|
+
repository URL, not the `/pull/<number>` suffix. The `.git` suffix is
|
|
176
|
+
automatically removed from URLs when generating directory names.
|
|
167
177
|
|
|
168
178
|
### Keyboard Shortcuts
|
|
169
179
|
|
|
@@ -199,9 +209,9 @@ nix run github:tobi/try init ~/my-tries
|
|
|
199
209
|
```nix
|
|
200
210
|
{
|
|
201
211
|
inputs.try.url = "github:tobi/try";
|
|
202
|
-
|
|
212
|
+
|
|
203
213
|
imports = [ inputs.try.homeManagerModules.default ];
|
|
204
|
-
|
|
214
|
+
|
|
205
215
|
programs.try = {
|
|
206
216
|
enable = true;
|
|
207
217
|
path = "~/experiments"; # optional, defaults to ~/src/tries
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.10.0
|
data/lib/tui.rb
CHANGED
|
@@ -90,14 +90,14 @@ module Tui
|
|
|
90
90
|
module Palette
|
|
91
91
|
HEADER = ANSI.sgr(1, "38;5;114")
|
|
92
92
|
ACCENT = ANSI.sgr(1, "38;5;214")
|
|
93
|
-
HIGHLIGHT = "\e[
|
|
93
|
+
HIGHLIGHT = "\e[1m" # Bold only, no fixed color: readable on any theme
|
|
94
94
|
MUTED = ANSI.fg(245)
|
|
95
95
|
MATCH = ANSI.sgr(1, "38;5;226")
|
|
96
96
|
INPUT_HINT = ANSI.fg(244)
|
|
97
97
|
INPUT_CURSOR_ON = "\e[7m"
|
|
98
98
|
INPUT_CURSOR_OFF = "\e[27m"
|
|
99
99
|
|
|
100
|
-
SELECTED_BG =
|
|
100
|
+
SELECTED_BG = "\e[7m" # reverse video: adapts to terminal's own colors, not just dark themes
|
|
101
101
|
DANGER_BG = ANSI.bg(52)
|
|
102
102
|
end
|
|
103
103
|
|
data/try.rb
CHANGED
|
@@ -77,7 +77,7 @@ class TrySelector
|
|
|
77
77
|
STDERR.print("#{Tui::ANSI::ALT_SCREEN_ON}#{Tui::ANSI.set_title("try")}#{Tui::ANSI::CURSOR_BLINK}")
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
@old_winch_handler = Signal.trap('WINCH') { @needs_redraw = true }
|
|
80
|
+
@old_winch_handler = Signal.trap('WINCH') { @needs_redraw = true } if Signal.list.key?('WINCH')
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
def restore_terminal
|
|
@@ -955,7 +955,7 @@ end
|
|
|
955
955
|
# Main execution with OptionParser subcommands
|
|
956
956
|
if __FILE__ == $0
|
|
957
957
|
|
|
958
|
-
VERSION = "1.
|
|
958
|
+
VERSION = "1.10.0"
|
|
959
959
|
|
|
960
960
|
def print_global_help
|
|
961
961
|
text = <<~HELP
|
|
@@ -984,6 +984,7 @@ if __FILE__ == $0
|
|
|
984
984
|
try Open interactive selector
|
|
985
985
|
try project Selector with initial filter
|
|
986
986
|
try clone https://github.com/user/repo
|
|
987
|
+
try https://github.com/user/repo/pull/123
|
|
987
988
|
try worktree feature-branch
|
|
988
989
|
|
|
989
990
|
Manual mode (without alias):
|
|
@@ -1053,19 +1054,44 @@ if __FILE__ == $0
|
|
|
1053
1054
|
# https://gitlab.com/user/repo or other git hosts
|
|
1054
1055
|
host, user, repo = $1, $2, $3
|
|
1055
1056
|
return { user: user, repo: repo, host: host }
|
|
1056
|
-
elsif uri.match(%r{^git@([^:]+):([^/]+)/(
|
|
1057
|
-
# git@host:user/repo
|
|
1058
|
-
host, user,
|
|
1057
|
+
elsif uri.match(%r{^git@([^:]+):([^/]+)/(.+)})
|
|
1058
|
+
# git@host:user/path/to/repo
|
|
1059
|
+
host, user, path = $1, $2, $3
|
|
1060
|
+
repo = File.basename(path)
|
|
1061
|
+
return { user: user, repo: repo, host: host }
|
|
1062
|
+
elsif uri.match(%r{^ssh://[^@/]+@([^/]+)/([^/]+)/(.+)})
|
|
1063
|
+
# ssh://user@host:port/user/repo
|
|
1064
|
+
host, user, path = $1, $2, $3
|
|
1065
|
+
repo = File.basename(path)
|
|
1066
|
+
return { user: user, repo: repo, host: host }
|
|
1067
|
+
elsif uri.match(%r{^([^@/:]+)@([^:]+):(.+)})
|
|
1068
|
+
# SCP-style SSH: user@host:path/to/repo
|
|
1069
|
+
user, host, path = $1, $2, $3
|
|
1070
|
+
repo = File.basename(path)
|
|
1059
1071
|
return { user: user, repo: repo, host: host }
|
|
1060
1072
|
else
|
|
1061
1073
|
return nil
|
|
1062
1074
|
end
|
|
1063
1075
|
end
|
|
1064
1076
|
|
|
1077
|
+
def github_pr_details(uri)
|
|
1078
|
+
return nil unless uri
|
|
1079
|
+
|
|
1080
|
+
match = uri.match(%r{\Ahttps?://(?:www\.)?github\.com/([^/]+)/([^/]+)/pull/(\d+)/?\z})
|
|
1081
|
+
return nil unless match
|
|
1082
|
+
|
|
1083
|
+
{
|
|
1084
|
+
user: match[1],
|
|
1085
|
+
repo: match[2].sub(/\.git\z/, ''),
|
|
1086
|
+
pr_id: match[3],
|
|
1087
|
+
git_uri: "https://github.com/#{match[1]}/#{match[2].sub(/\.git\z/, '')}.git"
|
|
1088
|
+
}
|
|
1089
|
+
end
|
|
1090
|
+
|
|
1065
1091
|
def generate_clone_directory_name(git_uri, custom_name = nil)
|
|
1066
1092
|
return custom_name if custom_name && !custom_name.empty?
|
|
1067
1093
|
|
|
1068
|
-
parsed = parse_git_uri(git_uri)
|
|
1094
|
+
parsed = github_pr_details(git_uri) || parse_git_uri(git_uri)
|
|
1069
1095
|
return nil unless parsed
|
|
1070
1096
|
|
|
1071
1097
|
date_prefix = Time.now.strftime("%Y-%m-%d")
|
|
@@ -1166,7 +1192,12 @@ if __FILE__ == $0
|
|
|
1166
1192
|
exit 1
|
|
1167
1193
|
end
|
|
1168
1194
|
|
|
1169
|
-
|
|
1195
|
+
path = File.join(tries_path, dir_name)
|
|
1196
|
+
if pr = github_pr_details(git_uri)
|
|
1197
|
+
script_clone_pr(path, pr[:git_uri], pr[:pr_id])
|
|
1198
|
+
else
|
|
1199
|
+
script_clone(path, git_uri)
|
|
1200
|
+
end
|
|
1170
1201
|
end
|
|
1171
1202
|
|
|
1172
1203
|
def cmd_init!(args, tries_path)
|
|
@@ -1355,7 +1386,11 @@ if __FILE__ == $0
|
|
|
1355
1386
|
exit 1
|
|
1356
1387
|
end
|
|
1357
1388
|
full_path = File.join(tries_path, dir_name)
|
|
1358
|
-
|
|
1389
|
+
if pr = github_pr_details(git_uri)
|
|
1390
|
+
return script_clone_pr(full_path, pr[:git_uri], pr[:pr_id])
|
|
1391
|
+
else
|
|
1392
|
+
return script_clone(full_path, git_uri)
|
|
1393
|
+
end
|
|
1359
1394
|
end
|
|
1360
1395
|
|
|
1361
1396
|
# Regular interactive selector
|
|
@@ -1408,8 +1443,31 @@ if __FILE__ == $0
|
|
|
1408
1443
|
end
|
|
1409
1444
|
end
|
|
1410
1445
|
|
|
1446
|
+
# Emit best-effort terminal manager rename commands. Keep these as the final
|
|
1447
|
+
# commands so a missing or broken optional CLI never prevents the directory
|
|
1448
|
+
# change from completing.
|
|
1449
|
+
def terminal_rename_commands(path)
|
|
1450
|
+
name = File.basename(path).sub(/\A\d{4}-\d{2}-\d{2}-/, '')
|
|
1451
|
+
label = "try: #{name}"
|
|
1452
|
+
|
|
1453
|
+
if ENV['HERDR_ENV'] == '1' && ENV['HERDR_PANE_ID'] && !ENV['HERDR_PANE_ID'].empty?
|
|
1454
|
+
commands = [
|
|
1455
|
+
"command -v herdr >/dev/null 2>&1 && herdr pane report-metadata #{q(ENV['HERDR_PANE_ID'])} --source try --title #{q(label)} >/dev/null 2>&1 || true"
|
|
1456
|
+
]
|
|
1457
|
+
if ENV['HERDR_PANE_ID'].match?(/:p1\z/) && ENV['HERDR_WORKSPACE_ID'] && !ENV['HERDR_WORKSPACE_ID'].empty?
|
|
1458
|
+
commands << "command -v herdr >/dev/null 2>&1 && herdr workspace rename #{q(ENV['HERDR_WORKSPACE_ID'])} #{q(label)} >/dev/null 2>&1 || true"
|
|
1459
|
+
end
|
|
1460
|
+
commands
|
|
1461
|
+
elsif (ENV['CMUX_SOCKET_PATH'] && !ENV['CMUX_SOCKET_PATH'].empty?) ||
|
|
1462
|
+
(ENV['CMUX_BUNDLE_ID'] && !ENV['CMUX_BUNDLE_ID'].empty?)
|
|
1463
|
+
["command -v cmux >/dev/null 2>&1 && cmux rename-tab #{q(label)} >/dev/null 2>&1 || true"]
|
|
1464
|
+
else
|
|
1465
|
+
[]
|
|
1466
|
+
end
|
|
1467
|
+
end
|
|
1468
|
+
|
|
1411
1469
|
def script_cd(path)
|
|
1412
|
-
["touch #{q(path)}", "echo #{q(path)}", "cd #{q(path)}"]
|
|
1470
|
+
["touch #{q(path)}", "echo #{q(path)}", "cd #{q(path)}"] + terminal_rename_commands(path)
|
|
1413
1471
|
end
|
|
1414
1472
|
|
|
1415
1473
|
def script_mkdir_cd(path)
|
|
@@ -1420,6 +1478,17 @@ if __FILE__ == $0
|
|
|
1420
1478
|
["mkdir -p #{q(path)}", "echo #{q("Using git clone to create this trial from #{uri}.")}", "git clone '#{uri}' #{q(path)}"] + script_cd(path)
|
|
1421
1479
|
end
|
|
1422
1480
|
|
|
1481
|
+
def script_clone_pr(path, uri, pr_id)
|
|
1482
|
+
ref = "pull/#{pr_id}/head"
|
|
1483
|
+
[
|
|
1484
|
+
"mkdir -p #{q(path)}",
|
|
1485
|
+
"echo #{q("Using git clone to create this trial from #{uri} PR ##{pr_id}.")}",
|
|
1486
|
+
"git clone #{q(uri)} #{q(path)}",
|
|
1487
|
+
"git -C #{q(path)} fetch origin #{q(ref)}",
|
|
1488
|
+
"git -C #{q(path)} checkout --detach FETCH_HEAD"
|
|
1489
|
+
] + script_cd(path)
|
|
1490
|
+
end
|
|
1491
|
+
|
|
1423
1492
|
def script_worktree(path, repo = nil)
|
|
1424
1493
|
r = repo ? q(repo) : nil
|
|
1425
1494
|
worktree_cmd = if r
|
|
@@ -1463,7 +1532,7 @@ if __FILE__ == $0
|
|
|
1463
1532
|
"mv #{q(old_name)} #{q(new_name)}",
|
|
1464
1533
|
"echo #{q(new_path)}",
|
|
1465
1534
|
"cd #{q(new_path)}"
|
|
1466
|
-
]
|
|
1535
|
+
] + terminal_rename_commands(new_path)
|
|
1467
1536
|
end
|
|
1468
1537
|
|
|
1469
1538
|
# Return a unique directory name under tries_path by appending -2, -3, ... if needed
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: try-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tobi Lutke
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-08-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A CLI tool for managing experimental projects. Creates dated directories
|
|
14
14
|
for your tries, with fuzzy search and easy navigation.
|