]> code.delx.au - gnu-emacs/blobdiff - lisp/emulation/viper-ex.el
new version
[gnu-emacs] / lisp / emulation / viper-ex.el
index 8e35403e5703d24bddb3ac07ade7e8acd7ef05d7..4b29dc1465e70476d576dfcef64a6f88d6186096 100644 (file)
 (defvar vip-ex-history)
 (defvar vip-related-files-and-buffers-ring)
 (defvar vip-local-search-start-marker)
-(defvar vip-expert-level)
+(defvar viper-expert-level)
 (defvar vip-custom-file-name)
 (defvar vip-case-fold-search)
-
-(eval-when-compile
-  (let ((load-path (cons (expand-file-name ".") load-path)))
-    (or (featurep 'viper-util)
-       (load "viper-util.el" nil nil 'nosuffix))
-    (or (featurep 'viper-keym)
-       (load "viper-keym.el" nil nil 'nosuffix))
-    (or (featurep 'viper)
-       (load "viper.el" nil nil 'nosuffix))
-    ))
+(defvar explicit-shell-file-name)
+
+;; loading happens only in non-interactive compilation
+;; in order to spare non-viperized emacs from being viperized
+(if noninteractive
+    (eval-when-compile
+      (let ((load-path (cons (expand-file-name ".") load-path)))
+       (or (featurep 'viper-util)
+           (load "viper-util.el" nil nil 'nosuffix))
+       (or (featurep 'viper-keym)
+           (load "viper-keym.el" nil nil 'nosuffix))
+       (or (featurep 'viper-cmd)
+           (load "viper-cmd.el" nil nil 'nosuffix))
+       )))
 ;; end pacifier
 
 (require 'viper-util)
 
+(defgroup viper-ex nil
+  "Viper support for Ex commands"
+  :prefix "ex-"
+  :group 'viper)
+
+
 
 ;;; Variables
 
 ;; A-list of Ex variables that can be set using the :set command.
 (defconst ex-variable-alist 
   '(("wrapscan") ("ws") ("wrapmargin") ("wm")
-    ("global-tabstop") ("gts") ("tabstop") ("ts")
+    ("tabstop-global") ("ts-g") ("tabstop") ("ts")
     ("showmatch") ("sm") ("shiftwidth") ("sw") ("shell") ("sh")
     ("readonly") ("ro") 
     ("nowrapscan") ("nows") ("noshowmatch") ("nosm")
     ("noreadonly") ("noro") ("nomagic") ("noma")
     ("noignorecase") ("noic")
-    ("global-noautoindent") ("gnoai") ("noautoindent") ("noai")
+    ("noautoindent-global") ("noai-g") ("noautoindent") ("noai")
     ("magic") ("ma") ("ignorecase") ("ic")
-    ("global-autoindent") ("gai") ("autoindent") ("ai")
+    ("autoindent-global") ("ai-g") ("autoindent") ("ai") 
+    ("all") 
     ))
 
   
 ;; Value of ex count.
 (defvar ex-count nil)
 
-;; Flag for global command.
+;; Flag indicating that :global Ex command is being executed.
 (defvar ex-g-flag nil)
-
-;; If t, global command is executed on lines not matching ex-g-pat.
+;; Flag indicating that :vglobal Ex command is being executed.
 (defvar ex-g-variant nil)
 
 ;; Save reg-exp used in substitute.
 ;; Pattern for global command.
 (defvar ex-g-pat nil)
 
-
-(defvar ex-unix-type-shell
+(defcustom ex-unix-type-shell
   (let ((case-fold-search t))
     (and (stringp shell-file-name)
         (string-match
           "bash$\\|bash.exe$"
           "\\)")
          shell-file-name)))
-  "Is the user using a unix-type shell?")
+  "Is the user using a unix-type shell under a non-OS?"
+  :type 'string
+  :group 'viper-ex)
 
-(defvar ex-unix-type-shell-options
+(defcustom ex-unix-type-shell-options
   (let ((case-fold-search t))
     (if ex-unix-type-shell
        (cond ((string-match "\\(csh$\\|csh.exe$\\)" shell-file-name)
               "-noprofile") ; bash: ignore .profile
              )))
   "Options to pass to the Unix-style shell. 
-Don't put `-c' here, as it is added automatically.")
+Don't put `-c' here, as it is added automatically."
+  :type 'string
+  :group 'viper-ex)
 
 (defvar ex-nontrivial-find-file-function
   (cond (ex-unix-type-shell 'vip-ex-nontrivial-find-file-unix)
@@ -185,13 +198,17 @@ Don't put `-c' here, as it is added automatically.")
 ;; multiple file names. Used for :edit and :next
 (defvar vip-keep-reading-filename nil)
 
-(defconst ex-cycle-other-window t
+(defcustom ex-cycle-other-window t
   "*If t, :n and :b cycles through files and buffers in other window.
 Then :N and :B cycles in the current window. If nil, this behavior is
-reversed.")
+reversed."
+  :type 'boolean
+  :group 'viper-ex)
 
-(defconst ex-cycle-through-non-files nil
-  "*Cycle through *scratch* and other buffers that don't visit any file.")
+(defcustom ex-cycle-through-non-files nil
+  "*Cycle through *scratch* and other buffers that don't visit any file."
+  :type 'boolean
+  :group 'viper-ex)
 
 ;; Last shell command executed with :! command.
 (defvar vip-ex-last-shell-com nil)
@@ -422,7 +439,7 @@ reversed.")
                      "*[ \t]*$"))
        (stay-regex (concat
                     "\\(" "^[ \t]*$"
-                    "\\|" "[?/].*[?/].*"
+                    "\\|" "[?/].*"
                     "\\|" "[ktgjmsz][ \t]*$"
                     "\\|" "^[ \t]*ab.*"
                     "\\|" "tr[ansfer \t]*"
@@ -498,7 +515,6 @@ reversed.")
     
 
 ;; Read Ex commands 
-;; Ex commands themselves are implemented in viper-ex.el
 (defun vip-ex (&optional string)
   (interactive)
   (or string
@@ -608,7 +624,15 @@ reversed.")
            (setq ex-token
                  (if (= (mark t) (point)) ""
                    (buffer-substring (1- (point)) (mark t))))
-           (backward-char 1))
+           (backward-char 1)
+           ;; if the user doesn't specify the final pattern delimiter, we're
+           ;; at newline now. In this case, insert the initial delimiter
+           ;; specified in variable c
+           (if (looking-at "\n")
+               (progn
+                   (insert c)
+                     (backward-char 1)))
+           )
        (setq ex-token nil))
       c)))
 
@@ -1228,6 +1252,14 @@ reversed.")
 
 
 ;; Ex global command
+;; This is executed in response to:
+;;             :global "pattern" ex-command
+;;             :vglobal "pattern" ex-command
+;; :global executes ex-command on all lines matching <pattern>
+;; :vglobal executes ex-command on all lines that don't match <pattern>
+;;
+;; With VARIANT nil, this functions executes :global
+;; With VARIANT t, executes :vglobal
 (defun ex-global (variant)
   (let ((gcommand ex-token))
     (if (or ex-g-flag ex-g-variant)
@@ -1250,8 +1282,11 @@ reversed.")
   (if (null ex-addresses)
       (setq ex-addresses (list (point-max) (point-min)))
     (vip-default-ex-addresses))
-  (let ((marks nil) (mark-count 0)
-       com-str (end (car ex-addresses)) (beg (car (cdr ex-addresses))))
+  (let ((marks nil)
+       (mark-count 0)
+       (end (car ex-addresses))
+       (beg (car (cdr ex-addresses)))
+       com-str)
     (if (> beg end) (error vip-FirstAddrExceedsSecond))
     (save-excursion
       (vip-enlarge-region beg end)
@@ -1487,7 +1522,7 @@ reversed.")
     (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name)) 
     (set-buffer vip-ex-work-buf)
     (if (looking-at "!") (forward-char 1)))
-  (if (< vip-expert-level 3)
+  (if (< viper-expert-level 3)
       (save-buffers-kill-emacs)
     (kill-buffer (current-buffer))))
 
@@ -1561,7 +1596,7 @@ reversed.")
     (while (string-match "^[ \\t\\n]*$"
                         (setq str
                               (completing-read ":set " ex-variable-alist)))
-      (message ":set <Variable> ")
+      (message ":set <Variable> [= <Value>]")
       ;; if there are unread events, don't wait
       (or (vip-set-unread-command-events "") (sit-for 2))
       ) ; while
@@ -1579,12 +1614,15 @@ reversed.")
        actual-lisp-cmd lisp-cmd-del-pattern
        val2 orig-var)
     (setq orig-var var)
-    (cond ((member var '("ai" "autoindent"))
+    (cond ((string= var "all")
+          (setq ask-if-save nil
+                set-cmd nil))
+         ((member var '("ai" "autoindent"))
           (setq var "vip-auto-indent"
                 set-cmd "setq"
                 ask-if-save nil
                 val "t"))
-         ((member var '("gai" "global-autoindent"))
+         ((member var '("ai-g" "autoindent-global"))
           (kill-local-variable 'vip-auto-indent)
           (setq var "vip-auto-indent"
                 set-cmd "setq-default"
@@ -1593,7 +1631,7 @@ reversed.")
           (setq var "vip-auto-indent"
                 ask-if-save nil
                 val "nil"))
-         ((member var '("gnoai" "global-noautoindent"))
+         ((member var '("noai-g" "noautoindent-global"))
           (kill-local-variable 'vip-auto-indent)
           (setq var "vip-auto-indent"
                 set-cmd "setq-default"
@@ -1607,7 +1645,7 @@ reversed.")
          ((member var '("ma" "magic"))
           (setq var "vip-re-search"
                 val "t"))
-         ((member var '("noma" "nomagic"))
+         ((member var '("noma" "nomagic"))
           (setq var "vip-re-search"
                 val "nil"))
          ((member var '("ro" "readonly"))
@@ -1628,7 +1666,7 @@ reversed.")
          ((member var '("nows" "nowrapscan"))
           (setq var "vip-search-wrap-around-t"
                 val "nil")))
-    (if (eq val 0) ; value must be set by the user
+    (if (and set-cmd (eq val 0)) ; value must be set by the user
        (let ((cursor-in-echo-area t))
          (message ":set %s = <Value>" var)
          ;; if there are unread events, don't wait
@@ -1640,7 +1678,7 @@ reversed.")
          (if (member var
                      '("sw" "shiftwidth"
                        "ts" "tabstop"
-                       "gts" "global-tabstop"
+                       "ts-g" "tabstop-global"
                        "wm" "wrapmargin")) 
              (condition-case nil
                  (or (numberp (setq val2 (car (read-from-string val))))
@@ -1656,7 +1694,7 @@ reversed.")
            (setq var "tab-width"
                  set-cmd "setq"
                  ask-if-save nil))
-          ((member var '("gts" "global-tabstop"))
+          ((member var '("ts-g" "tabstop-global"))
            (kill-local-variable 'tab-width)
            (setq var "tab-width"
                  set-cmd "setq-default"))
@@ -1671,11 +1709,12 @@ reversed.")
                  val (format "\"%s\"" val)))))
       (ex-fixup-history "set" orig-var))
     
-    (setq actual-lisp-cmd (format "\n(%s %s %s) %s"
-                                 set-cmd var val auto-cmd-label))
-    (setq lisp-cmd-del-pattern
-         (format "^\n?[ \t]*([ \t]*%s[ \t]+%s[ \t].*)[ \t]*%s"
-                 set-cmd var auto-cmd-label))
+    (if set-cmd
+       (setq actual-lisp-cmd
+             (format "\n(%s %s %s) %s" set-cmd var val auto-cmd-label)
+             lisp-cmd-del-pattern
+             (format "^\n?[ \t]*([ \t]*%s[ \t]+%s[ \t].*)[ \t]*%s"
+                     set-cmd var auto-cmd-label)))
     
     (if (and ask-if-save
             (y-or-n-p (format "Do you want to save this setting in %s "
@@ -1702,15 +1741,19 @@ reversed.")
                ))
          ))
     
-    (message "%s %s %s" set-cmd var (if (string-match "^[ \t]*$" val)
-                                       (format "%S" val)
-                                     val))
-    (eval (car (read-from-string actual-lisp-cmd)))
-       (if (string= var "fill-column")
-               (if (> val2 0)
-                       (auto-fill-mode 1)
-                 (auto-fill-mode -1)))
-               
+    (if set-cmd
+       (message "%s %s %s"
+                set-cmd var
+                (if (string-match "^[ \t]*$" val)
+                    (format "%S" val)
+                  val)))
+    (if actual-lisp-cmd
+       (eval (car (read-from-string actual-lisp-cmd))))
+    (if (string= var "fill-column")
+       (if (> val2 0)
+           (auto-fill-mode 1)
+         (auto-fill-mode -1)))
+    (if (string= var "all") (ex-show-vars))
     ))
 
 ;; In inline args, skip regex-forw and (optionally) chars-back.
@@ -1971,7 +2014,7 @@ Please contact your system administrator. "
          (not writing-same-file)
          (set-buffer-modified-p t))
       (if q-flag
-         (if (< vip-expert-level 2)
+         (if (< viper-expert-level 2)
              (save-buffers-kill-emacs)
            (kill-buffer (current-buffer))))
       )))
@@ -2074,5 +2117,32 @@ Please contact your system administrator. "
        (kill-buffer " *vip-info*")))
     ))
 
+;; display all variables set through :set
+(defun ex-show-vars ()
+  (with-output-to-temp-buffer " *vip-info*"
+    (princ (if vip-auto-indent
+              "autoindent (local)\n" "noautoindent (local)\n"))
+    (princ (if (default-value 'vip-auto-indent) 
+              "autoindent (global) \n" "noautoindent (global) \n"))
+    (princ (if vip-case-fold-search "ignorecase\n" "noignorecase\n"))
+    (princ (if vip-re-search "magic\n" "nomagic\n"))
+    (princ (if buffer-read-only "readonly\n" "noreadonly\n"))
+    (princ (if blink-matching-paren "showmatch\n" "noshowmatch\n"))
+    (princ (if vip-search-wrap-around-t "wrapscan\n" "nowrapscan\n"))
+    (princ (format "shiftwidth \t\t= %S\n" vip-shift-width))
+    (princ (format "tabstop (local) \t= %S\n" tab-width))
+    (princ (format "tabstop (global) \t= %S\n" (default-value 'tab-width)))
+    (princ (format "wrapmargin (local) \t= %S\n"
+                  (- (window-width) fill-column)))
+    (princ (format "wrapmargin (global) \t= %S\n"
+                  (- (window-width) (default-value 'fill-column))))
+    (princ (format "shell \t\t\t= %S\n" (if (boundp 'explicit-shell-file-name)
+                                           explicit-shell-file-name
+                                         'none)))
+    ))
+
+
+
+
 
 ;;;  viper-ex.el ends here