From 002d6abcc76a8a83e5ea191e6f8d6dbed6b714eb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Vincent=20Bela=C3=AFche?= Date: Mon, 17 Jul 2017 19:58:12 +0200 Subject: [PATCH] Fix symbol completion and document it. * doc/misc/ses.texi (Configuring what printer function applies): Add description of keys for completing local printer symbols and listing local printers in a help buffer. (Formulas): Add decription for key to list the named cell symbols in a help buffer. * lisp/ses.el (ses-completion-keys): New constant. (ses--completion-table): New defvar. (ses--list-orig-buffer): New defvar. (ses-mode-edit-map): Fixed for symbol completion, plus add help functions to list named cells or local printers. (ses-edit-cell-complete-symbol) (ses--edit-cell-completion-at-point-function): New defuns for completion during formula edition. (ses-edit-cell): Redefine dynamically edit keymap for completion keys to point at the right function. (ses-read-printer-complete-symbol) (ses--read-printer-completion-at-point-function): New defuns for completion during printer edition. (ses-read-printer): Redefine dynamically edit keymap for completion keys to point at the right function. (ses-list-local-printers): New defun. (ses-list-named-cells): New defun. --- doc/misc/ses.texi | 29 ++++++-- lisp/ses.el | 172 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 194 insertions(+), 7 deletions(-) diff --git a/doc/misc/ses.texi b/doc/misc/ses.texi index cac874d0f02..fc79b027a1d 100644 --- a/doc/misc/ses.texi +++ b/doc/misc/ses.texi @@ -292,7 +292,13 @@ Self-insert an expression. The right-parenthesis is inserted for you (@code{ses-read-cell}). To access another cell's value, just use its identifier in your expression. Whenever the other cell is changed, this cell's formula will be reevaluated. While typing in the -expression, you can use @kbd{M-@key{TAB}} to complete symbol names. +expression, you can use the following keys: +@table @kbd +@item M-@key{TAB} +to complete symbol names, and +@item C-h C-n +to list the named cells symbols in a help buffer. +@end table @item ' @r{(apostrophe)} Enter a symbol (ses-read-symbol). @acronym{SES} remembers all symbols that have @@ -458,11 +464,22 @@ Enter the default printer for the spreadsheet (@code{ses-read-default-printer}). @end table -The @code{ses-read-@var{xxx}-printer} commands have their own -minibuffer history, which is preloaded with the set of all printers -used in this spreadsheet, plus the standard printers (@pxref{Standard -printer functions}) and the local printers (@pxref{Local printer -functions}). +The @code{ses-read-@var{xxx}-printer} allows the following commands during editing: + +@table @kbd +@item @key{arrow-up} +@itemx @key{arrow-down} +To browse history: the @code{ses-read-@var{xxx}-printer} commands have +their own minibuffer history, which is preloaded with the set of all +printers used in this spreadsheet, plus the standard printers +(@pxref{Standard printer functions}) and the local printers +(@pxref{Local printer functions}). +@item @key{TAB} +To complete the local printer symbols, and +@item C-h C-p +To list the local printers in a help buffer. +@end table + @node Standard printer functions @subsection Standard printer functions diff --git a/lisp/ses.el b/lisp/ses.el index 5c560efb703..2e214348eb9 100644 --- a/lisp/ses.el +++ b/lisp/ses.el @@ -167,12 +167,32 @@ Each function is called with ARG=1." ["Export values" ses-export-tsv t] ["Export formulas" ses-export-tsf t])) +(defconst ses-completion-keys '("\M-\C-i" "\C-i") + "List for keys that can be used for completion while editing.") + +(defvar ses--completion-table nil + "Set globally to what completion table to use depending on type + of completion (local printers, cells, etc.). We need to go + through a local variable to pass the SES buffer local variable + to completing function while the current buffer is the + minibuffer.") + +(defvar ses--list-orig-buffer nil + "Calling buffer for SES listing help. Used for listing local + printers or renamed cells.") + + (defconst ses-mode-edit-map (let ((keys '("\C-c\C-r" ses-insert-range "\C-c\C-s" ses-insert-ses-range [S-mouse-3] ses-insert-range-click [C-S-mouse-3] ses-insert-ses-range-click - "\M-\C-i" lisp-complete-symbol)) ; FIXME obsolete + "\C-h\C-p" ses-list-local-printers + "\C-h\C-n" ses-list-named-cells + "\M-\C-i" lisp-complete-symbol)) ; redefined + ; dynamically in + ; editing + ; functions (newmap (make-sparse-keymap))) (set-keymap-parent newmap minibuffer-local-map) (while keys @@ -2447,6 +2467,42 @@ to are recalculated first." ;;---------------------------------------------------------------------------- ;; Input of cell formulas ;;---------------------------------------------------------------------------- +(defun ses-edit-cell-complete-symbol () + (interactive) + (let ((completion-at-point-functions (cons 'ses--edit-cell-completion-at-point-function + completion-at-point-functions))) + (completion-at-point))) + +(defun ses--edit-cell-completion-at-point-function () + (and + ses--completion-table + (let* ((bol (save-excursion (move-beginning-of-line nil) (point))) + start end collection + (prefix + (save-excursion + (setq end (point)) + (backward-sexp) + (if (< (point) bol) + (progn + (setq start bol) + (buffer-substring start end)) + (setq start (point)) + (forward-sexp) + (if (>= (point) end) + (progn + (setq end (point)) + (buffer-substring start end)) + nil)))) + prefix-length) + (when (and prefix (null (string= prefix ""))) + (setq prefix-length (length prefix)) + (maphash (lambda (key val) + (let ((key-name (symbol-name key))) + (when (and (>= (length key-name) prefix-length) + (string= prefix (substring key-name 0 prefix-length))) + (push key-name collection)))) + ses--completion-table) + (and collection (list start end collection)))))) (defun ses-edit-cell (row col newval) "Display current cell contents in minibuffer, for editing. Returns nil if @@ -2468,6 +2524,10 @@ cell formula was unsafe and user declined confirmation." (if (stringp formula) ;; Position cursor inside close-quote. (setq initial (cons initial (length initial)))) + (dolist (key ses-completion-keys) + (define-key ses-mode-edit-map key 'ses-edit-cell-complete-symbol)) + ;; make it globally visible, so that it can be visbile from the minibuffer. + (setq ses--completion-table ses--named-cell-hashmap) (list row col (read-from-minibuffer (format "Cell %s: " ses--curcell) initial @@ -2562,6 +2622,40 @@ cells." ;;---------------------------------------------------------------------------- ;; Input of cell-printer functions ;;---------------------------------------------------------------------------- +(defun ses-read-printer-complete-symbol () + (interactive) + (let ((completion-at-point-functions (cons 'ses--read-printer-completion-at-point-function + completion-at-point-functions))) + (completion-at-point))) + +(defun ses--read-printer-completion-at-point-function () + (let* ((bol (save-excursion (move-beginning-of-line nil) (point))) + start end collection + (prefix + (save-excursion + (setq end (point)) + (backward-sexp) + (if (< (point) bol) + (progn + (setq start bol) + (buffer-substring start end)) + (setq start (point)) + (forward-sexp) + (if (>= (point) end) + (progn + (setq end (point)) + (buffer-substring start end)) + nil)))) + prefix-length) + (when prefix + (setq prefix-length (length prefix)) + (maphash (lambda (key val) + (let ((key-name (symbol-name key))) + (when (and (>= (length key-name) prefix-length) + (string= prefix (substring key-name 0 prefix-length))) + (push key-name collection)))) + ses--completion-table) + (and collection (list start end collection))))) (defun ses-read-printer (prompt default) "Common code for functions `ses-read-cell-printer', `ses-read-column-printer', @@ -2574,6 +2668,10 @@ canceled." (setq prompt (format "%s (default %S): " (substring prompt 0 -2) default))) + (dolist (key ses-completion-keys) + (define-key ses-mode-edit-map key 'ses-read-printer-complete-symbol)) + ;; make it globally visible, so that it can be visbile from the minibuffer. + (setq ses--completion-table ses--local-printer-hashmap) (let ((new (read-from-minibuffer prompt nil ; Initial contents. ses-mode-edit-map @@ -3282,6 +3380,78 @@ is non-nil. Newlines and tabs in the export text are escaped." (setq result (apply #'concat (nreverse result))) (kill-new result))) +;;---------------------------------------------------------------------------- +;; Interactive help on symbols +;;---------------------------------------------------------------------------- + +(defun ses-list-local-printers (&optional local-printer-hashmap) + "List local printers in a help buffer. Can be called either +during editing a printer or a formula, or while in the SES +buffer." + (interactive + (list (cond + ((derived-mode-p 'ses-mode) ses--local-printer-hashmap) + ((minibufferp) ses--completion-table) + ((derived-mode-p 'help-mode) nil) + (t (error "Not in a SES buffer"))))) + (when local-printer-hashmap + (let ((ses--list-orig-buffer (or ses--list-orig-buffer (current-buffer)))) + (help-setup-xref + (list (lambda (local-printer-hashmap buffer) + (let ((ses--list-orig-buffer + (if (buffer-live-p buffer) buffer))) + (ses-list-local-printers local-printer-hashmap))) + local-printer-hashmap ses--list-orig-buffer) + (called-interactively-p 'interactive)) + + (save-excursion + (with-help-window (help-buffer) + (if (= 0 (hash-table-count local-printer-hashmap)) + (princ "No local printers defined.") + (princ "List of local printers definitions:\n") + (maphash (lambda (key val) + (princ key) + (princ " as ") + (prin1 (ses--locprn-def val)) + (princ "\n")) + local-printer-hashmap)) + (with-current-buffer standard-output + (buffer-string))))))) + +(defun ses-list-named-cells (&optional named-cell-hashmap) + "List named cells in a help buffer. Can be called either +during editing a printer or a formula, or while in the SES +buffer." + (interactive + (list (cond + ((derived-mode-p 'ses-mode) ses--named-cell-hashmap) + ((minibufferp) ses--completion-table) + ((derived-mode-p 'help-mode) nil) + (t (error "Not in a SES buffer"))))) + (when named-cell-hashmap + (let ((ses--list-orig-buffer (or ses--list-orig-buffer (current-buffer)))) + (help-setup-xref + (list (lambda (named-cell-hashmap buffer) + (let ((ses--list-orig-buffer + (if (buffer-live-p buffer) buffer))) + (ses-list-named-cells named-cell-hashmap))) + named-cell-hashmap ses--list-orig-buffer) + (called-interactively-p 'interactive)) + + (save-excursion + (with-help-window (help-buffer) + (if (= 0 (hash-table-count named-cell-hashmap)) + (princ "No cell was renamed.") + (princ "List of named cells definitions:\n") + (maphash (lambda (key val) + (princ key) + (princ " for ") + (prin1 (ses-create-cell-symbol (car val) (cdr val))) + (princ "\n")) + named-cell-hashmap)) + (with-current-buffer standard-output + (buffer-string))))))) + ;;---------------------------------------------------------------------------- ;; Other user commands -- 2.39.5