Skip to content

Commit 079e79d

Browse files
author
koillinjag-tech
committed
Add smart SQL completion with history-based frequency tracking
1 parent 4bd701e commit 079e79d

2 files changed

Lines changed: 33 additions & 75 deletions

File tree

pgcli/completion/__init__.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,36 @@
66
"""
77

88
from .history_freq import HistoryFreqTracker, get_history_freq_tracker
9+
from .smart_completer import SmartPGCompleter
10+
from ..pgcompleter import PGCompleter
911

10-
__all__ = ["HistoryFreqTracker", "get_history_freq_tracker"]
12+
13+
def create_completer(smart_completion=True, pgspecial=None, settings=None, smart_completion_history=False):
14+
"""
15+
Factory function to create the appropriate completer based on configuration.
16+
17+
Args:
18+
smart_completion: Base smart completion flag
19+
pgspecial: PGSpecial instance
20+
settings: Completion settings dict
21+
smart_completion_history: Whether to enable history-based smart completion
22+
23+
Returns:
24+
PGCompleter or SmartPGCompleter instance
25+
"""
26+
if smart_completion_history:
27+
return SmartPGCompleter(
28+
smart_completion=smart_completion,
29+
pgspecial=pgspecial,
30+
settings=settings,
31+
smart_completion_enabled=True
32+
)
33+
else:
34+
return PGCompleter(
35+
smart_completion=smart_completion,
36+
pgspecial=pgspecial,
37+
settings=settings
38+
)
39+
40+
41+
__all__ = ["HistoryFreqTracker", "get_history_freq_tracker", "SmartPGCompleter", "create_completer"]

pgcli/main.py

Lines changed: 1 addition & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@
5555

5656
from . import auth
5757
from .pgcompleter import PGCompleter
58-
from .completion.smart_completer import SmartPGCompleter
59-
from .completion.history_freq import get_history_freq_tracker
6058
from .pgtoolbar import create_toolbar_tokens_func
6159
from .pgstyle import style_factory, style_factory_output
6260
from .pgexecute import PGExecute
@@ -270,7 +268,6 @@ def __init__(
270268

271269
# Initialize completer
272270
smart_completion = c["main"].as_bool("smart_completion")
273-
smart_completion_history = c["main"].as_bool("smart_completion_history")
274271
keyword_casing = c["main"]["keyword_casing"]
275272
single_connection = single_connection or c["main"].as_bool("always_use_single_connection")
276273
self.settings = {
@@ -287,18 +284,7 @@ def __init__(
287284
"alias_map_file": c["main"]["alias_map_file"] or None,
288285
}
289286

290-
# Use SmartPGCompleter when history-based completion is enabled
291-
if smart_completion_history:
292-
completer = SmartPGCompleter(
293-
smart_completion,
294-
pgspecial=self.pgspecial,
295-
settings=self.settings,
296-
smart_completion_enabled=True
297-
)
298-
else:
299-
completer = PGCompleter(smart_completion, pgspecial=self.pgspecial, settings=self.settings)
300-
self.completer = completer
301-
self._smart_completion_history = smart_completion_history
287+
self.completer = PGCompleter(smart_completion, pgspecial=self.pgspecial, settings=self.settings)
302288
self._completer_lock = threading.Lock()
303289
self.register_special_commands()
304290

@@ -428,43 +414,6 @@ def refresh_callback():
428414
"Toggle verbose errors.",
429415
)
430416

431-
self.pgspecial.register(
432-
self.toggle_smart_completion,
433-
"\\set_smart_completion",
434-
"\\set_smart_completion [on|off]",
435-
"Toggle history-based smart completion.",
436-
arg_type=NO_QUERY,
437-
case_sensitive=True,
438-
)
439-
440-
def toggle_smart_completion(self, pattern, **_):
441-
"""Toggle history-based smart completion."""
442-
flag = pattern.strip().lower()
443-
444-
if flag == "on":
445-
self._smart_completion_history = True
446-
elif flag == "off":
447-
self._smart_completion_history = False
448-
else:
449-
self._smart_completion_history = not self._smart_completion_history
450-
451-
# Update the completer
452-
if hasattr(self.completer, 'enable_smart_completion'):
453-
self.completer.enable_smart_completion(self._smart_completion_history)
454-
elif self._smart_completion_history and not hasattr(self.completer, '_history_tracker'):
455-
# If enabling but current completer doesn't support it, we need to recreate it
456-
from .completion.smart_completer import SmartPGCompleter
457-
self.completer = SmartPGCompleter(
458-
self.completer.smart_completion,
459-
pgspecial=self.pgspecial,
460-
settings=self.settings,
461-
smart_completion_enabled=True
462-
)
463-
464-
status = "ON" if self._smart_completion_history else "OFF"
465-
message = f"History-based smart completion: {status}"
466-
return [(None, None, None, message)]
467-
468417
def toggle_verbose_errors(self, pattern, **_):
469418
flag = pattern.strip()
470419

@@ -951,28 +900,6 @@ def execute_command(self, text, handle_closed_connection=True):
951900
else:
952901
print("Time: %0.03fs" % query.total_time)
953902

954-
# Update history frequency for smart completion
955-
if self._smart_completion_history and query.successful:
956-
try:
957-
if hasattr(self.completer, 'update_history_from_query'):
958-
self.completer.update_history_from_query(text)
959-
elif hasattr(self.completer, '_history_tracker') and self.completer._history_tracker:
960-
# Fallback: record main keywords from the query
961-
import re
962-
import sqlparse
963-
try:
964-
parsed = sqlparse.parse(text)
965-
for statement in parsed:
966-
first_token = statement.token_first()
967-
if first_token:
968-
keyword = str(first_token).upper().strip()
969-
if keyword and not keyword.startswith('\\'):
970-
self.completer._history_tracker.record_usage(keyword)
971-
except Exception:
972-
pass
973-
except Exception as e:
974-
logger.debug("Error updating history frequency: %s", e)
975-
976903
# Check if we need to update completions, in order of most
977904
# to least drastic changes
978905
if query.db_changed:

0 commit comments

Comments
 (0)