(defvar ex-unix-type-shell)
(defvar ex-unix-type-shell-options)
(defvar viper-ex-tmp-buf-name)
+(defvar viper-syntax-preference)
(require 'cl)
(require 'ring)
(require 'viper-init)
+;; A fix for NeXT Step
+;; Should go away, when NS people fix the design flaw, which leaves the
+;; two x-* functions undefined.
+(if (and (not (fboundp 'x-display-color-p)) (fboundp 'ns-display-color-p))
+ (fset 'x-display-color-p (symbol-function 'ns-display-color-p)))
+(if (and (not (fboundp 'x-color-defined-p)) (fboundp 'ns-color-defined-p))
+ (fset 'x-color-defined-p (symbol-function 'ns-color-defined-p)))
+
\f
;;; XEmacs support
-;; A fix for NeXT Step
-;; Should probably be eliminated in later versions.
-(if (and (viper-window-display-p) (eq (viper-device-type) 'ns))
- (progn
- (fset 'x-display-color-p (symbol-function 'ns-display-color-p))
- (fset 'x-color-defined-p (symbol-function 'ns-color-defined-p))
- ))
(if viper-xemacs-p
(progn
(cdr (assoc 'cursor-color (frame-parameters)))
(color-instance-name (frame-property (selected-frame) 'cursor-color))))
-(defun viper-set-face-pixmap (face pixmap)
- "Set face pixmap on a monochrome display."
- (if (and (viper-window-display-p) (not (viper-color-display-p)))
- (condition-case nil
- (set-face-background-pixmap face pixmap)
- (error
- (message "Pixmap not found for %S: %s" (face-name face) pixmap)
- (sit-for 1)))))
-
;; OS/2
(cond ((eq (viper-device-type) 'pm)
(fset 'viper-color-defined-p
(function (lambda (color) (assoc color pm-color-alist))))))
-;; needed to smooth out the difference between Emacs and XEmacs
-(defsubst viper-italicize-face (face)
- (if viper-xemacs-p
- (make-face-italic face)
- (make-face-italic face nil 'noerror)))
-
-;; test if display is color and the colors are defined
-(defsubst viper-can-use-colors (&rest colors)
- (if (viper-color-display-p)
- (not (memq nil (mapcar 'viper-color-defined-p colors)))
- ))
-
-(defun viper-hide-face (face)
- (if (and (viper-has-face-support-p) viper-emacs-p)
- (add-to-list 'facemenu-unlisted-faces face)))
;; cursor colors
(defun viper-change-cursor-color (new-color)
(defsubst viper-restore-cursor-color-after-insert ()
(viper-change-cursor-color viper-saved-cursor-color))
-\f
-;; Face-saving tricks
-
-(defvar viper-search-face
- (if (viper-has-face-support-p)
- (progn
- (make-face 'viper-search-face)
- (viper-hide-face 'viper-search-face)
- (or (face-differs-from-default-p 'viper-search-face)
- ;; face wasn't set in .viper or .Xdefaults
- (if (viper-can-use-colors "Black" "khaki")
- (progn
- (set-face-background 'viper-search-face "khaki")
- (set-face-foreground 'viper-search-face "Black"))
- (set-face-underline-p 'viper-search-face t)
- (viper-set-face-pixmap 'viper-search-face viper-search-face-pixmap)))
- 'viper-search-face))
- "*Face used to flash out the search pattern.")
-
-(defvar viper-replace-overlay-face
- (if (viper-has-face-support-p)
- (progn
- (make-face 'viper-replace-overlay-face)
- (viper-hide-face 'viper-replace-overlay-face)
- (or (face-differs-from-default-p 'viper-replace-overlay-face)
- (progn
- (if (viper-can-use-colors "darkseagreen2" "Black")
- (progn
- (set-face-background
- 'viper-replace-overlay-face "darkseagreen2")
- (set-face-foreground 'viper-replace-overlay-face "Black")))
- (set-face-underline-p 'viper-replace-overlay-face t)
- (viper-set-face-pixmap
- 'viper-replace-overlay-face viper-replace-overlay-pixmap)))
- 'viper-replace-overlay-face))
- "*Face for highlighting replace regions on a window display.")
-
-(defvar viper-minibuffer-emacs-face
- (if (viper-has-face-support-p)
- (progn
- (make-face 'viper-minibuffer-emacs-face)
- (viper-hide-face 'viper-minibuffer-emacs-face)
- (or (face-differs-from-default-p 'viper-minibuffer-emacs-face)
- ;; face wasn't set in .viper or .Xdefaults
- (if viper-vi-style-in-minibuffer
- ;; emacs state is an exception in the minibuffer
- (if (viper-can-use-colors "darkseagreen2" "Black")
- (progn
- (set-face-background
- 'viper-minibuffer-emacs-face "darkseagreen2")
- (set-face-foreground
- 'viper-minibuffer-emacs-face "Black"))
- (copy-face 'modeline 'viper-minibuffer-emacs-face))
- ;; emacs state is the main state in the minibuffer
- (if (viper-can-use-colors "Black" "pink")
- (progn
- (set-face-background 'viper-minibuffer-emacs-face "pink")
- (set-face-foreground
- 'viper-minibuffer-emacs-face "Black"))
- (copy-face 'italic 'viper-minibuffer-emacs-face))
- ))
- 'viper-minibuffer-emacs-face))
- "Face used in the Minibuffer when it is in Emacs state.")
-
-(defvar viper-minibuffer-insert-face
- (if (viper-has-face-support-p)
- (progn
- (make-face 'viper-minibuffer-insert-face)
- (viper-hide-face 'viper-minibuffer-insert-face)
- (or (face-differs-from-default-p 'viper-minibuffer-insert-face)
- (if viper-vi-style-in-minibuffer
- (if (viper-can-use-colors "Black" "pink")
- (progn
- (set-face-background 'viper-minibuffer-insert-face "pink")
- (set-face-foreground
- 'viper-minibuffer-insert-face "Black"))
- (copy-face 'italic 'viper-minibuffer-insert-face))
- ;; If Insert state is an exception
- (if (viper-can-use-colors "darkseagreen2" "Black")
- (progn
- (set-face-background
- 'viper-minibuffer-insert-face "darkseagreen2")
- (set-face-foreground
- 'viper-minibuffer-insert-face "Black"))
- (copy-face 'modeline 'viper-minibuffer-insert-face))
- (viper-italicize-face 'viper-minibuffer-insert-face)))
- 'viper-minibuffer-insert-face))
- "Face used in the Minibuffer when it is in Insert state.")
-
-(defvar viper-minibuffer-vi-face
- (if (viper-has-face-support-p)
- (progn
- (make-face 'viper-minibuffer-vi-face)
- (viper-hide-face 'viper-minibuffer-vi-face)
- (or (face-differs-from-default-p 'viper-minibuffer-vi-face)
- (if viper-vi-style-in-minibuffer
- (if (viper-can-use-colors "Black" "grey")
- (progn
- (set-face-background 'viper-minibuffer-vi-face "grey")
- (set-face-foreground 'viper-minibuffer-vi-face "Black"))
- (copy-face 'bold 'viper-minibuffer-vi-face))
- (copy-face 'bold 'viper-minibuffer-vi-face)
- (invert-face 'viper-minibuffer-vi-face)))
- 'viper-minibuffer-vi-face))
- "Face used in the Minibuffer when it is in Vi state.")
-
-;; the current face to be used in the minibuffer
-(viper-deflocalvar viper-minibuffer-current-face viper-minibuffer-emacs-face "")
\f
;; Check the current version against the major and minor version numbers
(goto-char cur-pos)
result))
+;; Emacs counts each multibyte character as several positions in the buffer, so
+;; we use Emacs' chars-in-region. XEmacs is counting each char as just one pos,
+;; so we can simply subtract.
+(defun viper-chars-in-region (beg end &optional preserve-sign)
+ (let ((count (abs (if (fboundp 'chars-in-region)
+ (chars-in-region beg end)
+ (- end beg)))))
+ (if (and (< end beg) preserve-sign)
+ (- count)
+ count)))
+
+;; Test if POS is between BEG and END
+(defsubst viper-pos-within-region (pos beg end)
+ (and (>= pos (min beg end)) (>= (max beg end) pos)))
+
;; Like move-marker but creates a virgin marker if arg isn't already a marker.
;; The first argument must eval to a variable name.
(let ((buf (find-file-noselect (substitute-in-file-name custom-file))))
(save-excursion
(set-buffer buf)
- (goto-char (point-min))
- (if pattern (delete-matching-lines pattern))
- (goto-char (point-max))
- (if string (insert string))
- (save-buffer))
+ (let (buffer-read-only)
+ (goto-char (point-min))
+ (if pattern (delete-matching-lines pattern))
+ (goto-char (point-max))
+ (if string (insert string))
+ (save-buffer)))
(kill-buffer buf)
))
+
+
+;; define remote file test
+(or (fboundp 'viper-file-remote-p) ; user supplied his own function: use it
+ (defun viper-file-remote-p (file-name)
+ (car (cond ((featurep 'efs-auto) (efs-ftp-path file-name))
+ ((fboundp 'file-remote-p) (file-remote-p file-name))
+ (t (require 'ange-ftp)
+ ;; Can happen only in Emacs, since XEmacs has file-remote-p
+ (ange-ftp-ftp-name file-name))))))
+
+
+
+;; This is a simple-minded check for whether a file is under version control.
+;; If file,v exists but file doesn't, this file is considered to be not checked
+;; in and not checked out for the purpose of patching (since patch won't be
+;; able to read such a file anyway).
+;; FILE is a string representing file name
+;;(defun viper-file-under-version-control (file)
+;; (let* ((filedir (file-name-directory file))
+;; (file-nondir (file-name-nondirectory file))
+;; (trial (concat file-nondir ",v"))
+;; (full-trial (concat filedir trial))
+;; (full-rcs-trial (concat filedir "RCS/" trial)))
+;; (and (stringp file)
+;; (file-exists-p file)
+;; (or
+;; (and
+;; (file-exists-p full-trial)
+;; ;; in FAT FS, `file,v' and `file' may turn out to be the same!
+;; ;; don't be fooled by this!
+;; (not (equal (file-attributes file)
+;; (file-attributes full-trial))))
+;; ;; check if a version is in RCS/ directory
+;; (file-exists-p full-rcs-trial)))
+;; ))
+
+
+(defsubst viper-file-checked-in-p (file)
+ (and (vc-backend file)
+ (not (vc-locking-user file))))
+;; checkout if visited file is checked in
+(defun viper-maybe-checkout (buf)
+ (let ((file (expand-file-name (buffer-file-name buf)))
+ (checkout-function (key-binding "\C-x\C-q")))
+ (if (and (viper-file-checked-in-p file)
+ (or (beep 1) t)
+ (y-or-n-p
+ (format
+ "File %s is checked in. Check it out? "
+ (viper-abbreviate-file-name file))))
+ (with-current-buffer buf
+ (command-execute checkout-function)))))
+
+
\f
;;; Overlays
(defsubst viper-is-in-minibuffer ()
- (string-match "\*Minibuf-" (buffer-name)))
+ (save-match-data
+ (string-match "\*Minibuf-" (buffer-name))))
\f
(cond (viper-xemacs-p (events-to-keys events))
(t events)))
-
-;; This is here because Emacs changed the way local hooks work.
-;;
-;;Add to the value of HOOK the function FUNCTION.
-;;FUNCTION is not added if already present.
-;;FUNCTION is added (if necessary) at the beginning of the hook list
-;;unless the optional argument APPEND is non-nil, in which case
-;;FUNCTION is added at the end.
-;;
-;;HOOK should be a symbol, and FUNCTION may be any valid function. If
-;;HOOK is void, it is first set to nil. If HOOK's value is a single
-;;function, it is changed to a list of functions."
-(defun viper-add-hook (hook function &optional append)
- (if (not (boundp hook)) (set hook nil))
- ;; If the hook value is a single function, turn it into a list.
- (let ((old (symbol-value hook)))
- (if (or (not (listp old)) (eq (car old) 'lambda))
- (setq old (list old)))
- (if (member function old)
- nil
- (set hook (if append
- (append old (list function)) ; don't nconc
- (cons function old))))))
-
-;; This is here because of Emacs's changes in the semantics of add/remove-hooks
-;; and due to the bugs they introduced.
-;;
-;; Remove from the value of HOOK the function FUNCTION.
-;; HOOK should be a symbol, and FUNCTION may be any valid function. If
-;; FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the
-;; list of hooks to run in HOOK, then nothing is done. See `viper-add-hook'."
-(defun viper-remove-hook (hook function)
- (if (or (not (boundp hook)) ;unbound symbol, or
- (null (symbol-value hook)) ;value is nil, or
- (null function)) ;function is nil, then
- nil ;Do nothing.
- (let ((hook-value (symbol-value hook)))
- (if (consp hook-value)
- ;; don't side-effect the list
- (setq hook-value (delete function (copy-sequence hook-value)))
- (if (equal hook-value function)
- (setq hook-value nil)))
- (set hook hook-value))))
-
;; it is suggested that an event must be copied before it is assigned to
;; last-command-event in XEmacs
(defun viper-read-key ()
(let ((overriding-local-map viper-overriding-map)
(inhibit-quit t)
- key)
+ help-char key)
(use-global-map viper-overriding-map)
- (setq key (elt (read-key-sequence nil) 0))
- (use-global-map global-map)
+ (unwind-protect
+ (setq key (elt (read-key-sequence nil) 0))
+ (use-global-map global-map))
key))
;;; Movement utilities
-(defcustom viper-syntax-preference 'strict-vi
- "*Syntax type characterizing Viper's alphanumeric symbols.
-`emacs' means only word constituents are considered to be alphanumeric.
-Word constituents are symbols specified as word constituents by the current
-syntax table.
-`extended' means word and symbol constituents.
-`reformed-vi' means Vi-ish behavior: word constituents and the symbol `_'.
-However, word constituents are determined according to Emacs syntax tables,
-which may be different from Vi in some major modes.
-`strict-vi' means Viper words are exactly as in Vi."
- :type '(radio (const strict-vi) (const reformed-vi)
- (const extended) (const emacs))
- :group 'viper)
+;; Characters that should not be considered as part of the word, in reformed-vi
+;; syntax mode.
+(defconst viper-non-word-characters-reformed-vi
+ "!@#$%^&*()-+=|\\~`{}[];:'\",<.>/?")
+;; These are characters that are not to be considered as parts of a word in
+;; Viper.
+;; Set each time state changes and at loading time
+(viper-deflocalvar viper-non-word-characters nil)
+;; must be buffer-local
(viper-deflocalvar viper-ALPHA-char-class "w"
"String of syntax classes characterizing Viper's alphanumeric symbols.
In addition, the symbol `_' may be considered alphanumeric if
-`viper-syntax-preference'is `reformed-vi'.")
+`viper-syntax-preference' is `strict-vi' or `reformed-vi'.")
-(viper-deflocalvar viper-strict-ALPHA-chars "a-zA-Z0-9_"
+(defconst viper-strict-ALPHA-chars "a-zA-Z0-9_"
"Regexp matching the set of alphanumeric characters acceptable to strict
Vi.")
-(viper-deflocalvar viper-strict-SEP-chars " \t\n"
+(defconst viper-strict-SEP-chars " \t\n"
+ "Regexp matching the set of alphanumeric characters acceptable to strict
+Vi.")
+(defconst viper-strict-SEP-chars-sans-newline " \t"
"Regexp matching the set of alphanumeric characters acceptable to strict
Vi.")
-(viper-deflocalvar viper-SEP-char-class " -"
+(defconst viper-SEP-char-class " -"
"String of syntax classes for Vi separators.
Usually contains ` ', linefeed, TAB or formfeed.")
-(defun viper-update-alphanumeric-class ()
- "Set the syntax class of Viper alphanumerals according to `viper-syntax-preference'.
-Must be called in order for changes to `viper-syntax-preference' to take effect."
+
+;; Set Viper syntax classes and related variables according to
+;; `viper-syntax-preference'.
+(defun viper-update-syntax-classes (&optional set-default)
+ (let ((preference (cond ((eq viper-syntax-preference 'emacs)
+ "w") ; Viper words have only Emacs word chars
+ ((eq viper-syntax-preference 'extended)
+ "w_") ; Viper words have Emacs word & symbol chars
+ (t "w"))) ; Viper words are Emacs words plus `_'
+ (non-word-chars (cond ((eq viper-syntax-preference 'reformed-vi)
+ (viper-string-to-list
+ viper-non-word-characters-reformed-vi))
+ (t nil))))
+ (if set-default
+ (setq-default viper-ALPHA-char-class preference
+ viper-non-word-characters non-word-chars)
+ (setq viper-ALPHA-char-class preference
+ viper-non-word-characters non-word-chars))
+ ))
+
+;; SYMBOL is used because customize requires it, but it is ignored, unless it
+;; is `nil'. If nil, use setq.
+(defun viper-set-syntax-preference (&optional symbol value)
+ "Set Viper syntax preference.
+If called interactively or if SYMBOL is nil, sets syntax preference in current
+buffer. If called non-interactively, preferably via the customization widget,
+sets the default value."
(interactive)
- (setq-default
- viper-ALPHA-char-class
- (cond ((eq viper-syntax-preference 'emacs) "w") ; only word constituents
- ((eq viper-syntax-preference 'extended) "w_") ; word & symbol chars
- (t "w")))) ; vi syntax: word constituents and the symbol `_'
+ (or value
+ (setq value
+ (completing-read
+ "Viper syntax preference: "
+ '(("strict-vi") ("reformed-vi") ("extended") ("emacs"))
+ nil 'require-match)))
+ (if (stringp value) (setq value (intern value)))
+ (or (memq value '(strict-vi reformed-vi extended emacs))
+ (error "Invalid Viper syntax preference, %S" value))
+ (if symbol
+ (setq-default viper-syntax-preference value)
+ (setq viper-syntax-preference value))
+ (viper-update-syntax-classes))
+
+(defcustom viper-syntax-preference 'reformed-vi
+ "*Syntax type characterizing Viper's alphanumeric symbols.
+Affects movement and change commands that deal with Vi-style words.
+Works best when set in the hooks to various major modes.
+
+`strict-vi' means Viper words are (hopefully) exactly as in Vi.
+
+`reformed-vi' means Viper words are like Emacs words \(as determined using
+Emacs syntax tables, which are different for different major modes\) with two
+exceptions: the symbol `_' is always part of a word and typical Vi non-word
+symbols, such as `,',:,\",),{, etc., are excluded.
+This behaves very close to `strict-vi', but also works well with non-ASCII
+characters from various alphabets.
+
+`extended' means Viper word constituents are symbols that are marked as being
+parts of words OR symbols in Emacs syntax tables.
+This is most appropriate for major modes intended for editing programs.
+
+`emacs' means Viper words are the same as Emacs words as specified by Emacs
+syntax tables.
+This option is appropriate if you like Emacs-style words."
+ :type '(radio (const strict-vi) (const reformed-vi)
+ (const extended) (const emacs))
+ :set 'viper-set-syntax-preference
+ :group 'viper)
+(make-variable-buffer-local 'viper-syntax-preference)
+
;; addl-chars are characters to be temporarily considered as alphanumerical
(defun viper-looking-at-alpha (&optional addl-chars)
(if char
(if (eq viper-syntax-preference 'strict-vi)
(looking-at (concat "[" viper-strict-ALPHA-chars addl-chars "]"))
- (or (memq char
- ;; convert string to list
- (append (vconcat addl-chars) nil))
- (memq (char-syntax char)
- (append (vconcat viper-ALPHA-char-class) nil)))))
+ (or
+ ;; or one of the additional chars being asked to include
+ (memq char (viper-string-to-list addl-chars))
+ (and
+ ;; not one of the excluded word chars
+ (not (memq char viper-non-word-characters))
+ ;; char of the Viper-word syntax class
+ (memq (char-syntax char)
+ (viper-string-to-list viper-ALPHA-char-class))))))
))
(defun viper-looking-at-separator ()
(let ((char (char-after (point))))
(if char
- (or (eq char ?\n) ; RET is always a separator in Vi
- (memq (char-syntax char)
- (append (vconcat viper-SEP-char-class) nil))))))
+ (if (eq viper-syntax-preference 'strict-vi)
+ (memq char (viper-string-to-list viper-strict-SEP-chars))
+ (or (eq char ?\n) ; RET is always a separator in Vi
+ (memq (char-syntax char)
+ (viper-string-to-list viper-SEP-char-class)))))
+ ))
(defsubst viper-looking-at-alphasep (&optional addl-chars)
(or (viper-looking-at-separator) (viper-looking-at-alpha addl-chars)))
'forward
(cond ((eq viper-syntax-preference 'strict-vi)
"")
- (t viper-ALPHA-char-class ))
+ (t viper-ALPHA-char-class))
(cond ((eq viper-syntax-preference 'strict-vi)
(concat viper-strict-ALPHA-chars addl-chars))
(t addl-chars))))
'backward
(cond ((eq viper-syntax-preference 'strict-vi)
"")
- (t viper-ALPHA-char-class ))
+ (t viper-ALPHA-char-class))
(cond ((eq viper-syntax-preference 'strict-vi)
(concat viper-strict-ALPHA-chars addl-chars))
(t addl-chars))))
;; weird syntax tables may confuse strict-vi style
(defsubst viper-skip-all-separators-forward (&optional within-line)
- (viper-skip-syntax 'forward
- viper-SEP-char-class
- (or within-line "\n")
- (if within-line (viper-line-pos 'end))))
+ (if (eq viper-syntax-preference 'strict-vi)
+ (if within-line
+ (skip-chars-forward viper-strict-SEP-chars-sans-newline)
+ (skip-chars-forward viper-strict-SEP-chars))
+ (viper-skip-syntax 'forward
+ viper-SEP-char-class
+ (or within-line "\n")
+ (if within-line (viper-line-pos 'end)))))
(defsubst viper-skip-all-separators-backward (&optional within-line)
- (viper-skip-syntax 'backward
- viper-SEP-char-class
- (or within-line "\n")
- (if within-line (viper-line-pos 'start))))
+ (if (eq viper-syntax-preference 'strict-vi)
+ (if within-line
+ (skip-chars-backward viper-strict-SEP-chars-sans-newline)
+ (skip-chars-backward viper-strict-SEP-chars))
+ (viper-skip-syntax 'backward
+ viper-SEP-char-class
+ (or within-line "\n")
+ (if within-line (viper-line-pos 'start)))))
(defun viper-skip-nonseparators (direction)
- (let ((func (intern (format "skip-syntax-%S" direction))))
- (funcall func (concat "^" viper-SEP-char-class)
- (viper-line-pos (if (eq direction 'forward) 'end 'start)))))
+ (viper-skip-syntax
+ direction
+ (concat "^" viper-SEP-char-class)
+ nil
+ (viper-line-pos (if (eq direction 'forward) 'end 'start))))
+
+;; skip over non-word constituents and non-separators
(defun viper-skip-nonalphasep-forward ()
(if (eq viper-syntax-preference 'strict-vi)
(skip-chars-forward
(concat "^" viper-strict-SEP-chars viper-strict-ALPHA-chars))
- (skip-syntax-forward
- (concat
- "^" viper-ALPHA-char-class viper-SEP-char-class) (viper-line-pos 'end))))
+ (viper-skip-syntax
+ 'forward
+ (concat "^" viper-ALPHA-char-class viper-SEP-char-class)
+ ;; Emacs may consider some of these as words, but we don't want them
+ viper-non-word-characters
+ (viper-line-pos 'end))))
(defun viper-skip-nonalphasep-backward ()
(if (eq viper-syntax-preference 'strict-vi)
(skip-chars-backward
(concat "^" viper-strict-SEP-chars viper-strict-ALPHA-chars))
- (skip-syntax-backward
- (concat
- "^"
- viper-ALPHA-char-class viper-SEP-char-class)
+ (viper-skip-syntax
+ 'backward
+ (concat "^" viper-ALPHA-char-class viper-SEP-char-class)
+ ;; Emacs may consider some of these as words, but we don't want them
+ viper-non-word-characters
(viper-line-pos 'start))))
;; Skip SYNTAX like skip-syntax-* and ADDL-CHARS like skip-chars-*
;; Return the number of chars traveled.
-;; Either SYNTAX or ADDL-CHARS can be nil, in which case they are interpreted
-;; as an empty string.
+;; Both SYNTAX or ADDL-CHARS can be strings or lists of characters.
+;; When SYNTAX is "w", then viper-non-word-characters are not considered to be
+;; words, even if Emacs syntax table says they are.
(defun viper-skip-syntax (direction syntax addl-chars &optional limit)
(let ((total 0)
(local 1)
- (skip-chars-func (intern (format "skip-chars-%S" direction)))
- (skip-syntax-func (intern (format "skip-syntax-%S" direction))))
- (or (stringp addl-chars) (setq addl-chars ""))
- (or (stringp syntax) (setq syntax ""))
- (while (and (not (= local 0)) (not (eobp)))
+ (skip-chars-func
+ (if (eq direction 'forward)
+ 'skip-chars-forward 'skip-chars-backward))
+ (skip-syntax-func
+ (if (eq direction 'forward)
+ 'viper-forward-char-carefully 'viper-backward-char-carefully))
+ char-looked-at syntax-of-char-looked-at negated-syntax)
+ (setq addl-chars
+ (cond ((listp addl-chars) (viper-charlist-to-string addl-chars))
+ ((stringp addl-chars) addl-chars)
+ (t "")))
+ (setq syntax
+ (cond ((listp syntax) syntax)
+ ((stringp syntax) (viper-string-to-list syntax))
+ (t nil)))
+ (if (memq ?^ syntax) (setq negated-syntax t))
+
+ (while (and (not (= local 0))
+ (cond ((eq direction 'forward)
+ (not (eobp)))
+ (t (not (bobp)))))
+ (setq char-looked-at (viper-char-at-pos direction)
+ ;; if outside the range, set to nil
+ syntax-of-char-looked-at (if char-looked-at
+ (char-syntax char-looked-at)))
(setq local
- (+ (funcall skip-syntax-func syntax limit)
+ (+ (if (and
+ (cond ((and limit (eq direction 'forward))
+ (< (point) limit))
+ (limit ; backward & limit
+ (> (point) limit))
+ (t t)) ; no limit
+ ;; char under/before cursor has appropriate syntax
+ (if negated-syntax
+ (not (memq syntax-of-char-looked-at syntax))
+ (memq syntax-of-char-looked-at syntax))
+ ;; if char-syntax class is "word", make sure it is not one
+ ;; of the excluded characters
+ (if (and (eq syntax-of-char-looked-at ?w)
+ (not negated-syntax))
+ (not (memq char-looked-at viper-non-word-characters))
+ t))
+ (funcall skip-syntax-func 1)
+ 0)
(funcall skip-chars-func addl-chars limit)))
(setq total (+ total local)))
total