copa-cli 0.3.0__tar.gz → 0.3.1__tar.gz

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.
Files changed (36) hide show
  1. {copa_cli-0.3.0/copa_cli.egg-info → copa_cli-0.3.1}/PKG-INFO +1 -1
  2. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/cli_internal.py +6 -6
  3. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/copa.zsh +8 -8
  4. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/fzf.py +5 -6
  5. {copa_cli-0.3.0 → copa_cli-0.3.1/copa_cli.egg-info}/PKG-INFO +1 -1
  6. {copa_cli-0.3.0 → copa_cli-0.3.1}/pyproject.toml +1 -1
  7. {copa_cli-0.3.0 → copa_cli-0.3.1}/tests/test_modal.py +10 -5
  8. {copa_cli-0.3.0 → copa_cli-0.3.1}/LICENSE +0 -0
  9. {copa_cli-0.3.0 → copa_cli-0.3.1}/README.md +0 -0
  10. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/__init__.py +0 -0
  11. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/__main__.py +0 -0
  12. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/cli.py +0 -0
  13. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/cli_common.py +0 -0
  14. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/cli_llm.py +0 -0
  15. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/cli_share.py +0 -0
  16. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/config.py +0 -0
  17. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/db.py +0 -0
  18. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/evolve.py +0 -0
  19. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/history.py +0 -0
  20. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/llm.py +0 -0
  21. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/mcp_server.py +0 -0
  22. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/models.py +0 -0
  23. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/scanner.py +0 -0
  24. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/scoring.py +0 -0
  25. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa/sharing.py +0 -0
  26. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa_cli.egg-info/SOURCES.txt +0 -0
  27. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa_cli.egg-info/dependency_links.txt +0 -0
  28. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa_cli.egg-info/entry_points.txt +0 -0
  29. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa_cli.egg-info/requires.txt +0 -0
  30. {copa_cli-0.3.0 → copa_cli-0.3.1}/copa_cli.egg-info/top_level.txt +0 -0
  31. {copa_cli-0.3.0 → copa_cli-0.3.1}/setup.cfg +0 -0
  32. {copa_cli-0.3.0 → copa_cli-0.3.1}/tests/test_cli_and_sharing.py +0 -0
  33. {copa_cli-0.3.0 → copa_cli-0.3.1}/tests/test_db.py +0 -0
  34. {copa_cli-0.3.0 → copa_cli-0.3.1}/tests/test_fzf.py +0 -0
  35. {copa_cli-0.3.0 → copa_cli-0.3.1}/tests/test_models.py +0 -0
  36. {copa_cli-0.3.0 → copa_cli-0.3.1}/tests/test_scanner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copa-cli
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Command Palette — smart command tracking, ranking, and sharing for your shell
5
5
  Author: Mark Stanford
6
6
  License-Expression: MIT
@@ -175,20 +175,20 @@ def set_flags(cmd_id: int):
175
175
 
176
176
  @click.command("_list-groups", hidden=True)
177
177
  def list_groups():
178
- """Output group names for fzf group picker."""
178
+ """Output group names for fzf group picker (delimited for --with-nth)."""
179
179
  db = get_db()
180
- click.echo("(all)")
180
+ click.echo("0┃(all)")
181
181
  for g in db.get_groups():
182
- click.echo(g)
182
+ click.echo(f"0┃{g}┃")
183
183
 
184
184
 
185
185
  @click.command("_list-groups-for-assign", hidden=True)
186
186
  def list_groups_for_assign():
187
- """Output group names for group-assign modal."""
187
+ """Output group names for group-assign modal (delimited for --with-nth)."""
188
188
  db = get_db()
189
- click.echo("(none)")
189
+ click.echo("0┃(none)")
190
190
  for g in db.get_groups():
191
- click.echo(g)
191
+ click.echo(f"0┃{g}┃")
192
192
 
193
193
 
194
194
  @click.command("_set-group-direct", hidden=True)
@@ -73,10 +73,10 @@ _copa_fzf_widget() {
73
73
  --expect "$_COPA_EXPECT" \
74
74
  --bind "${_COPA_DESCRIBE_KEY}:execute($copa_bin describe {1})+refresh-preview" \
75
75
  --bind "${_COPA_FLAGS_KEY}:execute($copa_bin _set-flags {1})+reload($copa_bin fzf-list)+refresh-preview" \
76
- --bind "${_COPA_FILTER_GROUP_KEY}:reload($copa_bin _list-groups)+change-prompt(scope> )+clear-query" \
76
+ --bind "${_COPA_FILTER_GROUP_KEY}:reload($copa_bin _list-groups)+change-prompt(scope> )+clear-query+hide-preview" \
77
77
  --bind "${_COPA_GROUP_KEY}:transform:
78
78
  echo {1} > ${_copa_modal_file};
79
- echo \"reload(${copa_bin} _list-groups-for-assign)+change-prompt(group> )+clear-query\"" \
79
+ echo \"reload(${copa_bin} _list-groups-for-assign)+change-prompt(group> )+clear-query+hide-preview\"" \
80
80
  --bind "${_COPA_CYCLE_GROUP_KEY}:transform:
81
81
  cur_group='(all)';
82
82
  if [[ \$FZF_PROMPT =~ 'copa \\[(.+)\\]> ' ]]; then
@@ -99,23 +99,23 @@ _copa_fzf_widget() {
99
99
  --bind "${_COPA_TOGGLE_HEADER_KEY}:toggle-header" \
100
100
  --bind 'enter:transform:
101
101
  if [[ $FZF_PROMPT == "scope> " ]]; then
102
- selected={};
102
+ selected={2};
103
103
  if [[ $selected == "(all)" ]]; then
104
- echo "reload('"$copa_bin"' fzf-list --mode all)+change-prompt(copa> )+clear-query"
104
+ echo "reload('"$copa_bin"' fzf-list --mode all)+change-prompt(copa> )+clear-query+show-preview"
105
105
  else
106
- echo "reload('"$copa_bin"' fzf-list --mode group --group $selected)+change-prompt(copa [$selected]> )+clear-query"
106
+ echo "reload('"$copa_bin"' fzf-list --mode group --group $selected)+change-prompt(copa [$selected]> )+clear-query+show-preview"
107
107
  fi
108
108
  elif [[ $FZF_PROMPT == "group> " ]]; then
109
109
  cmd_id=$(cat '"${_copa_modal_file}"');
110
- selected={};
110
+ selected={2};
111
111
  '"$copa_bin"' _set-group-direct $cmd_id $selected;
112
- echo "reload('"$copa_bin"' fzf-list)+change-prompt(copa> )+clear-query"
112
+ echo "reload('"$copa_bin"' fzf-list)+change-prompt(copa> )+clear-query+show-preview"
113
113
  else
114
114
  echo "accept"
115
115
  fi' \
116
116
  --bind 'esc:transform:
117
117
  if [[ $FZF_PROMPT == "scope> " || $FZF_PROMPT == "group> " ]]; then
118
- echo "reload('"$copa_bin"' fzf-list)+change-prompt(copa> )+clear-query"
118
+ echo "reload('"$copa_bin"' fzf-list)+change-prompt(copa> )+clear-query+show-preview"
119
119
  else
120
120
  echo "abort"
121
121
  fi' \
@@ -37,7 +37,7 @@ def format_lines(commands: list[Command]) -> list[str]:
37
37
  return []
38
38
 
39
39
  # Compute column widths from the full list
40
- max_cmd = min(max(len(c.command) for c in commands), 60)
40
+ max_cmd = max(len(c.command) for c in commands)
41
41
  max_grp = max(
42
42
  (len(f"[{c.group_name}]") for c in commands if c.group_name),
43
43
  default=0,
@@ -48,11 +48,10 @@ def format_lines(commands: list[Command]) -> list[str]:
48
48
  # Field 1: hidden ID
49
49
  id_field = f"{cmd.id:>5}"
50
50
 
51
- # Field 2: command text, padded for column alignment
52
- cmd_text = cmd.command
53
- if len(cmd_text) > 60:
54
- cmd_text = cmd_text[:57] + "..."
55
- cmd_field = f" {cmd_text:<{max_cmd}} "
51
+ # Field 2: command text full text, never truncated.
52
+ # fzf handles overflow with horizontal scrolling.
53
+ # Padding uses max_cmd for column alignment on shorter commands.
54
+ cmd_field = f" {cmd.command:<{max_cmd}} "
56
55
 
57
56
  # Field 3: metadata — pin indicator, group badge, frequency
58
57
  pin = f"{_YELLOW}*{_RESET} " if cmd.is_pinned else " "
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copa-cli
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Command Palette — smart command tracking, ranking, and sharing for your shell
5
5
  Author: Mark Stanford
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "copa-cli"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "Command Palette — smart command tracking, ranking, and sharing for your shell"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -27,7 +27,9 @@ class TestListGroupsForAssign:
27
27
  result = runner.invoke(cli, ["_list-groups-for-assign"])
28
28
  assert result.exit_code == 0
29
29
  lines = result.output.strip().split("\n")
30
- assert lines[0] == "(none)"
30
+ # Delimited format: 0┃(none)
31
+ assert "(none)" in lines[0]
32
+ assert "┃" in lines[0]
31
33
 
32
34
  def test_outputs_groups(self, tmp_path, monkeypatch):
33
35
  db = self._make_db(tmp_path, monkeypatch)
@@ -37,16 +39,19 @@ class TestListGroupsForAssign:
37
39
  result = runner.invoke(cli, ["_list-groups-for-assign"])
38
40
  assert result.exit_code == 0
39
41
  lines = result.output.strip().split("\n")
40
- assert lines[0] == "(none)"
41
- assert "alpha" in lines
42
- assert "beta" in lines
42
+ assert "(none)" in lines[0]
43
+ group_names = [line.split("")[1] for line in lines]
44
+ assert "alpha" in group_names
45
+ assert "beta" in group_names
43
46
 
44
47
  def test_no_groups_just_none(self, tmp_path, monkeypatch):
45
48
  self._make_db(tmp_path, monkeypatch)
46
49
  runner = CliRunner()
47
50
  result = runner.invoke(cli, ["_list-groups-for-assign"])
48
51
  assert result.exit_code == 0
49
- assert result.output.strip() == "(none)"
52
+ lines = result.output.strip().split("\n")
53
+ assert len(lines) == 1
54
+ assert "(none)" in lines[0]
50
55
 
51
56
 
52
57
  class TestSetGroupDirect:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes