这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
Upcoming Release (TBD)
======================

Features
--------

* Keybindings to insert current date/datetime.


1.32.0 (2025/07/04)
======================

Expand Down
24 changes: 24 additions & 0 deletions doc/key_bindings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,27 @@ C-x u (Emacs-mode)
Unprettify and dedent current statement, usually into one line.

Only accepts buffers containing single SQL statements.

##################
C-o d (Emacs-mode)
##################

Insert the current date at cursor, defined by NOW() on the server.

####################
C-o C-d (Emacs-mode)
####################

Insert the quoted current date at cursor.

##################
C-o t (Emacs-mode)
##################

Insert the current datetime at cursor.

####################
C-o C-t (Emacs-mode)
####################

Insert the quoted current datetime at cursor.
37 changes: 37 additions & 0 deletions mycli/key_bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from prompt_toolkit.filters import completion_is_selected, emacs_mode
from prompt_toolkit.key_binding import KeyBindings

from mycli import shortcuts
from mycli.packages.toolkit.fzf import search_history

_logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -102,6 +103,42 @@ def _(event):
cursorpos_abs -= 1
b.cursor_position = min(cursorpos_abs, len(b.text))

@kb.add("c-o", "d", filter=emacs_mode)
def _(event):
"""
Insert the current date.
"""
_logger.debug("Detected <C-o d> key.")

event.app.current_buffer.insert_text(shortcuts.server_date(mycli.sqlexecute))

@kb.add("c-o", "c-d", filter=emacs_mode)
def _(event):
"""
Insert the quoted current date.
"""
_logger.debug("Detected <C-o C-d> key.")

event.app.current_buffer.insert_text(shortcuts.server_date(mycli.sqlexecute, quoted=True))

@kb.add("c-o", "t", filter=emacs_mode)
def _(event):
"""
Insert the current datetime.
"""
_logger.debug("Detected <C-o t> key.")

event.app.current_buffer.insert_text(shortcuts.server_datetime(mycli.sqlexecute))

@kb.add("c-o", "c-t", filter=emacs_mode)
def _(event):
"""
Insert the quoted current datetime.
"""
_logger.debug("Detected <C-o C-t> key.")

event.app.current_buffer.insert_text(shortcuts.server_datetime(mycli.sqlexecute, quoted=True))

@kb.add("c-r", filter=emacs_mode)
def _(event):
"""Search history using fzf or default reverse incremental search."""
Expand Down
14 changes: 14 additions & 0 deletions mycli/shortcuts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
def server_date(sqlexecute, quoted: bool = False) -> str:
server_date_str = sqlexecute.now().strftime('%Y-%m-%d')
if quoted:
return f"'{server_date_str}'"
else:
return server_date_str


def server_datetime(sqlexecute, quoted: bool = False) -> str:
server_datetime_str = sqlexecute.now().strftime('%Y-%m-%d %H:%M:%S')
if quoted:
return f"'{server_datetime_str}'"
else:
return server_datetime_str
8 changes: 8 additions & 0 deletions mycli/sqlexecute.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class SQLExecute(object):
where table_schema = '%s'
order by table_name,ordinal_position"""

now_query = """SELECT NOW()"""

def __init__(
self,
database,
Expand Down Expand Up @@ -393,6 +395,12 @@ def users(self):
for row in cur:
yield row

def now(self):
with self.conn.cursor() as cur:
_logger.debug("Now Query. sql: %r", self.now_query)
cur.execute(self.now_query)
return cur.fetchone()[0]

def get_connection_id(self):
if not self.connection_id:
self.reset_connection_id()
Expand Down
6 changes: 6 additions & 0 deletions test/features/basic_commands.feature
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
Feature: run the cli,
call the help command,
check our application name,
insert the date,
exit the cli

Scenario: run "\?" command
Expand All @@ -14,6 +16,10 @@ Feature: run the cli,
When we run query to check application_name
then we see found

Scenario: insert the date
When we send "ctrl + o, ctrl + d"
then we see the date

Scenario: run the cli and exit
When we send "ctrl + d"
then dbcli exits
34 changes: 34 additions & 0 deletions test/features/steps/basic_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

"""

import datetime
import tempfile
from textwrap import dedent

Expand All @@ -29,6 +30,16 @@ def step_ctrl_d(context):
context.exit_sent = True


@when('we send "ctrl + o, ctrl + d"')
def step_ctrl_o_ctrl_d(context):
"""Send ctrl + o, ctrl + d to insert the quoted date."""
context.cli.send("SELECT ")
context.cli.sendcontrol("o")
context.cli.sendcontrol("d")
context.cli.send(" AS dt")
context.cli.sendline("")


@when(r'we send "\?" command')
def step_send_help(context):
r"""Send \?
Expand Down Expand Up @@ -75,6 +86,29 @@ def step_see_found(context):
)


@then("we see the date")
def step_see_date(context):
# There are some edge cases in which this test could fail,
# such as running near midnight when the test database has
# a different TZ setting than the system.
date_str = datetime.datetime.now().strftime("%Y-%m-%d")
wrappers.expect_exact(
context,
context.conf["pager_boundary"]
+ "\r"
+ dedent(f"""
+------------+\r
| dt |\r
+------------+\r
| {date_str} |\r
+------------+\r
\r
""")
+ context.conf["pager_boundary"],
timeout=5,
)


@then("we confirm the destructive warning")
def step_confirm_destructive_command(context): # noqa
"""Confirm destructive command."""
Expand Down