Skip to content

Improve completion suggestions inside backticks#1581

Open
rolandwalker wants to merge 1 commit intomainfrom
RW/better-suggest-inside-backquotes
Open

Improve completion suggestions inside backticks#1581
rolandwalker wants to merge 1 commit intomainfrom
RW/better-suggest-inside-backquotes

Conversation

@rolandwalker
Copy link
Contributor

@rolandwalker rolandwalker commented Feb 18, 2026

Description

Previously the behavior was a little janky: on the first character after a backtick, only identifiers which might require a backtick were offered as suggestions (because, for instance, they matched reserved words). Sometimes, that list would be empty, and no suggestions were offered. Then, after typing a few more characters, rapidfuzz matching kicked in, and more suggestions were offered, with backticks off for the additional rapidfuzz suggestions.

Now the behavior is more consistent: if a backtick is typed, all suggestions which could work in that place are offered, with uniform backticks on the suggestions, even if backticks are not required for the given identifier.

Of course, how early the suggestions are offered is still dependent on the min_completion_trigger option in ~/.myclirc, so precise behavior in the above paragraph is conditional on having the default settings.

This PR still struggles on the case of spaces within the backtick, which I'd like to leave for future work, and an xfail test is included to represent the todo.

Fixes #1564 .

Changes

  • Tuck optimization check inside _find_doubled_backticks(), and make the optimization test for double instead of single backticks.
  • Remove function unescape_name(), which is unused, and seems wrongly named since it oriented towards strings rather than identifiers.
  • Let find_matches() add backticks to all suggestions if backtick quoting is detected at the cursor.
  • Recast a variable name in _find_doubled_backticks().

Per some comments in the tests, it would be nicer if column names sorted more strongly to the top in the SELECT context, but that is not new to these changes.

Another idea could be sorting to the top only those suggestions which require a backtick, when in the backtick context -- something for the future.

We also seem to be needlessly suggesting some generic keywords in the SELECT context, but that is also not new to these changes. And if they are going to appear, it seems to make more sense to have them in backticks like the other suggestions, for the sake of uniformity.

Example of the new behavior:
new_backtick

Checklist

  • I added this contribution to the changelog.md file.
  • I added my name to the AUTHORS file (or it's already there).
  • To lint and format the code, I ran
    uv run ruff check && uv run ruff format && uv run mypy --install-types .

@github-actions
Copy link

Findings

  1. Backtick detection can miss valid backtick context after whitespace inside identifiers.
    find_matches() decides to quote based on text.startswith('')oris_inside_quotes(orig_text, len(orig_text)), but orig_textis onlyword_before_cursor(not the full text). If a user is inside a backticked identifier that contains whitespace (e.g.,SELECT `foo bar|), word_before_cursorisbar, so the backtick context isn’t detected and suggestions won’t be uniformly backticked. That contradicts the new behavior stated in the PR description. File: mycli/sqlcompleter.py:1001-1010`

Missing tests / edge cases

  1. Add a test for backtick completion when the identifier includes spaces, to ensure backtick context is detected using the full input, not just the last word.
    Suggested test case: text = "select foo bar"` with cursor at end should yield backticked completions.

Notes

  • No security concerns found in this diff.
  • The rest of the change set looks consistent with the intended behavior.

Suggestions

  1. Update backtick context detection to use document.text_before_cursor (or otherwise pass the full buffer) when calling is_inside_quotes() in find_matches().
  2. Add the whitespace-in-backticks completion test above.

@rolandwalker rolandwalker force-pushed the RW/better-suggest-inside-backquotes branch 3 times, most recently from ca874de to f12b8f2 Compare February 18, 2026 09:56
@rolandwalker
Copy link
Contributor Author

1 Update backtick context detection to use document.text_before_cursor (or otherwise pass the full buffer) when calling is_inside_quotes() in find_matches().

Mostly correct, addressed.

Add the whitespace-in-backticks completion test above.

Added as an xfail, because the issue with spaces runs deeper.

@rolandwalker rolandwalker added the codex request Codex review for an updated PR label Feb 18, 2026
@github-actions
Copy link

Findings (focus: correctness/regressions, security, missing tests)

  1. Incorrect backtick detection when cursor isn’t at end of input
    find_matches() uses is_inside_quotes(full_text, len(full_text)), which always checks the end of the input, not the current cursor position. If a user moves the cursor earlier in the line (prompt_toolkit supports this), completions will be quoted/unquoted based on the wrong position. This is a correctness regression for mid-line edits.
    Action: pass the cursor position into find_matches() and use it for is_inside_quotes.
    Files: mycli/sqlcompleter.py

Missing tests / edge cases

  1. Cursor not at end
    No test covers completion behavior when cursor is in the middle of a line. This would have caught the issue above.
    Action: add a test that inserts text after the cursor and verifies backtick quoting uses Document(..., cursor_position=...) rather than end-of-text.
    Files: test/test_smart_completion_public_schema_only.py

No security concerns found.

If you want, I can propose the exact signature change and test case.

Previously the behavior was a little janky: on the first character after
a backtick, only identifiers which might _require_ a backtick were
offered as suggestions (because, for instance, they matched reserved
words).  Sometimes, that list would be empty, and no suggestions were
offered.  Then, after typing a few more characters, rapidfuzz matching
kicked in, and more suggestions were offered, with backticks off for
the additional rapidfuzz suggestions.

Now the behavior is more consistent: if a backtick is typed, _all_
suggestions which could work in that place are offered, with uniform
backticks on the suggestions, even if backticks are not required for
the given identifier.

Of course, how early the suggestions are offered is still dependent on
the min_completion_trigger option in ~/.myclirc, so the above
paragraph is conditional.

Changes

 * tuck optimization check inside _find_doubled_backticks(), and make
   the optimization test for double instead of single backticks
 * remove function unescape_name(), which is unused, and seems wrongly
   named since it oriented towards strings rather than identifiers
 * let find_matches() add backticks to all suggestions if backtick
   quoting is detected at the cursor
 * recast a variable name in _find_doubled_backticks()

Per some comments in the tests, it would be nicer if column names
sorted more strongly to the top in the SELECT context, but that is not
new to these changes.

Another idea could be sorting to the top only those suggestions which
require a backtick, when in the backtick context -- something for the
future.

We also seem to be needlessly suggesting some generic keywords in the
SELECT context, but that is also not new to these changes.  And if they
are going to appear, it seems to make more sense to have them in
backticks like the other suggestions, for the sake of uniformity.
@rolandwalker rolandwalker force-pushed the RW/better-suggest-inside-backquotes branch from f12b8f2 to 048a2f8 Compare February 18, 2026 10:09
@rolandwalker rolandwalker added codex request Codex review for an updated PR and removed codex request Codex review for an updated PR labels Feb 18, 2026
@github-actions
Copy link

Findings (Correctness)

  1. Potential invalid completions for enum values inside backticks
    find_matches() now wraps all string suggestions with backticks when the cursor is inside backticks, including enum value suggestions that are already single‑quoted. That can yield completions like 'active' which is invalid SQL if the enum value path is active and the user accidentally started a backtick (e.g., WHERE status = \``). Suggested fix: only backtick‑quote identifier‑like suggestions, or skip quoting when the item already looks like a string literal (starts with 'or"). Files: mycli/sqlcompleter.py(infind_matches, around the new maybe_quote_identifier` logic).

Missing tests / edge cases

  1. Enum value suggestions under backtick context
    Add a test where enum value completions are available and the cursor is inside backticks, asserting that suggestions remain single‑quoted or that completions are suppressed. This will guard against the invalid 'value' scenario.
    Files: test/test_smart_completion_public_schema_only.py

If you want, I can propose a small patch to gate the backtick wrapping to identifier‑like items only.

@rolandwalker rolandwalker self-assigned this Feb 18, 2026
@rolandwalker rolandwalker removed the codex request Codex review for an updated PR label Feb 18, 2026
@scottnemes
Copy link
Contributor

This one is a bit complex, and my gut says to scale back the suggestions. You can't run most things surrounded by backticks, so suggesting most keywords and what not often does not make sense. I.e.

`SELECT` * FROM blah;

From a user perspective, it seems like it would make more sense to only ever suggest object type items when suggesting inside backticks; databases, tables, columns, procedures, functions. If a user is wanting a reserved word/keyword to show up inside backticks, it means they're using it as a database/table/column name most likely anyway, and would be covered by only suggesting those objects to begin with.

@rolandwalker
Copy link
Contributor Author

select_select_inappropriate_keywords

I think this is explained in the description pretty well. We are completing too many keywords, but it isn't new to this bugfix, nor particular to backticks at all.

Future work could include:

  • better handling spaces within backticks (we currently start a new completion)
  • recognizing a special backtick context within which only identifiers can be completed
  • sorting column names closer to the top in the SELECT + backtick context
  • sorting identifiers which actually need backticks closer to the top in the backtick context

but it is highly preferable to do those things in separate PRs.

The cause of exuberantly offering inappropriate keywords as completions could be #1447 . We might need to do better (manual) separation of functions vs other keywords. In addition, the favorite_keywords from sqlcompleter.py seem to always be offered, and we expanded that list:

last image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Difference in completion behavior after a backtick

2 participants

Comments