Skip to content

Commit

Permalink
New & keybinding to run an external application with cell value as ar…
Browse files Browse the repository at this point in the history
…gv[1]
  • Loading branch information
emarsden committed Oct 12, 2024
1 parent 17fae3e commit bade301
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
- New keybinding in a row-list buffer: `U` will unmark all marked rows (deselects them for
deletion).

- New keybinding in a row-list buffer: `&` will run an application asynchronously with the current
cell value as first commandline argument. This complements the existing `!` keybinding which runs
a Unix-like filter shell command with the current cell value as input.

- Fixes to the interaction between marking rows for deletion and refetching/redrawing the row-list
table. A refetch will now unmark all rows, because data in PostgreSQL may have changed since rows
were marked for deletion leading to inconsistent line numbers.
Expand Down
36 changes: 36 additions & 0 deletions doc/src/row-list.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The following keys are bound when the point is located in the row-list table:
| <kbd>RET</kbd> | Edit the value at point in the minibuffer, or jump to foreign table. |
| <kbd>w</kbd> | Edit the value at point in a widget-based buffer. |
| <kbd>!</kbd> | Run a shell command on the value at point, replacing the output if prefix argument. |
| <kbd>&</kbd> | Run a program asynchronously with the value at point as first arugment. |
| <kbd>Alt</kbd>-<kbd>u</kbd> | Upcase the content of the current cell and update PostgreSQL. |
| <kbd>Alt</kbd>-<kbd>l</kbd> | Downcase the content of the current cell and update PostgreSQL. |
| <kbd>Alt</kbd>-<kbd>c</kbd> | Capitalize the content of the current cell and update PostgreSQL. |
Expand Down Expand Up @@ -56,6 +57,41 @@ The following keys are bound when the point is located in the row-list table:



## Run a shell command or an external application on cell value

There are two methods for running an external (non-Emacs) command on the current cell value:

- Run a Unix filter shell command with the cell value as input: press <kbd>!</kbd>. This is works
similarly to the standard Emacs `shell-command` command, which is bound to
<kbd>M</kbd>-<kbd>!</kbd>. If called with a prefix argument, it will update the database value to
the result of the shell command.

- Run a program asynchronously with the cell value as its first commandline argument: press
<kbd>&amp;</kbd>. This works similarly to the standard Emacs `async-shell-command`, which is bound
to <kbd>M</kbd>-<kbd>&amp;</kbd>.

For example, to count the number of characters in the current cell, type

! wc -c

To downcase the value of a text cell (and modify the value in the database) use

C-u ! tr '[:upper:]' '[:lower]'

To reverse the order of the characters in the cell (and modify the value in
the database), use

C-u ! rev

On a Microsoft Windows machine, you may need to install the [MSYS2](https://www.msys2.org/)
commandline tools for these examples to work.

If the current cell contains a file name, you can launch your system’s default application for that
filename extension by typing <kbd>&amp;</kbd> then entering `xdg-open` (or `open` on a MacOS
machine).



## Follow foreign key references

A column that references data in a foreign table (`FOREIGN KEY`) will be shown in blue. If you type
Expand Down
36 changes: 29 additions & 7 deletions pgmacs.el
Original file line number Diff line number Diff line change
Expand Up @@ -598,9 +598,11 @@ PRIMARY-KEYS."
(defvar pgmacs--shell-command-history nil)

(defun pgmacs--shell-command-on-value (current-row primary-keys)
"Run a shell command with the current cell value as input.
Normally display output in the echo area. If called with a prefix argument,
place the current cell value with the output.
"Run a Unix filter shell command with the current cell value as input.
When called without a prefix argument, output is diplayed in the echo area.
When called with a prefix argument, replace the current cell value with the output
(updating the database).
For example, to count the number of characters in the current cell,
Expand Down Expand Up @@ -637,6 +639,26 @@ Works on the CURRENT-ROW and on a table with PRIMARY-KEYS."
;; displayed pgmacstbl.
(pgmacs--setf-cell current-row primary-keys get-value))))

(defvar pgmacs--async-command-history nil)

(defun pgmacs--async-command-on-value (&rest _ignore)
"Run a command asynchronously with the current cell value as first argument.
The command should be the name of a program, which will be searched for in
`exec-path' (it is run via `start-process', without a shell). Command output will
be displayed in a buffer called *PGmacs async command*.
For example, if the cell contains a filename, you can open the filename in the
default application on your system by entering `xdg-open' (or `open' on a MacOS
machine).
Works on the CURRENT-ROW and on a table with PRIMARY-KEYS."
(pgmacs-funcall-cell
(lambda (cell-value)
(let* ((prompt "Async command: ")
(cmd (read-string prompt nil 'pgmacs--async-command-history))
(buf (get-buffer-create "*PGmacs async command*")))
(start-process "PGmacs-async-command" buf cmd cell-value)))))

(defun pgmacs--downcase-value (current-row primary-keys)
"Downcase the value in the cell at point and update PostgreSQL.
Operates on the CURRENT-ROW and on a table with PRIMARY-KEYS."
Expand Down Expand Up @@ -1469,9 +1491,7 @@ Table names are schema-qualified if the schema is non-default."
(when (y-or-n-p (format "Really run SQL '%s'?" sql))
(let ((res (pg-exec pgmacs--con sql)))
(pgmacs--notify "%s" (pg-result res :status))))))
(pgmacs--display-table pgmacs--table)
(pgmacs--update-row-markings))

(pgmacs--display-table pgmacs--table))

(defun pgmacs--display-procedures (&rest _ignore)
"Open a buffer displaying the FUNCTIONs and PROCEDURES defined in this database."
Expand Down Expand Up @@ -1592,7 +1612,8 @@ Table names are schema-qualified if the schema is non-default."
(shw "U" "Unmark all rows (deselect all for deletion)")
(shw "x" "Delete marked rows")
(shw "R" "Rename the current column")
(shw "!" "Run a shell command on the value of the current cell")
(shw "!" "Run a filter-like shell command with current cell value as input")
(shw "&" "Run a program with the value of current cell as first argument")
(shw "M-u" "Upcase the value of the current cell")
(shw "M-l" "Downcase the value of the current cell")
(shw "M-c" "Capitalize the value of the current cell")
Expand Down Expand Up @@ -1880,6 +1901,7 @@ The CENTER-ON and WHERE-FILTER arguments are mutually exclusive."
:actions `("RET" (lambda (row) (pgmacs--table-list-dwim row ',primary-keys))
"w" (lambda (row) (pgmacs--edit-value-widget row ',primary-keys))
"!" (lambda (row) (pgmacs--shell-command-on-value row ',primary-keys))
"&" pgmacs--async-command-on-value
"M-u" (lambda (row) (pgmacs--upcase-value row ',primary-keys))
"M-l" (lambda (row) (pgmacs--downcase-value row ',primary-keys))
"M-c" (lambda (row) (pgmacs--capitalize-value row ',primary-keys))
Expand Down

0 comments on commit bade301

Please sign in to comment.