Commit d895fd3d authored by David Byers's avatar David Byers
Browse files

Gör långsamma kommandon mycket roligare.

Kod klart för korrekt completion av kommandon (men inte inkopplad).
parent 4b491373
2000-08-31 David Byers <davby@ida.liu.se>
* option-edit.el (lyskom-customize-buffer-format): Moved
lyskom-trim-buffer-minimum to a better position.
* english-strings.el, swedish-strings.el: Fixed some minor rookie
mistakes made by Ulrik.
* completing-read.el (lyskom-completing-match-string-regexp):
Moved to avoid compiler warnings and to make inlining work.
(lyskom-completing-match-string): Ditto.
* Makefile (SOURCES): Moved completing-read up to avoid warnings.
2000-08-30 David Byers <davby@ida.liu.se>
* lyskom-rest.el (lyskom-update-prompt): Don't fsck up the command
the user is currently entering at the prompt when in slow mode.
* vars.el.in (lyskom-command-alternatives): New variable.
* slow.el (kom-slow-list-completions): New command.
* swedish-strings.el (lyskom-command): Renamed "terstarta kom" so
that "terse" would be easier to complete when using slow
commands.
* language.el (lyskom-set-language): Call
lyskom-update-command-completion.
* lyskom-rest.el (lyskom-is-loaded): Set the default value of
lyskom-collate-table so that lyskom-unicase works even before we
connect to the server.
* utilities.el (lyskom-unicase): Don't attempt to switch to lyskom
buffer if there is none.
* command.el (lyskom-update-command-completion): New function.
(lyskom-lookup-command-by-name): New function.
(lyskom-complete-command): New function.
* completing-read.el (lyskom-completing-match-string-regexp): New
function.
(lyskom-completing-match-string): Use it.
2000-08-30 Ulrik Haugen <qha@lysator.liu.se>
* english-strings.el (lyskom-custom-strings)
......
......@@ -64,6 +64,7 @@ SOURCES = $(LANGUAGE-EL) \
clienttypes.el \
deferred-insert.el \
utilities.el \
completing-read.el \
command.el \
buffers.el \
aux-items.el \
......@@ -85,7 +86,6 @@ SOURCES = $(LANGUAGE-EL) \
lyskom-buttons.el \
view-text.el \
async.el \
completing-read.el \
mship-edit.el \
prioritize.el \
flags.el \
......
......@@ -241,6 +241,41 @@
t nil 'lyskom-command-history)))
(cdr (lyskom-string-assoc name alternatives))))
(defun lyskom-update-command-completion ()
"Build a list of alternatives for completion of LysKOM commands.
FIXME: Do this only when changing the language or logging in."
(setq lyskom-command-alternatives
(mapcar (lambda (el)
(vector (cdr el)
(car el)
(lyskom-completing-strip-name
(lyskom-unicase (cdr el)))))
(lyskom-get-strings lyskom-commands 'lyskom-command))))
(defun lyskom-lookup-command-by-name (string &optional predicate)
"Look up the command that corresponds to a certain string."
(lyskom-complete-command string predicate 'lyskom-lookup))
(defun lyskom-complete-command (string predicate all)
"Completion function for LysKOM commands."
(let ((alternatives nil)
(string (lyskom-completing-match-string-regexp string)))
(lyskom-traverse el lyskom-command-alternatives
(when (and (string-match string (elt el 2))
(or (null predicate) (funcall predicate el)))
(setq alternatives (cons (if (eq all 'lyskom-lookup) el (elt el 0))
alternatives))))
(cond
((eq all 'lyskom-lookup) (elt (car alternatives) 1))
((eq all 'lambda) (= (length alternatives) 1))
(all alternatives)
((null alternatives) nil)
((eq (length alternatives) 1) t)
(t (lyskom-complete-string alternatives)))))
(defun lyskom-start-of-command (function &optional may-interrupt)
"This function is run at the beginning of every LysKOM command.
It moves the cursor one line down, and +++ later it will tell the server
......
......@@ -115,8 +115,16 @@ but first checks a cache."
map)
"Keymap used for reading LysKOM names.")
(defsubst lyskom-completing-match-string-regexp (string)
(concat "^"
(replace-in-string (regexp-quote (lyskom-unicase (lyskom-completing-strip-name string)))
"\\s-+" "\\\\S-*\\\\s-+")
"\\s-*"))
(defsubst lyskom-completing-match-string (string name)
"Return non-nil if STRING matches NAME using LysKOM completion rules."
(string-match (lyskom-completing-match-string-regexp string)
(lyskom-completing-strip-name (lyskom-unicase name))))
(defun lyskom-read-conf-no (prompt type &optional empty initial mustmatch)
......@@ -529,14 +537,6 @@ function work as a name-to-conf-stat translator."
login-list
candidate-list)
(list string))))))))))))
(defun lyskom-completing-match-string (string name)
"Return non-nil if STRING matches NAME using LysKOM completion rules."
(string-match (concat "^"
(replace-in-string (regexp-quote (lyskom-unicase (lyskom-completing-strip-name string)))
"\\s-+" "\\\\S-*\\\\s-+")
"\\s-*")
(lyskom-completing-strip-name (lyskom-unicase name))))
(defun lyskom-completing-member (string list)
......
......@@ -52,6 +52,7 @@ SOURCES = $(LANGUAGE-EL) \
clienttypes.el \
deferred-insert.el \
utilities.el \
completing-read.el \
command.el \
buffers.el \
aux-items.el \
......@@ -73,7 +74,6 @@ SOURCES = $(LANGUAGE-EL) \
lyskom-buttons.el \
view-text.el \
async.el \
completing-read.el \
mship-edit.el \
prioritize.el \
flags.el \
......
......@@ -3181,10 +3181,10 @@ be saved in the server. Otherwise it will be saved in your .emacs.")
recipient. For most people it is a good idea to leave this on.")
(kom-trim-buffer-minimum-doc . "\
If you have anything in lyskom-trim-buffer-hook this variable determines
with how many characters the lyskom buffer size must excede
kom-max-buffer-size before your hook is run and the buffer is trimmed.
The variable should be an integer, the default is 4096.")
If you have limited the LysKOM buffer size, this variable determines
how much larget than the limit the buffer has to be before it is
trimmed back to the maximum size. The variable must be an integer;
the default is 4096.")
;;
......@@ -3340,8 +3340,8 @@ be saved in the server. Otherwise it will be saved in your .emacs.")
(kom-follow-attachments-tag . "Read imported attachments as texts:")
(kom-show-unread-in-frame-title-tag . "Show unread indicator in title bar:")
(kom-created-texts-are-saved-tag . "Save created texts:")
(kom-confirm-add-recipients-tag . "Ask if comments shoulw be sent to new recipients:")
(kom-trim-buffer-minimum-tag . "How small parts of the lyskom buffer are trimmed.")
(kom-confirm-add-recipients-tag . "Ask if comments should be sent to new recipients:")
(kom-trim-buffer-minimum-tag . "How small parts of the LysKOM buffer are trimmed:")
)
)
......
......@@ -285,6 +285,7 @@ if 'lyskom-menu is not found."
(lyskom-set-language-keymaps language)
(lyskom-update-menus)
(lyskom-update-prompt t)
(lyskom-update-command-completion)
t)))
......
......@@ -796,8 +796,6 @@ will automagically flow into your lyskom log file."
(append-to-file 1 lyskom-trim-buffer-delete-to
(expand-file-name (concat "~/" (buffer-name) "-history"))))
;(add-hook 'lyskom-trim-buffer-hook 'jhs-garb-lyskom-buffer-to-file)
(defun lyskom-scroll ()
"Scroll screen if necessary.
......@@ -2380,132 +2378,139 @@ positions are counted from 0, as they are."
(defun lyskom-update-prompt (&optional force-prompt-update)
"Print prompt if the client knows which command will be default.
Set lyskom-current-prompt accordingly. Tell server what I am doing."
(if (or lyskom-executing-command
(and lyskom-current-prompt
lyskom-dont-change-prompt))
nil
(let ((to-do (lyskom-what-to-do))
(prompt nil)
(prompt-args nil))
(setq lyskom-command-to-do to-do)
(cond
((eq to-do 'next-pri-conf)
(setq prompt 'go-to-pri-conf-prompt)
(or (eq lyskom-current-prompt prompt)
(lyskom-beep kom-ding-on-priority-break)))
((eq to-do 'reedit-text)
(setq prompt 're-edit-text-prompt))
((and (eq to-do 'next-pri-session)
(lyskom-get-prioritized-session))
(if (and (read-list-isempty lyskom-reading-list)
(read-list-isempty lyskom-to-do-list))
(setq prompt 'next-unread-session-prompt)
(setq prompt 'next-pri-session-prompt))
(setq prompt-args
(save-excursion
(set-buffer (lyskom-get-prioritized-session))
(list
(or (cdr (lyskom-string-assoc lyskom-server-name
kom-server-aliases))
lyskom-server-name)))))
((eq to-do 'next-pri-text)
(setq prompt 'read-pri-text-conf)
(or (eq lyskom-current-prompt prompt)
(lyskom-beep kom-ding-on-priority-break)))
((eq to-do 'next-text)
(setq prompt
(let ((read-info (read-list->first lyskom-reading-list)))
(let ((was-at-max (eq (point) (point-max)))
(saved-suffix (if lyskom-slow-mode
(save-excursion (lyskom-get-entered-slow-command))
nil)))
(if (or lyskom-executing-command
(and lyskom-current-prompt
lyskom-dont-change-prompt))
nil
(let ((to-do (lyskom-what-to-do))
(prompt nil)
(prompt-args nil))
(setq lyskom-command-to-do to-do)
(cond
((eq to-do 'next-pri-conf)
(setq prompt 'go-to-pri-conf-prompt)
(or (eq lyskom-current-prompt prompt)
(lyskom-beep kom-ding-on-priority-break)))
((eq to-do 'reedit-text)
(setq prompt 're-edit-text-prompt))
((and (eq to-do 'next-pri-session)
(lyskom-get-prioritized-session))
(if (and (read-list-isempty lyskom-reading-list)
(read-list-isempty lyskom-to-do-list))
(setq prompt 'next-unread-session-prompt)
(setq prompt 'next-pri-session-prompt))
(setq prompt-args
(save-excursion
(set-buffer (lyskom-get-prioritized-session))
(list
(or (cdr (lyskom-string-assoc lyskom-server-name
kom-server-aliases))
lyskom-server-name)))))
((eq to-do 'next-pri-text)
(setq prompt 'read-pri-text-conf)
(or (eq lyskom-current-prompt prompt)
(lyskom-beep kom-ding-on-priority-break)))
((eq to-do 'next-text)
(setq prompt
(let ((read-info (read-list->first lyskom-reading-list)))
(cond
((eq 'REVIEW (read-info->type read-info))
'review-next-text-prompt)
((eq 'REVIEW-TREE (read-info->type read-info))
'review-next-comment-prompt)
((eq 'REVIEW-MARK (read-info->type read-info))
'review-next-marked-prompt)
;; The following is not really correct. The text to be
;; read might be in another conference.
((= lyskom-current-conf lyskom-pers-no)
'read-next-letter-prompt)
((eq 'FOOTN-IN (read-info->type read-info))
'read-next-footnote-prompt)
((eq 'COMM-IN (read-info->type read-info))
'read-next-comment-prompt)
(t
'read-next-text-prompt)))))
((eq to-do 'next-conf)
(setq prompt
(cond
((eq 'REVIEW (read-info->type read-info))
'review-next-text-prompt)
((eq 'REVIEW-TREE (read-info->type read-info))
'review-next-comment-prompt)
((eq 'REVIEW-MARK (read-info->type read-info))
'review-next-marked-prompt)
;; The following is not really correct. The text to be
;; read might be in another conference.
((= lyskom-current-conf lyskom-pers-no)
'read-next-letter-prompt)
((eq 'FOOTN-IN (read-info->type read-info))
'read-next-footnote-prompt)
((eq 'COMM-IN (read-info->type read-info))
'read-next-comment-prompt)
((eq 'REVIEW-MARK
(read-info->type (read-list->first lyskom-to-do-list)))
'go-to-conf-of-marked-prompt)
((eq 'REVIEW
(read-info->type (read-list->first lyskom-to-do-list)))
'go-to-conf-of-review-prompt)
((eq 'REVIEW-TREE
(read-info->type (read-list->first lyskom-to-do-list)))
'go-to-conf-of-review-tree-prompt)
((/= lyskom-pers-no
(conf-stat->conf-no
(read-info->conf-stat (read-list->first
lyskom-to-do-list))))
'go-to-next-conf-prompt)
(t
'read-next-text-prompt)))))
((eq to-do 'next-conf)
(setq prompt
(cond
((eq 'REVIEW-MARK
(read-info->type (read-list->first lyskom-to-do-list)))
'go-to-conf-of-marked-prompt)
((eq 'REVIEW
(read-info->type (read-list->first lyskom-to-do-list)))
'go-to-conf-of-review-prompt)
((eq 'REVIEW-TREE
(read-info->type (read-list->first lyskom-to-do-list)))
'go-to-conf-of-review-tree-prompt)
((/= lyskom-pers-no
(conf-stat->conf-no
(read-info->conf-stat (read-list->first
lyskom-to-do-list))))
'go-to-next-conf-prompt)
(t
'go-to-your-mailbox-prompt))))
'go-to-your-mailbox-prompt))))
((eq to-do 'when-done)
(if (not lyskom-is-writing)
(lyskom-tell-server kom-mercial))
(setq prompt
(let ((command (lyskom-what-to-do-when-done t)))
(cond
((lyskom-command-name command))
((and (stringp command)
(lyskom-command-name (key-binding command))))
(t (lyskom-format 'the-command command))))))
((eq to-do 'when-done)
(if (not lyskom-is-writing)
(lyskom-tell-server kom-mercial))
(setq prompt
(let ((command (lyskom-what-to-do-when-done t)))
(cond
((lyskom-command-name command))
((and (stringp command)
(lyskom-command-name (key-binding command))))
(t (lyskom-format 'the-command command))))))
((eq to-do 'unknown) ;Pending replies from server.
(setq prompt nil))
((eq to-do 'unknown) ;Pending replies from server.
(setq prompt nil))
(t (message "%s" to-do)
(setq prompt "???")))
(when (or force-prompt-update
(not (equal prompt lyskom-current-prompt)))
(let ((inhibit-read-only t)
(prompt-text
(if prompt
(lyskom-modify-prompt
(apply 'lyskom-format
(cond
((symbolp prompt) (lyskom-get-string prompt))
(t prompt))
prompt-args))
""))
(was-at-max (eq (point) (point-max))))
(save-excursion
;; Insert the new prompt
(goto-char (point-max))
(beginning-of-line)
(when lyskom-slow-mode
(t (message "%s" to-do)
(setq prompt "???")))
(when (or force-prompt-update
(not (equal prompt lyskom-current-prompt)))
(let ((inhibit-read-only t)
(prompt-text
(if prompt
(lyskom-modify-prompt
(apply 'lyskom-format
(cond
((symbolp prompt) (lyskom-get-string prompt))
(t prompt))
prompt-args))
"")))
(save-excursion
;; Insert the new prompt
(goto-char (point-max))
(beginning-of-line)
(add-text-properties 0 (length prompt-text)
'(read-only t rear-nonsticky t)
prompt-text))
(insert-string prompt-text)
;; Delete the old prompt
(if lyskom-current-prompt
(delete-region (point) (point-max))))
(if was-at-max (goto-char (point-max)))
prompt-text)
(insert-string prompt-text)
;; Delete the old prompt
(when lyskom-current-prompt
(if (and lyskom-slow-mode
(looking-at
(regexp-quote lyskom-current-prompt-text)))
(delete-region (point) (match-end 0))
(delete-region (point) (point-max))
(if saved-suffix (insert saved-suffix)))))
(if was-at-max (goto-char (point-max)))
(setq lyskom-current-prompt prompt)
(setq lyskom-current-prompt-args prompt-args)
(setq lyskom-current-prompt-text prompt-text))))
(lyskom-set-mode-line)))
(setq lyskom-current-prompt prompt)
(setq lyskom-current-prompt-args prompt-args)
(setq lyskom-current-prompt-text prompt-text))))
(lyskom-set-mode-line))))
(defun lyskom-modify-prompt (s &optional executing)
(let ((text (lyskom-format-prompt (cond (lyskom-is-administrator
......@@ -3545,6 +3550,7 @@ One parameter - the prompt string."
(if lyskom-is-loaded
nil
(setq-default lyskom-collate-table lyskom-default-collate-table)
(lyskom-set-language lyskom-language)
(unless (or (memq 'lyskom-unread-mode-line global-mode-string)
(rassq 'lyskom-unread-mode-line global-mode-string))
......
......@@ -80,6 +80,7 @@
[kom-page-before-command]
[kom-deferred-printing]
[kom-max-buffer-size]
[kom-trim-buffer-minimum]
[kom-bury-buffers]
[kom-keep-alive-interval]
"\n"
......@@ -240,7 +241,6 @@
"\n"
[kom-login-hook]
[kom-do-when-done]
[kom-trim-buffer-minimum]
))
;;; ======================================================================
......
......@@ -41,15 +41,14 @@
(make-sparse-keymap)
"Mode map for the `slow' lyskom command mode.")
(define-key lyskom-slow-mode-map "\r" 'kom-parse-command-and-execute)
(define-key lyskom-slow-mode-map "\t" 'kom-expand-slow-command)
(define-key lyskom-slow-mode-map " " 'kom-expand-slow-or-next-command)
(defun lyskom-get-entered-slow-command ()
"Get the text that the user has entered after the last prompt.
Note that this function leaves point at the end of the prompt.
If no text is entered, nil is returned."
(define-key lyskom-slow-mode-map (kbd "RET") 'kom-parse-command-and-execute)
(define-key lyskom-slow-mode-map (kbd "TAB") 'kom-expand-slow-command)
(define-key lyskom-slow-mode-map (kbd "SPC") 'kom-expand-slow-or-next-command)
(define-key lyskom-slow-mode-map (kbd "C-a") 'kom-slow-start-of-line)
(define-key lyskom-slow-mode-map (kbd "?") 'kom-slow-list-completions)
(defun lyskom-slow-start-of-line ()
"Move point to start of command, after LysKOM prompt."
(goto-char (point-max))
(save-restriction
(when (> lyskom-last-viewed (point-max))
......@@ -60,70 +59,93 @@ If no text is entered, nil is returned."
(goto-char (point-max))
(beginning-of-line))
(when (looking-at "\\(\\s-+\\)")
(goto-char (match-end 0))))
(goto-char (match-end 0)))))
(defun lyskom-get-entered-slow-command ()
"Get the text that the user has entered after the last prompt.
Note that this function leaves point at the end of the prompt.
If no text is entered, nil is returned."
(lyskom-slow-start-of-line)
(if (= (point) (point-max))
nil
(buffer-substring (point) (point-max))))
(defun kom-expand-slow-command (&optional try-exact)
"Tries to complete the command at point.
If optional TRY-EXACT is non-nil, look for an exact match.
If the completion was exact return a pair `(COMMAND . POINT)' where
COMMAND is the command and POINT is the point where the command text
starts.
If the completion was not exact it returns nil."
(defun kom-slow-start-of-line ()
(interactive)
(let* ((text (lyskom-get-entered-slow-command))
(completion-ignore-case t)
(alternatives (mapcar (function (lambda (pair)
(cons (cdr pair) (car pair))))
(lyskom-get-strings
lyskom-commands 'lyskom-command)))
(exact (and try-exact text (lyskom-string-assoc text alternatives)))
(completes (and text (all-completions text alternatives)))
(lyskom-slow-start-of-line))
(defun lyskom-expand-slow-command (try-exact eager-completion)
(let* ((saved-point (point-marker))
(text (lyskom-get-entered-slow-command))
(exact (and text try-exact (lyskom-complete-command text nil 'lambda)))
(completes (and text (all-completions text 'lyskom-complete-command)))
(command nil))
(cond
((null text)
(lyskom-beep t))
((null completes)
(goto-char saved-point)
(lyskom-insert-before-prompt (lyskom-get-string 'no-such-command))
(lyskom-beep t))
(exact
(setq command (cons (cdr exact) (point))))
(setq command (cons (lyskom-lookup-command-by-name text) (point))))
((= (length completes) 1)
(setq command (cons (cdr (assq (car completes) alternatives))
(point)))
(setq command (cons (lyskom-lookup-command-by-name text) (point)))
(delete-region (point) (point-max))
(insert (car completes)))
((> (length completes) 1)
(let ((longest (try-completion text alternatives)))
(let ((longest (try-completion text 'lyskom-complete-command)))
(cond
((eq longest 't)
(delete-region (point) (point-max))
(insert (car completes)))
((stringp longest)
(if (lyskom-string= (upcase longest) (upcase text))
(lyskom-format-insert-before-prompt
'command-completions
(mapconcat 'identity completes "\n ")))
(delete-region (point) (point-max))
(insert longest))
(insert longest)
;; If the completion is the same as the entered string
;; then we either add a space if there was none at the
;; end or list all possible completions *and* add a
;; space (since it has been killed).
(let* ((have-space (string-match "\\s-+$" text))
(text (if have-space (substring text 0 (match-beginning 0)) text))
(longest (if (string-match "\\s-+$" longest)
(substring longest 0 (match-beginning 0))
longest)))
(when (lyskom-string= (lyskom-unicase longest) (lyskom-unicase text))
(if (or have-space eager-completion)
(lyskom-format-insert-before-prompt
'command-completions
(mapconcat 'identity completes "\n ")))
(unless (or eager-completion (eq ?\ (char-before (point))) (insert " "))))
))
(t (signal 'lyskom-internal-error '()))))))
command))
(defun kom-expand-slow-command (&optional try-exact)
"Tries to complete the command at point.
If optional TRY-EXACT is non-nil, look for an exact match.
If the completion was exact return a pair `(COMMAND . POINT)' where
COMMAND is the command and POINT is the point where the command text
starts.
If the completion was not exact it returns nil."
(interactive)
(lyskom-expand-slow-command try-exact t))
(defun kom-expand-slow-or-next-command (&optional try-exact)
"If any part of a slow command has been entered, call
`kom-expand-slow-command'. Otherwise, do `kom-next-command'."
(interactive)
(if (lyskom-get-entered-slow-command)
(kom-expand-slow-command try-exact)
(if (save-excursion (lyskom-get-entered-slow-command))
(lyskom-expand-slow-command try-exact nil)
(buffer-disable-undo)
(kom-next-command)))
(defun kom-parse-command-and-execute ()