aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPer Abrahamsen1997-06-04 11:40:44 +0000
committerPer Abrahamsen1997-06-04 11:40:44 +0000
commit0ce5b5d5c435b11caaf72068bd6b35338736d02b (patch)
treeedd3c67e03b9536cc655daad409ad6b9ee79e9f0
parent9304909ed21d969e814d6530a5c4ef7ab6813a24 (diff)
downloademacs-0ce5b5d5c435b11caaf72068bd6b35338736d02b.tar.gz
emacs-0ce5b5d5c435b11caaf72068bd6b35338736d02b.zip
Synached with 1.9908.
-rw-r--r--lisp/wid-edit.el169
1 files changed, 118 insertions, 51 deletions
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 260079fe5fe..35c0ffd0e13 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -4,7 +4,7 @@
4;; 4;;
5;; Author: Per Abrahamsen <abraham@dina.kvl.dk> 5;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
6;; Keywords: extensions 6;; Keywords: extensions
7;; Version: 1.9905 7;; Version: 1.9908
8;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ 8;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
@@ -54,7 +54,11 @@
54 "Character position of the end of event if that exists, or nil." 54 "Character position of the end of event if that exists, or nil."
55 (posn-point (event-end event)))) 55 (posn-point (event-end event))))
56 56
57;; The following should go away when bundled with Emacs. 57(defalias 'widget-read-event (if (string-match "XEmacs" emacs-version)
58 'next-event
59 'read-event))
60
61 ;; The following should go away when bundled with Emacs.
58 (condition-case () 62 (condition-case ()
59 (require 'custom) 63 (require 'custom)
60 (error nil)) 64 (error nil))
@@ -122,16 +126,6 @@ is the string or buffer containing the text."
122 :group 'faces 126 :group 'faces
123 :group 'hypermedia) 127 :group 'hypermedia)
124 128
125(defface widget-documentation-face '((((class color)
126 (background dark))
127 (:foreground "lime green"))
128 (((class color)
129 (background light))
130 (:foreground "dark green"))
131 (t nil))
132 "Face used for documentation text."
133 :group 'widgets)
134
135(defface widget-button-face '((t (:bold t))) 129(defface widget-button-face '((t (:bold t)))
136 "Face used for widget buttons." 130 "Face used for widget buttons."
137 :group 'widgets) 131 :group 'widgets)
@@ -262,10 +256,17 @@ minibuffer."
262(defun widget-specify-field (widget from to) 256(defun widget-specify-field (widget from to)
263 "Specify editable button for WIDGET between FROM and TO." 257 "Specify editable button for WIDGET between FROM and TO."
264 (put-text-property from to 'read-only nil) 258 (put-text-property from to 'read-only nil)
259 ;; Terminating space is not part of the field, but necessary in
260 ;; order for local-map to work. Remove next sexp if local-map works
261 ;; at the end of the overlay.
262 (save-excursion
263 (goto-char to)
264 (insert-and-inherit " ")
265 (setq to (point)))
266 (add-text-properties (1- to) to ;to (1+ to)
267 '(front-sticky nil start-open t read-only to))
265 (add-text-properties (1- from) from 268 (add-text-properties (1- from) from
266 '(rear-nonsticky t end-open t read-only from)) 269 '(rear-nonsticky t end-open t read-only from))
267 (add-text-properties to (1+ to)
268 '(front-sticky nil start-open t read-only to))
269 (let ((map (widget-get widget :keymap)) 270 (let ((map (widget-get widget :keymap))
270 (face (or (widget-get widget :value-face) 'widget-field-face)) 271 (face (or (widget-get widget :value-face) 'widget-field-face))
271 (help-echo (widget-get widget :help-echo)) 272 (help-echo (widget-get widget :help-echo))
@@ -353,6 +354,7 @@ minibuffer."
353 (unless (widget-get widget :inactive) 354 (unless (widget-get widget :inactive)
354 (let ((overlay (make-overlay from to nil t nil))) 355 (let ((overlay (make-overlay from to nil t nil)))
355 (overlay-put overlay 'face 'widget-inactive-face) 356 (overlay-put overlay 'face 'widget-inactive-face)
357 (overlay-put overlay 'mouse-face 'widget-inactive-face)
356 (overlay-put overlay 'evaporate t) 358 (overlay-put overlay 'evaporate t)
357 (overlay-put overlay 'priority 100) 359 (overlay-put overlay 'priority 100)
358 (overlay-put overlay (if (string-match "XEmacs" emacs-version) 360 (overlay-put overlay (if (string-match "XEmacs" emacs-version)
@@ -522,22 +524,25 @@ extension (xpm, xbm, gif, jpg, or png) located in
522 (formats widget-image-conversion) 524 (formats widget-image-conversion)
523 file) 525 file)
524 (while (and formats (not file)) 526 (while (and formats (not file))
525 (if (valid-image-instantiator-format-p (car (car formats))) 527 (when (valid-image-instantiator-format-p (car (car formats)))
526 (setq file (locate-file image dirlist 528 (setq file (locate-file image dirlist
527 (mapconcat 'identity 529 (mapconcat 'identity
528 (cdr (car formats)) 530 (cdr (car formats))
529 ":"))) 531 ":"))))
532 (unless file
530 (setq formats (cdr formats)))) 533 (setq formats (cdr formats))))
531 ;; We create a glyph with the file as the default image 534 (and file
532 ;; instantiator, and the TAG fallback 535 ;; We create a glyph with the file as the default image
533 (make-glyph (if file 536 ;; instantiator, and the TAG fallback
534 (list (vector (car (car formats)) ':file file) 537 (make-glyph (list (vector (car (car formats)) ':file file)
535 (vector 'string ':data tag)) 538 (vector 'string ':data tag))))))
536 (vector 'string ':data tag)))))
537 ((valid-instantiator-p image 'image) 539 ((valid-instantiator-p image 'image)
538 ;; A valid image instantiator (e.g. [gif :file "somefile"] etc.) 540 ;; A valid image instantiator (e.g. [gif :file "somefile"] etc.)
539 (make-glyph (list image 541 (make-glyph (list image
540 (vector 'string ':data tag)))) 542 (vector 'string ':data tag))))
543 ((consp image)
544 ;; This could be virtually anything. Let `make-glyph' sort it out.
545 (make-glyph image))
541 (t 546 (t
542 ;; Oh well. 547 ;; Oh well.
543 nil))) 548 nil)))
@@ -554,7 +559,11 @@ glyph is pressed or inactive, respectively.
554WARNING: If you call this with a glyph, and you want the user to be 559WARNING: If you call this with a glyph, and you want the user to be
555able to invoke the glyph, make sure it is unique. If you use the 560able to invoke the glyph, make sure it is unique. If you use the
556same glyph for multiple widgets, invoking any of the glyphs will 561same glyph for multiple widgets, invoking any of the glyphs will
557cause the last created widget to be invoked." 562cause the last created widget to be invoked.
563
564Instead of an instantiator, you can also use a list of instantiators,
565or whatever `make-glyph' will accept. However, in that case you must
566provide the fallback TAG as a part of the instantiator yourself."
558 (let ((glyph (widget-glyph-find image tag))) 567 (let ((glyph (widget-glyph-find image tag)))
559 (if glyph 568 (if glyph
560 (widget-glyph-insert-glyph widget 569 (widget-glyph-insert-glyph widget
@@ -719,9 +728,7 @@ Recommended as a parent keymap for modes using widgets.")
719 728
720(unless widget-keymap 729(unless widget-keymap
721 (setq widget-keymap (make-sparse-keymap)) 730 (setq widget-keymap (make-sparse-keymap))
722 (define-key widget-keymap "\C-k" 'widget-kill-line)
723 (define-key widget-keymap "\t" 'widget-forward) 731 (define-key widget-keymap "\t" 'widget-forward)
724 (define-key widget-keymap "\M-\t" 'widget-backward)
725 (define-key widget-keymap [(shift tab)] 'widget-backward) 732 (define-key widget-keymap [(shift tab)] 'widget-backward)
726 (define-key widget-keymap [backtab] 'widget-backward) 733 (define-key widget-keymap [backtab] 'widget-backward)
727 (if (string-match "XEmacs" emacs-version) 734 (if (string-match "XEmacs" emacs-version)
@@ -743,6 +750,8 @@ Recommended as a parent keymap for modes using widgets.")
743 (setq widget-field-keymap (copy-keymap widget-keymap)) 750 (setq widget-field-keymap (copy-keymap widget-keymap))
744 (unless (string-match "XEmacs" (emacs-version)) 751 (unless (string-match "XEmacs" (emacs-version))
745 (define-key widget-field-keymap [menu-bar] 'nil)) 752 (define-key widget-field-keymap [menu-bar] 'nil))
753 (define-key widget-field-keymap "\C-k" 'widget-kill-line)
754 (define-key widget-field-keymap "\M-\t" 'widget-complete)
746 (define-key widget-field-keymap "\C-m" 'widget-field-activate) 755 (define-key widget-field-keymap "\C-m" 'widget-field-activate)
747 (define-key widget-field-keymap "\C-a" 'widget-beginning-of-line) 756 (define-key widget-field-keymap "\C-a" 'widget-beginning-of-line)
748 (define-key widget-field-keymap "\C-e" 'widget-end-of-line) 757 (define-key widget-field-keymap "\C-e" 'widget-end-of-line)
@@ -788,7 +797,7 @@ Recommended as a parent keymap for modes using widgets.")
788 (if button 797 (if button
789 (let* ((overlay (widget-get button :button-overlay)) 798 (let* ((overlay (widget-get button :button-overlay))
790 (face (overlay-get overlay 'face)) 799 (face (overlay-get overlay 'face))
791 (mouse-face (overlay-get overlay 'face))) 800 (mouse-face (overlay-get overlay 'mouse-face)))
792 (unwind-protect 801 (unwind-protect
793 (let ((track-mouse t)) 802 (let ((track-mouse t))
794 (overlay-put overlay 803 (overlay-put overlay
@@ -797,9 +806,7 @@ Recommended as a parent keymap for modes using widgets.")
797 'mouse-face 'widget-button-pressed-face) 806 'mouse-face 'widget-button-pressed-face)
798 (unless (widget-apply button :mouse-down-action event) 807 (unless (widget-apply button :mouse-down-action event)
799 (while (not (button-release-event-p event)) 808 (while (not (button-release-event-p event))
800 (setq event (if (fboundp 'read-event) 809 (setq event (widget-read-event)
801 (read-event)
802 (next-event))
803 pos (widget-event-point event)) 810 pos (widget-event-point event))
804 (if (and pos 811 (if (and pos
805 (eq (get-char-property pos 'button) 812 (eq (get-char-property pos 'button)
@@ -818,10 +825,25 @@ Recommended as a parent keymap for modes using widgets.")
818 (widget-apply-action button event))) 825 (widget-apply-action button event)))
819 (overlay-put overlay 'face face) 826 (overlay-put overlay 'face face)
820 (overlay-put overlay 'mouse-face mouse-face))) 827 (overlay-put overlay 'mouse-face mouse-face)))
821 (call-interactively 828 (let (command up)
822 (or (lookup-key widget-global-map [ button2 ]) 829 ;; Find the global command to run, and check whether it
823 (lookup-key widget-global-map [ down-mouse-2 ]) 830 ;; is bound to an up event.
824 (lookup-key widget-global-map [ mouse-2])))))) 831 (cond ((setq command ;down event
832 (lookup-key widget-global-map [ button2 ])))
833 ((setq command ;down event
834 (lookup-key widget-global-map [ down-mouse-2 ])))
835 ((setq command ;up event
836 (lookup-key widget-global-map [ button2up ]))
837 (setq up t))
838 ((setq command ;up event
839 (lookup-key widget-global-map [ mouse-2]))
840 (setq up t)))
841 (when command
842 ;; Don't execute up events twice.
843 (when up
844 (while (not (button-release-event-p event))
845 (setq event (widget-read-event))))
846 (call-interactively command))))))
825 (t 847 (t
826 (message "You clicked somewhere weird.")))) 848 (message "You clicked somewhere weird."))))
827 849
@@ -874,7 +896,7 @@ Recommended as a parent keymap for modes using widgets.")
874 "Move point to the ARG next field or button. 896 "Move point to the ARG next field or button.
875ARG may be negative to move backward." 897ARG may be negative to move backward."
876 (or (bobp) (> arg 0) (backward-char)) 898 (or (bobp) (> arg 0) (backward-char))
877 (let ((pos) 899 (let ((pos (point))
878 (number arg) 900 (number arg)
879 (old (or (get-char-property (point) 'button) 901 (old (or (get-char-property (point) 'button)
880 (get-char-property (point) 'field))) 902 (get-char-property (point) 'field)))
@@ -913,7 +935,9 @@ ARG may be negative to move backward."
913 (while (or (get-char-property (point) 'button) 935 (while (or (get-char-property (point) 'button)
914 (get-char-property (point) 'field)) 936 (get-char-property (point) 'field))
915 (backward-char)) 937 (backward-char))
916 (forward-char))) 938 (forward-char))
939 (widget-echo-help (point))
940 (run-hooks 'widget-move-hook))
917 941
918(defun widget-forward (arg) 942(defun widget-forward (arg)
919 "Move point to the next field or button. 943 "Move point to the next field or button.
@@ -932,27 +956,46 @@ With optional ARG, move across that many fields."
932(defun widget-beginning-of-line () 956(defun widget-beginning-of-line ()
933 "Go to beginning of field or beginning of line, whichever is first." 957 "Go to beginning of field or beginning of line, whichever is first."
934 (interactive) 958 (interactive)
935 (let ((bol (save-excursion (beginning-of-line) (point))) 959 (let* ((field (widget-field-find (point)))
936 (prev (previous-single-property-change (point) 'field))) 960 (start (and field (widget-field-start field))))
937 (goto-char (max bol (or prev bol))))) 961 (if (and start (not (eq start (point))))
962 (goto-char start)
963 (call-interactively 'beginning-of-line))))
938 964
939(defun widget-end-of-line () 965(defun widget-end-of-line ()
940 "Go to end of field or end of line, whichever is first." 966 "Go to end of field or end of line, whichever is first."
941 (interactive) 967 (interactive)
942 (let ((bol (save-excursion (end-of-line) (point))) 968 (let* ((field (widget-field-find (point)))
943 (prev (next-single-property-change (point) 'field))) 969 (end (and field (widget-field-end field))))
944 (goto-char (min bol (or prev bol))))) 970 (if (and end (not (eq end (point))))
971 (goto-char end)
972 (call-interactively 'end-of-line))))
945 973
946(defun widget-kill-line () 974(defun widget-kill-line ()
947 "Kill to end of field or end of line, whichever is first." 975 "Kill to end of field or end of line, whichever is first."
948 (interactive) 976 (interactive)
949 (let ((field (get-char-property (point) 'field)) 977 (let* ((field (widget-field-find (point)))
950 (newline (save-excursion (forward-line 1))) 978 (newline (save-excursion (forward-line 1) (point)))
951 (next (next-single-property-change (point) 'field))) 979 (end (and field (widget-field-end field))))
952 (if (and field (> newline next)) 980 (if (and field (> newline end))
953 (kill-region (point) next) 981 (kill-region (point) end)
954 (call-interactively 'kill-line)))) 982 (call-interactively 'kill-line))))
955 983
984(defcustom widget-complete-field (lookup-key global-map "\M-\t")
985 "Default function to call for completion inside fields."
986 :options '(ispell-complete-word complete-tag lisp-complete-symbol)
987 :type 'function
988 :group 'widgets)
989
990(defun widget-complete ()
991 "Complete content of editable field from point.
992When not inside a field, move to the previous button or field."
993 (interactive)
994 (let ((field (widget-field-find (point))))
995 (if field
996 (widget-apply field :complete)
997 (error "Not in an editable field"))))
998
956;;; Setting up the buffer. 999;;; Setting up the buffer.
957 1000
958(defvar widget-field-new nil) 1001(defvar widget-field-new nil)
@@ -1002,7 +1045,8 @@ With optional ARG, move across that many fields."
1002 1045
1003(defun widget-field-end (widget) 1046(defun widget-field-end (widget)
1004 "Return the end of WIDGET's editing field." 1047 "Return the end of WIDGET's editing field."
1005 (overlay-end (widget-get widget :field-overlay))) 1048 ;; Don't subtract one if local-map works at the end of the overlay.
1049 (1- (overlay-end (widget-get widget :field-overlay))))
1006 1050
1007(defun widget-field-find (pos) 1051(defun widget-field-find (pos)
1008 "Return the field at POS. 1052 "Return the field at POS.
@@ -1107,6 +1151,7 @@ Optional EVENT is the event that triggered the action."
1107 :value-to-external (lambda (widget value) value) 1151 :value-to-external (lambda (widget value) value)
1108 :button-prefix 'widget-button-prefix 1152 :button-prefix 'widget-button-prefix
1109 :button-suffix 'widget-button-suffix 1153 :button-suffix 'widget-button-suffix
1154 :complete 'widget-default-complete
1110 :create 'widget-default-create 1155 :create 'widget-default-create
1111 :indent nil 1156 :indent nil
1112 :offset 0 1157 :offset 0
@@ -1126,6 +1171,12 @@ Optional EVENT is the event that triggered the action."
1126 :notify 'widget-default-notify 1171 :notify 'widget-default-notify
1127 :prompt-value 'widget-default-prompt-value) 1172 :prompt-value 'widget-default-prompt-value)
1128 1173
1174(defun widget-default-complete (widget)
1175 "Call the value of the :complete-function property of WIDGET.
1176If that does not exists, call the value of `widget-complete-field'."
1177 (let ((fun (widget-get widget :complete-function)))
1178 (call-interactively (or fun widget-complete-field))))
1179
1129(defun widget-default-create (widget) 1180(defun widget-default-create (widget)
1130 "Create WIDGET at point in the current buffer." 1181 "Create WIDGET at point in the current buffer."
1131 (widget-specify-insert 1182 (widget-specify-insert
@@ -2417,6 +2468,16 @@ when he invoked the menu."
2417 2468
2418;;; The `documentation-string' Widget. 2469;;; The `documentation-string' Widget.
2419 2470
2471(defface widget-documentation-face '((((class color)
2472 (background dark))
2473 (:foreground "lime green"))
2474 (((class color)
2475 (background light))
2476 (:foreground "dark green"))
2477 (t nil))
2478 "Face used for documentation text."
2479 :group 'widgets)
2480
2420(define-widget 'documentation-string 'item 2481(define-widget 'documentation-string 'item
2421 "A documentation string." 2482 "A documentation string."
2422 :format "%v" 2483 :format "%v"
@@ -2431,8 +2492,10 @@ when he invoked the menu."
2431 (if (string-match "\n" doc) 2492 (if (string-match "\n" doc)
2432 (let ((before (substring doc 0 (match-beginning 0))) 2493 (let ((before (substring doc 0 (match-beginning 0)))
2433 (after (substring doc (match-beginning 0))) 2494 (after (substring doc (match-beginning 0)))
2495 (start (point))
2434 buttons) 2496 buttons)
2435 (insert before " ") 2497 (insert before " ")
2498 (widget-specify-doc widget start (point))
2436 (push (widget-create-child-and-convert 2499 (push (widget-create-child-and-convert
2437 widget 'visibility 2500 widget 'visibility
2438 :off nil 2501 :off nil
@@ -2440,7 +2503,9 @@ when he invoked the menu."
2440 shown) 2503 shown)
2441 buttons) 2504 buttons)
2442 (when shown 2505 (when shown
2443 (insert after)) 2506 (setq start (point))
2507 (insert after)
2508 (widget-specify-doc widget start (point)))
2444 (widget-put widget :buttons buttons)) 2509 (widget-put widget :buttons buttons))
2445 (insert doc))) 2510 (insert doc)))
2446 (insert "\n")) 2511 (insert "\n"))
@@ -2484,6 +2549,7 @@ when he invoked the menu."
2484 "A string" 2549 "A string"
2485 :tag "String" 2550 :tag "String"
2486 :format "%{%t%}: %v" 2551 :format "%{%t%}: %v"
2552 :complete-function 'ispell-complete-word
2487 :prompt-history 'widget-string-prompt-value-history) 2553 :prompt-history 'widget-string-prompt-value-history)
2488 2554
2489(define-widget 'regexp 'string 2555(define-widget 'regexp 'string
@@ -2582,6 +2648,7 @@ It will read a directory name from the minibuffer when invoked."
2582 2648
2583(define-widget 'function 'sexp 2649(define-widget 'function 'sexp
2584 "A lisp function." 2650 "A lisp function."
2651 :complete-function 'lisp-complete-symbol
2585 :prompt-value 'widget-field-prompt-value 2652 :prompt-value 'widget-field-prompt-value
2586 :prompt-internal 'widget-symbol-prompt-internal 2653 :prompt-internal 'widget-symbol-prompt-internal
2587 :prompt-match 'fboundp 2654 :prompt-match 'fboundp