From e6b4d00e3a586be753c3d457c5153380392bda32 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 19 Jun 2022 08:58:18 +0200 Subject: Merging upstream version 1.9.0. Signed-off-by: Daniel Baumann --- CHANGELOG.md | 15 ++++++++++ litecli/__init__.py | 2 +- litecli/clitoolbar.py | 1 + litecli/liteclirc | 5 ++++ litecli/main.py | 13 +++++++-- litecli/packages/completion_engine.py | 4 +-- litecli/packages/special/dbcommands.py | 53 ++++++++++++++++++++++------------ litecli/sqlexecute.py | 7 +++++ release.py | 2 +- tests/liteclirc | 8 +++++ tests/test_dbspecial.py | 11 +++++++ 11 files changed, 96 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fad747..afeebd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +## 1.9.0 - 2022-06-06 + +### Features + +* Add support for ANSI escape sequences for coloring the prompt. +* Add support for `.indexes` command. +* Add an option to turn off the auto-completion menu. Completion menu can be + triggered by pressed the `` key when this option is set to False. Fixes + [#105](https://github.com/dbcli/litecli/issues/105). + +### Bug Fixes + +* Fix [#120](https://github.com/dbcli/litecli/issues/120). Make the `.read` command actually read and execute the commands from a file. +* Fix [#96](https://github.com/dbcli/litecli/issues/96) the crash in VI mode when pressing `r`. + ## 1.8.0 - 2022-03-29 ### Features diff --git a/litecli/__init__.py b/litecli/__init__.py index 29654ee..0a0a43a 100644 --- a/litecli/__init__.py +++ b/litecli/__init__.py @@ -1 +1 @@ -__version__ = "1.8.0" +__version__ = "1.9.0" diff --git a/litecli/clitoolbar.py b/litecli/clitoolbar.py index 05d0bfd..1e28784 100644 --- a/litecli/clitoolbar.py +++ b/litecli/clitoolbar.py @@ -48,4 +48,5 @@ def _get_vi_mode(): InputMode.NAVIGATION: "N", InputMode.REPLACE: "R", InputMode.INSERT_MULTIPLE: "M", + InputMode.REPLACE_SINGLE: "R", }[get_app().vi_state.input_mode] diff --git a/litecli/liteclirc b/litecli/liteclirc index f0a4285..4db6f3a 100644 --- a/litecli/liteclirc +++ b/litecli/liteclirc @@ -52,6 +52,10 @@ key_bindings = emacs # Enabling this option will show the suggestions in a wider menu. Thus more items are suggested. wider_completion_menu = False +# Autocompletion is on by default. This can be truned off by setting this +# option to False. Pressing tab will still trigger completion. +autocompletion = True + # litecli prompt # \D - The full current date # \d - Database name @@ -62,6 +66,7 @@ wider_completion_menu = False # \R - The current time, in 24-hour military time (0-23) # \r - The current time, standard 12-hour time (1-12) # \s - Seconds of the current time +# \x1b[...m - insert ANSI escape sequence prompt = '\d> ' prompt_continuation = '-> ' diff --git a/litecli/main.py b/litecli/main.py index dce3c1f..de279f6 100644 --- a/litecli/main.py +++ b/litecli/main.py @@ -23,6 +23,7 @@ from prompt_toolkit.shortcuts import PromptSession, CompleteStyle from prompt_toolkit.styles.pygments import style_from_pygments_cls from prompt_toolkit.document import Document from prompt_toolkit.filters import HasFocus, IsDone +from prompt_toolkit.formatted_text import ANSI from prompt_toolkit.layout.processors import ( HighlightMatchingBracketProcessor, ConditionalProcessor, @@ -88,6 +89,7 @@ class LiteCli(object): self.cli_style = c["colors"] self.output_style = style_factory_output(self.syntax_style, self.cli_style) self.wider_completion_menu = c["main"].as_bool("wider_completion_menu") + self.autocompletion = c["main"].as_bool("autocompletion") c_dest_warning = c["main"].as_bool("destructive_warning") self.destructive_warning = c_dest_warning if warn is None else warn self.login_path_as_host = c["main"].as_bool("login_path_as_host") @@ -161,10 +163,11 @@ class LiteCli(object): ) special.register_special_command( self.execute_from_file, - "source", + ".read", "\\. filename", "Execute commands from file.", - aliases=("\\.",), + case_sensitive=True, + aliases=("\\.", "source"), ) special.register_special_command( self.change_prompt_format, @@ -381,7 +384,8 @@ class LiteCli(object): and len(prompt) > self.max_len_prompt ): prompt = self.get_prompt("\\d> ") - return [("class:prompt", prompt)] + prompt = prompt.replace("\\x1b", "\x1b") + return ANSI(prompt) def get_continuation(width, line_number, is_soft_wrap): continuation = " " * (width - 1) + " " @@ -547,6 +551,9 @@ class LiteCli(object): else: complete_style = CompleteStyle.COLUMN + if not self.autocompletion: + complete_style = CompleteStyle.READLINE_LIKE + with self._completer_lock: if self.key_bindings == "vi": diff --git a/litecli/packages/completion_engine.py b/litecli/packages/completion_engine.py index 0397857..0e2a30f 100644 --- a/litecli/packages/completion_engine.py +++ b/litecli/packages/completion_engine.py @@ -105,14 +105,14 @@ def suggest_special(text): if cmd in ["\\f", "\\fs", "\\fd"]: return [{"type": "favoritequery"}] - if cmd in ["\\d", "\\dt", "\\dt+", ".schema"]: + if cmd in ["\\d", "\\dt", "\\dt+", ".schema", ".indexes"]: return [ {"type": "table", "schema": []}, {"type": "view", "schema": []}, {"type": "schema"}, ] - if cmd in ["\\.", "source", ".open"]: + if cmd in ["\\.", "source", ".open", ".read"]: return [{"type": "file_name"}] if cmd in [".import"]: diff --git a/litecli/packages/special/dbcommands.py b/litecli/packages/special/dbcommands.py index a7eaa0c..203e1a8 100644 --- a/litecli/packages/special/dbcommands.py +++ b/litecli/packages/special/dbcommands.py @@ -110,6 +110,41 @@ def list_databases(cur, **_): return [(None, None, None, "")] +@special_command( + ".indexes", + ".indexes [tablename]", + "List indexes.", + arg_type=PARSED_QUERY, + case_sensitive=True, + aliases=("\\di",), +) +def list_indexes(cur, arg=None, arg_type=PARSED_QUERY, verbose=False): + if arg: + args = ("{0}%".format(arg),) + query = """ + SELECT name FROM sqlite_master + WHERE type = 'index' AND tbl_name LIKE ? AND name NOT LIKE 'sqlite_%' + ORDER BY 1 + """ + else: + args = tuple() + query = """ + SELECT name FROM sqlite_master + WHERE type = 'index' AND name NOT LIKE 'sqlite_%' + ORDER BY 1 + """ + + log.debug(query) + cur.execute(query, args) + indexes = cur.fetchall() + status = "" + if cur.description: + headers = [x[0] for x in cur.description] + else: + return [(None, None, None, "")] + return [(None, indexes, headers, status)] + + @special_command( ".status", "\\s", @@ -202,24 +237,6 @@ def describe(cur, arg, **_): return [(None, tables, headers, status)] -@special_command( - ".read", - ".read path", - "Read input from path", - arg_type=PARSED_QUERY, - case_sensitive=True, -) -def read_script(cur, arg, **_): - args = shlex.split(arg) - if len(args) != 1: - raise TypeError(".read accepts exactly one path") - path = args[0] - with open(path, "r") as f: - script = f.read() - cur.executescript(script) - return [(None, None, None, "")] - - @special_command( ".import", ".import filename table", diff --git a/litecli/sqlexecute.py b/litecli/sqlexecute.py index 2b8fce3..3f78d49 100644 --- a/litecli/sqlexecute.py +++ b/litecli/sqlexecute.py @@ -38,6 +38,13 @@ class SQLExecute(object): ORDER BY tableName, columnName """ + indexes_query = """ + SELECT name + FROM sqlite_master + WHERE type = 'index' AND name NOT LIKE 'sqlite_%' + ORDER BY 1 + """ + functions_query = '''SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE="FUNCTION" AND ROUTINE_SCHEMA = "%s"''' diff --git a/release.py b/release.py index 264a4c3..f6beb88 100644 --- a/release.py +++ b/release.py @@ -75,7 +75,7 @@ def upload_distribution_files(): def push_to_github(): - run_step("git", "push", "origin", "master") + run_step("git", "push", "origin", "main") def push_tags_to_github(): diff --git a/tests/liteclirc b/tests/liteclirc index 979b409..da9b061 100644 --- a/tests/liteclirc +++ b/tests/liteclirc @@ -51,6 +51,10 @@ key_bindings = emacs # Enabling this option will show the suggestions in a wider menu. Thus more items are suggested. wider_completion_menu = False +# Autocompletion is on by default. This can be truned off by setting this +# option to False. Pressing tab will still trigger completion. +autocompletion = True + # litecli prompt # \D - The full current date # \d - Database name @@ -61,9 +65,13 @@ wider_completion_menu = False # \R - The current time, in 24-hour military time (0-23) # \r - The current time, standard 12-hour time (1-12) # \s - Seconds of the current time +# \x1b[...m - insert ANSI escape sequence prompt = "\t :\d> " prompt_continuation = "-> " +# Show/hide the informational toolbar with function keymap at the footer. +show_bottom_toolbar = True + # Skip intro info on startup and outro info on exit less_chatty = False diff --git a/tests/test_dbspecial.py b/tests/test_dbspecial.py index c7065a9..5128b5b 100644 --- a/tests/test_dbspecial.py +++ b/tests/test_dbspecial.py @@ -63,3 +63,14 @@ def test_format_uptime(): seconds = 522600 assert "6 days 1 hour 10 min 0 sec" == format_uptime(seconds) + + +def test_indexes(): + suggestions = suggest_type(".indexes", ".indexes ") + assert sorted_dicts(suggestions) == sorted_dicts( + [ + {"type": "table", "schema": []}, + {"type": "view", "schema": []}, + {"type": "schema"}, + ] + ) -- cgit v1.2.3