copa-cli 0.7.0__tar.gz → 0.7.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 (37) hide show
  1. {copa_cli-0.7.0 → copa_cli-0.7.1}/PKG-INFO +3 -3
  2. {copa_cli-0.7.0 → copa_cli-0.7.1}/README.md +2 -2
  3. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/copa.zsh +31 -23
  4. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa_cli.egg-info/PKG-INFO +3 -3
  5. {copa_cli-0.7.0 → copa_cli-0.7.1}/pyproject.toml +1 -1
  6. {copa_cli-0.7.0 → copa_cli-0.7.1}/tests/test_modal.py +18 -23
  7. {copa_cli-0.7.0 → copa_cli-0.7.1}/LICENSE +0 -0
  8. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/__init__.py +0 -0
  9. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/__main__.py +0 -0
  10. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/cli.py +0 -0
  11. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/cli_common.py +0 -0
  12. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/cli_internal.py +0 -0
  13. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/cli_llm.py +0 -0
  14. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/cli_share.py +0 -0
  15. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/config.py +0 -0
  16. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/db.py +0 -0
  17. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/evolve.py +0 -0
  18. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/fzf.py +0 -0
  19. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/history.py +0 -0
  20. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/llm.py +0 -0
  21. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/mcp_server.py +0 -0
  22. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/models.py +0 -0
  23. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/scanner.py +0 -0
  24. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/scoring.py +0 -0
  25. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa/sharing.py +0 -0
  26. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa_cli.egg-info/SOURCES.txt +0 -0
  27. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa_cli.egg-info/dependency_links.txt +0 -0
  28. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa_cli.egg-info/entry_points.txt +0 -0
  29. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa_cli.egg-info/requires.txt +0 -0
  30. {copa_cli-0.7.0 → copa_cli-0.7.1}/copa_cli.egg-info/top_level.txt +0 -0
  31. {copa_cli-0.7.0 → copa_cli-0.7.1}/setup.cfg +0 -0
  32. {copa_cli-0.7.0 → copa_cli-0.7.1}/tests/test_cli_and_sharing.py +0 -0
  33. {copa_cli-0.7.0 → copa_cli-0.7.1}/tests/test_db.py +0 -0
  34. {copa_cli-0.7.0 → copa_cli-0.7.1}/tests/test_fzf.py +0 -0
  35. {copa_cli-0.7.0 → copa_cli-0.7.1}/tests/test_models.py +0 -0
  36. {copa_cli-0.7.0 → copa_cli-0.7.1}/tests/test_polish.py +0 -0
  37. {copa_cli-0.7.0 → copa_cli-0.7.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.7.0
3
+ Version: 0.7.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
@@ -285,8 +285,8 @@ $ git pu█sh origin main ← grey ghost text
285
285
  |-----|-------------------|---------------|
286
286
  | Type chars | Insert char, re-fetch suggestion | Insert char, fetch suggestion |
287
287
  | Backspace | Delete char, **latch** (suppress suggestions) | Delete char normally |
288
- | **Tab** | `tab_accept=1`: accept full suggestion. `tab_accept=2` (default): first Tab highlights suggestion (cyan), second Tab accepts | If latched: unlatch + re-fetch suggestion. Else: normal tab completion |
289
- | **Down** | Highlight suggestion (enter confirming state) | History navigation |
288
+ | **Tab** | `tab_accept=1`: accept full suggestion. `tab_accept=2` (default): open completion menu with suggestion highlighted at top, native completions below | If latched: unlatch + re-fetch suggestion. Else: normal tab completion |
289
+ | **Down** | Open completion menu with suggestion highlighted at top | History navigation |
290
290
  | **Right arrow** | Accept one word, re-fetch | Move cursor right |
291
291
  | Enter | Clear suggestion, execute | Execute |
292
292
  | Esc | Dismiss suggestion | Normal Esc |
@@ -255,8 +255,8 @@ $ git pu█sh origin main ← grey ghost text
255
255
  |-----|-------------------|---------------|
256
256
  | Type chars | Insert char, re-fetch suggestion | Insert char, fetch suggestion |
257
257
  | Backspace | Delete char, **latch** (suppress suggestions) | Delete char normally |
258
- | **Tab** | `tab_accept=1`: accept full suggestion. `tab_accept=2` (default): first Tab highlights suggestion (cyan), second Tab accepts | If latched: unlatch + re-fetch suggestion. Else: normal tab completion |
259
- | **Down** | Highlight suggestion (enter confirming state) | History navigation |
258
+ | **Tab** | `tab_accept=1`: accept full suggestion. `tab_accept=2` (default): open completion menu with suggestion highlighted at top, native completions below | If latched: unlatch + re-fetch suggestion. Else: normal tab completion |
259
+ | **Down** | Open completion menu with suggestion highlighted at top | History navigation |
260
260
  | **Right arrow** | Accept one word, re-fetch | Move cursor right |
261
261
  | Enter | Clear suggestion, execute | Execute |
262
262
  | Esc | Dismiss suggestion | Normal Esc |
@@ -290,19 +290,25 @@ eval "$(copa completion zsh)"
290
290
  # never — disable Copa tab completion entirely
291
291
  if [[ "$_COPA_COMPLETION_MODE" != 'never' ]]; then
292
292
 
293
- _copa_history_complete() {
294
- # Hoist pending inline suggestion as a completion candidate
295
- if [[ -n "$_COPA_SUGGEST_PENDING" ]]; then
296
- local pending="$_COPA_SUGGEST_PENDING"
297
- _COPA_SUGGEST_PENDING=""
298
- local cur_word="${words[CURRENT]}"
299
- local prefix_len=$(( ${#LBUFFER} - ${#cur_word} ))
300
- local insert_text="${pending:$prefix_len}"
301
- if [[ -n "$insert_text" ]]; then
302
- compadd -U -Q -V 'copa-suggestion' -X 'SUGGESTED' -o nosort -- "$insert_text"
303
- fi
304
- compstate[list]='list force'
293
+ # Suggestion completer: runs FIRST so menu-complete highlights the Copa
294
+ # suggestion before native completions. No-op when nothing is pending.
295
+ # Always returns 1 so the chain continues to _complete and _copa_history_complete;
296
+ # compadd matches persist across completers regardless of return value.
297
+ _copa_suggestion_complete() {
298
+ [[ -z "$_COPA_SUGGEST_PENDING" ]] && return 1
299
+ local pending="$_COPA_SUGGEST_PENDING"
300
+ _COPA_SUGGEST_PENDING=""
301
+ local cur_word="${words[CURRENT]}"
302
+ local prefix_len=$(( ${#LBUFFER} - ${#cur_word} ))
303
+ local insert_text="${pending:$prefix_len}"
304
+ if [[ -n "$insert_text" ]]; then
305
+ compadd -U -Q -V 'copa-suggestion' -X 'SUGGESTED' -o nosort -- "$insert_text"
305
306
  fi
307
+ compstate[list]='list force'
308
+ return 1 # don't stop chain — let _complete and _copa_history_complete also run
309
+ }
310
+
311
+ _copa_history_complete() {
306
312
  # In fallback mode, only show when native completers found nothing
307
313
  if [[ "$_COPA_COMPLETION_MODE" == 'fallback' ]]; then
308
314
  (( compstate[nmatches] > 0 )) && return
@@ -327,12 +333,14 @@ _copa_history_complete() {
327
333
  fi
328
334
  }
329
335
 
330
- # Append to existing completers without clobbering user config
336
+ # Append to existing completers without clobbering user config.
337
+ # _copa_suggestion_complete runs first so menu-complete highlights
338
+ # the Copa suggestion; _copa_history_complete runs last for history matches.
331
339
  () {
332
340
  local -a cur
333
341
  zstyle -g cur ':completion:*' completer 2>/dev/null
334
342
  if (( ! ${cur[(Ie)_copa_history_complete]} )); then
335
- zstyle ':completion:*' completer ${cur:-_complete} _copa_history_complete
343
+ zstyle ':completion:*' completer _copa_suggestion_complete ${cur:-_complete} _copa_history_complete
336
344
  fi
337
345
  # Enable group separation so Copa results appear as a distinct section
338
346
  zstyle ':completion:*' group-name ''
@@ -412,8 +420,7 @@ _copa_suggest_backward_delete_char() {
412
420
  zle -N backward-delete-char _copa_suggest_backward_delete_char
413
421
 
414
422
  # Tab: accept suggestion or open completion menu.
415
- # Tab: accept suggestion or open completion menu.
416
- # Don't call _copa_suggest_fetch after expand-or-complete — menu-select
423
+ # Don't call _copa_suggest_fetch after menu-complete menu-select
417
424
  # runs asynchronously and fetch would overwrite the display with
418
425
  # ghost text. The self-insert wrapper re-fetches on the next keystroke.
419
426
  _copa_suggest_expand_or_complete() {
@@ -424,14 +431,15 @@ _copa_suggest_expand_or_complete() {
424
431
  CURSOR=${#BUFFER}
425
432
  _copa_suggest_clear
426
433
  else
427
- # tab_accept=2: open completion menu with suggestion highlighted
428
- # Use .expand-or-complete (not menu-complete) so menu-select
429
- # highlights the first item in group-order (copa-suggestion),
430
- # rather than the first match from the first completer.
434
+ # tab_accept=2: open completion menu with suggestion highlighted.
435
+ # menu-complete enters menu-select mode reliably (unlike
436
+ # .expand-or-complete which bypasses menu-select). With
437
+ # group-order copa-suggestion copa-history, menu-select cycles
438
+ # in display order, so the Copa suggestion is highlighted first.
431
439
  local pending="$_COPA_SUGGESTION"
432
440
  _copa_suggest_clear
433
441
  _COPA_SUGGEST_PENDING="$pending"
434
- zle .expand-or-complete
442
+ zle menu-complete
435
443
  fi
436
444
  return
437
445
  fi
@@ -519,7 +527,7 @@ _copa_suggest_down_line_or_history() {
519
527
  local pending="$_COPA_SUGGESTION"
520
528
  _copa_suggest_clear
521
529
  _COPA_SUGGEST_PENDING="$pending"
522
- zle .expand-or-complete
530
+ zle menu-complete
523
531
  else
524
532
  zle .down-line-or-history
525
533
  fi
@@ -537,7 +545,7 @@ _copa_suggest_down_line_or_search() {
537
545
  local pending="$_COPA_SUGGESTION"
538
546
  _copa_suggest_clear
539
547
  _COPA_SUGGEST_PENDING="$pending"
540
- zle .expand-or-complete
548
+ zle menu-complete
541
549
  else
542
550
  zle .down-line-or-search
543
551
  fi
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copa-cli
3
- Version: 0.7.0
3
+ Version: 0.7.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
@@ -285,8 +285,8 @@ $ git pu█sh origin main ← grey ghost text
285
285
  |-----|-------------------|---------------|
286
286
  | Type chars | Insert char, re-fetch suggestion | Insert char, fetch suggestion |
287
287
  | Backspace | Delete char, **latch** (suppress suggestions) | Delete char normally |
288
- | **Tab** | `tab_accept=1`: accept full suggestion. `tab_accept=2` (default): first Tab highlights suggestion (cyan), second Tab accepts | If latched: unlatch + re-fetch suggestion. Else: normal tab completion |
289
- | **Down** | Highlight suggestion (enter confirming state) | History navigation |
288
+ | **Tab** | `tab_accept=1`: accept full suggestion. `tab_accept=2` (default): open completion menu with suggestion highlighted at top, native completions below | If latched: unlatch + re-fetch suggestion. Else: normal tab completion |
289
+ | **Down** | Open completion menu with suggestion highlighted at top | History navigation |
290
290
  | **Right arrow** | Accept one word, re-fetch | Move cursor right |
291
291
  | Enter | Clear suggestion, execute | Execute |
292
292
  | Esc | Dismiss suggestion | Normal Esc |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "copa-cli"
7
- version = "0.7.0"
7
+ version = "0.7.1"
8
8
  description = "Command Palette — smart command tracking, ranking, and sharing for your shell"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -819,7 +819,7 @@ class TestSuggestBackspaceLatch:
819
819
  def test_packaged_zsh_tab_unlatches(self):
820
820
  content = self._read_zsh("copa/copa.zsh")
821
821
  start = content.index("_copa_suggest_expand_or_complete()")
822
- func_block = content[start : start + 800]
822
+ func_block = content[start : start + 1000]
823
823
  assert "_COPA_SUGGEST_LATCHED=0" in func_block
824
824
 
825
825
  def test_packaged_zsh_backward_kill_word_latches(self):
@@ -920,9 +920,7 @@ class TestTabAcceptZsh:
920
920
  # Tab widget checks tab_accept internally for mode 1 vs 2
921
921
  assert "_COPA_SUGGEST_TAB_ACCEPT" in func_block
922
922
  assert "_copa_suggest_clear" in func_block
923
- # Mode 2 uses expand-or-complete so menu-select highlights by group-order
924
- assert "zle .expand-or-complete" in func_block
925
- # Non-suggestion fallback still uses menu-complete
923
+ # Mode 2 uses menu-complete to reliably enter menu-select mode
926
924
  assert "zle menu-complete" in func_block
927
925
  # Mode 2 sets pending and opens completion menu
928
926
  assert "_COPA_SUGGEST_PENDING" in func_block
@@ -935,7 +933,6 @@ class TestTabAcceptZsh:
935
933
  func_block = content[start : start + 1000]
936
934
  assert "_COPA_SUGGEST_TAB_ACCEPT" in func_block
937
935
  assert "_copa_suggest_clear" in func_block
938
- assert "zle .expand-or-complete" in func_block
939
936
  assert "zle menu-complete" in func_block
940
937
  assert "_COPA_SUGGEST_PENDING" in func_block
941
938
  assert "bindkey '^I' _copa_suggest_expand_or_complete" in content
@@ -948,7 +945,7 @@ class TestTabAcceptZsh:
948
945
  assert ".down-line-or-history" in func_block
949
946
  # Down arrow with suggestion: hoists to completion menu
950
947
  assert "_COPA_SUGGEST_PENDING" in func_block
951
- assert "zle .expand-or-complete" in func_block
948
+ assert "zle menu-complete" in func_block
952
949
 
953
950
  def test_root_zsh_down_opens_menu_or_history(self):
954
951
  content = self._read_zsh("copa.zsh")
@@ -957,7 +954,7 @@ class TestTabAcceptZsh:
957
954
  assert "_copa_suggest_clear" in func_block
958
955
  assert ".down-line-or-history" in func_block
959
956
  assert "_COPA_SUGGEST_PENDING" in func_block
960
- assert "zle .expand-or-complete" in func_block
957
+ assert "zle menu-complete" in func_block
961
958
 
962
959
  def test_packaged_zsh_clear_resets_pending(self):
963
960
  content = self._read_zsh("copa/copa.zsh")
@@ -1014,33 +1011,31 @@ class TestTabAcceptZsh:
1014
1011
  after_latch = func_block[latch_idx:]
1015
1012
  assert "_copa_suggest_fetch" in after_latch
1016
1013
 
1017
- def test_packaged_zsh_history_complete_hoists_suggestion(self):
1014
+ def test_packaged_zsh_suggestion_completer_exists(self):
1018
1015
  content = self._read_zsh("copa/copa.zsh")
1019
- start = content.index("_copa_history_complete()")
1020
- func_block = content[start : start + 800]
1016
+ start = content.index("_copa_suggestion_complete()")
1017
+ func_block = content[start : start + 500]
1021
1018
  assert "_COPA_SUGGEST_PENDING" in func_block
1022
1019
  assert "compadd -U -Q -V 'copa-suggestion'" in func_block
1020
+ assert "compstate[list]='list force'" in func_block
1023
1021
 
1024
- def test_root_zsh_history_complete_hoists_suggestion(self):
1022
+ def test_root_zsh_suggestion_completer_exists(self):
1025
1023
  content = self._read_zsh("copa.zsh")
1026
- start = content.index("_copa_history_complete()")
1027
- func_block = content[start : start + 800]
1024
+ start = content.index("_copa_suggestion_complete()")
1025
+ func_block = content[start : start + 500]
1028
1026
  assert "_COPA_SUGGEST_PENDING" in func_block
1029
1027
  assert "compadd -U -Q -V 'copa-suggestion'" in func_block
1028
+ assert "compstate[list]='list force'" in func_block
1030
1029
 
1031
- def test_packaged_zsh_forces_completion_list(self):
1032
- """compstate[list] forces the completion list to display."""
1030
+ def test_packaged_zsh_suggestion_completer_runs_first(self):
1031
+ """_copa_suggestion_complete must be before _complete in completer chain."""
1033
1032
  content = self._read_zsh("copa/copa.zsh")
1034
- start = content.index("_copa_history_complete()")
1035
- func_block = content[start : start + 800]
1036
- assert "compstate[list]='list force'" in func_block
1033
+ assert "_copa_suggestion_complete ${cur:-_complete} _copa_history_complete" in content
1037
1034
 
1038
- def test_root_zsh_forces_completion_list(self):
1039
- """compstate[list] forces the completion list to display."""
1035
+ def test_root_zsh_suggestion_completer_runs_first(self):
1036
+ """_copa_suggestion_complete must be before _complete in completer chain."""
1040
1037
  content = self._read_zsh("copa.zsh")
1041
- start = content.index("_copa_history_complete()")
1042
- func_block = content[start : start + 800]
1043
- assert "compstate[list]='list force'" in func_block
1038
+ assert "_copa_suggestion_complete ${cur:-_complete} _copa_history_complete" in content
1044
1039
 
1045
1040
  def test_packaged_zsh_has_suggestion_branding(self):
1046
1041
  content = self._read_zsh("copa/copa.zsh")
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
File without changes
File without changes