slow.el 7.06 KB
Newer Older
David Byers's avatar
David Byers committed
1
;;;;; -*-coding: iso-8859-1;-*-
David Kågedal's avatar
David Kågedal committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
;;;;;
;;;;; $Id$
;;;;; Copyright (C) 1996  Lysator Academic Computer Association.
;;;;;
;;;;; This file is part of the LysKOM server.
;;;;; 
;;;;; LysKOM is free software; you can redistribute it and/or modify it
;;;;; under the terms of the GNU General Public License as published by 
;;;;; the Free Software Foundation; either version 2, or (at your option) 
;;;;; any later version.
;;;;; 
;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT
;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
;;;;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
;;;;; for more details.
;;;;; 
;;;;; You should have received a copy of the GNU General Public License
;;;;; along with LysKOM; see the file COPYING.  If not, write to
;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
;;;;; MA 02139, USA.
;;;;;
;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. 
;;;;;
;;;; ================================================================
;;;; ================================================================
;;;;
;;;; File: slow.el
;;;;
;;;; This file contains the code that makes it possible to run a 
;;;; long-commands mode in the lyskom-buffer.
;;;;
;;;; ================================================================
;;;;

;;; Author: Linus Tolke
;;; Modified by: David Kågedal

(defvar lyskom-slow-mode-map
  (make-sparse-keymap)
  "Mode map for the `slow' lyskom command mode.")

44
45
46
47
48
49
50
51
(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."
David Kågedal's avatar
David Kågedal committed
52
53
  (goto-char (point-max))
  (save-restriction
David Byers's avatar
David Byers committed
54
55
    (when (> lyskom-last-viewed (point-max))
      (setq lyskom-last-viewed (point-max)))
David Kågedal's avatar
David Kågedal committed
56
    (narrow-to-region lyskom-last-viewed (point-max))
David Byers's avatar
David Byers committed
57
58
59
60
61
    (if (search-backward lyskom-current-prompt-text nil t)
        (forward-char (length lyskom-current-prompt-text))
      (goto-char (point-max))
      (beginning-of-line))
    (when (looking-at "\\(\\s-+\\)")
62
63
64
65
66
67
68
69
70
      (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)
David Kågedal's avatar
David Kågedal committed
71
72
73
74
  (if (= (point) (point-max))
      nil
    (buffer-substring (point) (point-max))))

75
(defun kom-slow-start-of-line ()
David Kågedal's avatar
David Kågedal committed
76
  (interactive)
77
78
79
80
81
82
83
  (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)))
David Kågedal's avatar
David Kågedal committed
84
85
86
87
88
	 (command nil))
    (cond
     ((null text)
      (lyskom-beep t))
     ((null completes)
89
      (goto-char saved-point)
David Kågedal's avatar
David Kågedal committed
90
91
      (lyskom-insert-before-prompt (lyskom-get-string 'no-such-command))
      (lyskom-beep t))
David Byers's avatar
David Byers committed
92
     (exact
93
      (setq command (cons (lyskom-lookup-command-by-name text) (point))))
David Kågedal's avatar
David Kågedal committed
94
     ((= (length completes) 1)
95
      (setq command (cons (lyskom-lookup-command-by-name text) (point)))
David Kågedal's avatar
David Kågedal committed
96
97
98
      (delete-region (point) (point-max))
      (insert (car completes)))
     ((> (length completes) 1)
99
      (let ((longest (try-completion text 'lyskom-complete-command)))
David Kågedal's avatar
David Kågedal committed
100
101
102
103
104
105
	(cond
	 ((eq longest 't)
	  (delete-region (point) (point-max))
	  (insert (car completes)))
	 ((stringp longest)
	  (delete-region (point) (point-max))
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
	  (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 " "))))
          ))
David Kågedal's avatar
David Kågedal committed
125
126
127
	 (t (signal 'lyskom-internal-error '()))))))
    command))

128
129
130
131
132
133
134
135
136
137
138
(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))
David Kågedal's avatar
David Kågedal committed
139

David Byers's avatar
David Byers committed
140
(defun kom-expand-slow-or-next-command (&optional try-exact)
David Kågedal's avatar
David Kågedal committed
141
142
143
  "If any part of a slow command has been entered, call
`kom-expand-slow-command'. Otherwise, do `kom-next-command'."
  (interactive)
144
145
  (if (save-excursion (lyskom-get-entered-slow-command))
      (lyskom-expand-slow-command try-exact nil)
David Byers's avatar
David Byers committed
146
    (buffer-disable-undo)
David Kågedal's avatar
David Kågedal committed
147
148
149
150
151
152
    (kom-next-command)))

(defun kom-parse-command-and-execute ()
  "Reads a command from the last line in the buffer and executes it."
  (interactive)
  (let* ((text (lyskom-get-entered-slow-command))
David Byers's avatar
David Byers committed
153
	 (command (and text (kom-expand-slow-command t))))
David Byers's avatar
David Byers committed
154
    (buffer-disable-undo)
David Kågedal's avatar
David Kågedal committed
155
156
157
158
159
160
161
    (cond
     ((null text)
      (call-interactively 'kom-next-command))
     (command
      (delete-region (cdr command) (point-max))
      (call-interactively (car command))))))

162
163
164
165
166
167
168
169
170
171
(defun kom-slow-list-completions ()
  (interactive)
  (save-excursion
    (let* ((text (lyskom-get-entered-slow-command))
           (completes (and text (all-completions text 'lyskom-complete-command))))
      (cond (completes (lyskom-format-insert-before-prompt
                        'command-completions
                        (mapconcat 'identity completes "\n ")))
            (t (lyskom-insert-before-prompt (lyskom-get-string 'no-such-command)))))))

David Kågedal's avatar
David Kågedal committed
172
173
174
175
176

(defun kom-slow-mode ()
  "Starts the slow-command-mode."
  (interactive)
  (lyskom-start-of-command 'kom-slow-mode)
David Byers's avatar
David Byers committed
177
178
179
180
181
  (unless lyskom-slow-mode
    (setq lyskom-saved-read-only buffer-read-only)
    (setq lyskom-slow-mode t)
    (setq buffer-read-only nil)
    (use-local-map lyskom-slow-mode-map))
David Kågedal's avatar
David Kågedal committed
182
183
184
185
186
187
  (lyskom-end-of-command))

(defun kom-quick-mode ()
  "Starts the quick-command-mode."
  (interactive)
  (lyskom-start-of-command 'kom-quick-mode)
David Byers's avatar
David Byers committed
188
189
190
191
  (when lyskom-slow-mode
    (setq buffer-read-only lyskom-saved-read-only)
    (setq lyskom-slow-mode nil)
    (use-local-map lyskom-mode-map))
David Kågedal's avatar
David Kågedal committed
192
193
194
  (lyskom-end-of-command))