comparison lisp/emulation/viper-util.el @ 19462:a3240ad2e954

new version
author Michael Kifer <kifer@cs.stonybrook.edu>
date Fri, 22 Aug 1997 03:15:57 +0000
parents eb1cef5fa337
children f7e788ea680b
comparison
equal deleted inserted replaced
19461:6b67f20dd710 19462:a3240ad2e954
33 (defvar viper-replace-overlay-face) 33 (defvar viper-replace-overlay-face)
34 (defvar viper-fast-keyseq-timeout) 34 (defvar viper-fast-keyseq-timeout)
35 (defvar ex-unix-type-shell) 35 (defvar ex-unix-type-shell)
36 (defvar ex-unix-type-shell-options) 36 (defvar ex-unix-type-shell-options)
37 (defvar viper-ex-tmp-buf-name) 37 (defvar viper-ex-tmp-buf-name)
38 (defvar viper-syntax-preference)
38 39
39 (require 'cl) 40 (require 'cl)
40 (require 'ring) 41 (require 'ring)
41 42
42 (if noninteractive 43 (if noninteractive
213 (back-to-indentation)) 214 (back-to-indentation))
214 (t nil)) 215 (t nil))
215 (setq result (point)) 216 (setq result (point))
216 (goto-char cur-pos) 217 (goto-char cur-pos)
217 result)) 218 result))
219
220 ;; Emacs counts each multibyte character as several positions in the buffer, so
221 ;; we use Emacs' chars-in-region. XEmacs is counting each char as just one pos,
222 ;; so we can simply subtract.
223 (defun viper-chars-in-region (beg end &optional preserve-sign)
224 (let ((count (abs (if (fboundp 'chars-in-region)
225 (chars-in-region beg end)
226 (- end beg)))))
227 (if (and (< end beg) preserve-sign)
228 (- count)
229 count)))
230
231 ;; Test if POS is between BEG and END
232 (defsubst viper-pos-within-region (pos beg end)
233 (and (>= pos (min beg end)) (>= (max beg end) pos)))
218 234
219 235
220 ;; Like move-marker but creates a virgin marker if arg isn't already a marker. 236 ;; Like move-marker but creates a virgin marker if arg isn't already a marker.
221 ;; The first argument must eval to a variable name. 237 ;; The first argument must eval to a variable name.
222 ;; Arguments: (var-name position &optional buffer). 238 ;; Arguments: (var-name position &optional buffer).
1056 (viper-ring-insert viper-related-files-and-buffers-ring (buffer-name)) 1072 (viper-ring-insert viper-related-files-and-buffers-ring (buffer-name))
1057 ) 1073 )
1058 1074
1059 ;;; Movement utilities 1075 ;;; Movement utilities
1060 1076
1061 (defcustom viper-syntax-preference 'strict-vi 1077 ;; Characters that should not be considered as part of the word, in reformed-vi
1062 "*Syntax type characterizing Viper's alphanumeric symbols. 1078 ;; syntax mode.
1063 `emacs' means only word constituents are considered to be alphanumeric. 1079 (defconst viper-non-word-characters-reformed-vi
1064 Word constituents are symbols specified as word constituents by the current 1080 "!@#$%^&*()-+=|\\~`{}[];:'\",<.>/?")
1065 syntax table. 1081 ;; These are characters that are not to be considered as parts of a word in
1066 `extended' means word and symbol constituents. 1082 ;; Viper.
1067 `reformed-vi' means Vi-ish behavior: word constituents and the symbol `_'. 1083 ;; Set each time state changes and at loading time
1068 However, word constituents are determined according to Emacs syntax tables, 1084 (viper-deflocalvar viper-non-word-characters nil)
1069 which may be different from Vi in some major modes. 1085
1070 `strict-vi' means Viper words are exactly as in Vi." 1086 ;; must be buffer-local
1071 :type '(radio (const strict-vi) (const reformed-vi)
1072 (const extended) (const emacs))
1073 :group 'viper)
1074
1075 (viper-deflocalvar viper-ALPHA-char-class "w" 1087 (viper-deflocalvar viper-ALPHA-char-class "w"
1076 "String of syntax classes characterizing Viper's alphanumeric symbols. 1088 "String of syntax classes characterizing Viper's alphanumeric symbols.
1077 In addition, the symbol `_' may be considered alphanumeric if 1089 In addition, the symbol `_' may be considered alphanumeric if
1078 `viper-syntax-preference'is `reformed-vi'.") 1090 `viper-syntax-preference' is `strict-vi' or `reformed-vi'.")
1079 1091
1080 (viper-deflocalvar viper-strict-ALPHA-chars "a-zA-Z0-9_" 1092 (defconst viper-strict-ALPHA-chars "a-zA-Z0-9_"
1081 "Regexp matching the set of alphanumeric characters acceptable to strict 1093 "Regexp matching the set of alphanumeric characters acceptable to strict
1082 Vi.") 1094 Vi.")
1083 (viper-deflocalvar viper-strict-SEP-chars " \t\n" 1095 (defconst viper-strict-SEP-chars " \t\n"
1084 "Regexp matching the set of alphanumeric characters acceptable to strict 1096 "Regexp matching the set of alphanumeric characters acceptable to strict
1085 Vi.") 1097 Vi.")
1086 1098 (defconst viper-strict-SEP-chars-sans-newline " \t"
1087 (viper-deflocalvar viper-SEP-char-class " -" 1099 "Regexp matching the set of alphanumeric characters acceptable to strict
1100 Vi.")
1101
1102 (defconst viper-SEP-char-class " -"
1088 "String of syntax classes for Vi separators. 1103 "String of syntax classes for Vi separators.
1089 Usually contains ` ', linefeed, TAB or formfeed.") 1104 Usually contains ` ', linefeed, TAB or formfeed.")
1090 1105
1091 (defun viper-update-alphanumeric-class () 1106
1092 "Set the syntax class of Viper alphanumerals according to `viper-syntax-preference'. 1107 ;; Set Viper syntax classes and related variables according to
1093 Must be called in order for changes to `viper-syntax-preference' to take effect." 1108 ;; `viper-syntax-preference'.
1109 (defun viper-update-syntax-classes (&optional set-default)
1110 (let ((preference (cond ((eq viper-syntax-preference 'emacs)
1111 "w") ; Viper words have only Emacs word chars
1112 ((eq viper-syntax-preference 'extended)
1113 "w_") ; Viper words have Emacs word & symbol chars
1114 (t "w"))) ; Viper words are Emacs words plus `_'
1115 (non-word-chars (cond ((eq viper-syntax-preference 'reformed-vi)
1116 (viper-string-to-list
1117 viper-non-word-characters-reformed-vi))
1118 (t nil))))
1119 (if set-default
1120 (setq-default viper-ALPHA-char-class preference
1121 viper-non-word-characters non-word-chars)
1122 (setq viper-ALPHA-char-class preference
1123 viper-non-word-characters non-word-chars))
1124 ))
1125
1126 ;; SYMBOL is used because customize requires it, but it is ignored, unless it
1127 ;; is `nil'. If nil, use setq.
1128 (defun viper-set-syntax-preference (&optional symbol value)
1129 "Set Viper syntax preference.
1130 If called interactively or if SYMBOL is nil, sets syntax preference in current
1131 buffer. If called non-interactively, preferably via the customization widget,
1132 sets the default value."
1094 (interactive) 1133 (interactive)
1095 (setq-default 1134 (or value
1096 viper-ALPHA-char-class 1135 (setq value
1097 (cond ((eq viper-syntax-preference 'emacs) "w") ; only word constituents 1136 (completing-read
1098 ((eq viper-syntax-preference 'extended) "w_") ; word & symbol chars 1137 "Viper syntax preference: "
1099 (t "w")))) ; vi syntax: word constituents and the symbol `_' 1138 '(("strict-vi") ("reformed-vi") ("extended") ("emacs"))
1139 nil 'require-match)))
1140 (if (stringp value) (setq value (intern value)))
1141 (or (memq value '(strict-vi reformed-vi extended emacs))
1142 (error "Invalid Viper syntax preference, %S" value))
1143 (if symbol
1144 (setq-default viper-syntax-preference value)
1145 (setq viper-syntax-preference value))
1146 (viper-update-syntax-classes))
1147
1148 (defcustom viper-syntax-preference 'reformed-vi
1149 "*Syntax type characterizing Viper's alphanumeric symbols.
1150 Affects movement and change commands that deal with Vi-style words.
1151 Works best when set in the hooks to various major modes.
1152
1153 `strict-vi' means Viper words are (hopefully) exactly as in Vi.
1154
1155 `reformed-vi' means Viper words are like Emacs words \(as determined using
1156 Emacs syntax tables, which are different for different major modes\) with two
1157 exceptions: the symbol `_' is always part of a word and typical Vi non-word
1158 symbols, such as `,',:,\",),{, etc., are excluded.
1159 This behaves very close to `strict-vi', but also works well with non-ASCII
1160 characters from various alphabets.
1161
1162 `extended' means Viper word constituents are symbols that are marked as being
1163 parts of words OR symbols in Emacs syntax tables.
1164 This is most appropriate for major modes intended for editing programs.
1165
1166 `emacs' means Viper words are the same as Emacs words as specified by Emacs
1167 syntax tables.
1168 This option is appropriate if you like Emacs-style words."
1169 :type '(radio (const strict-vi) (const reformed-vi)
1170 (const extended) (const emacs))
1171 :set 'viper-set-syntax-preference
1172 :group 'viper)
1173 (make-variable-buffer-local 'viper-syntax-preference)
1174
1100 1175
1101 ;; addl-chars are characters to be temporarily considered as alphanumerical 1176 ;; addl-chars are characters to be temporarily considered as alphanumerical
1102 (defun viper-looking-at-alpha (&optional addl-chars) 1177 (defun viper-looking-at-alpha (&optional addl-chars)
1103 (or (stringp addl-chars) (setq addl-chars "")) 1178 (or (stringp addl-chars) (setq addl-chars ""))
1104 (if (eq viper-syntax-preference 'reformed-vi) 1179 (if (eq viper-syntax-preference 'reformed-vi)
1105 (setq addl-chars (concat addl-chars "_"))) 1180 (setq addl-chars (concat addl-chars "_")))
1106 (let ((char (char-after (point)))) 1181 (let ((char (char-after (point))))
1107 (if char 1182 (if char
1108 (if (eq viper-syntax-preference 'strict-vi) 1183 (if (eq viper-syntax-preference 'strict-vi)
1109 (looking-at (concat "[" viper-strict-ALPHA-chars addl-chars "]")) 1184 (looking-at (concat "[" viper-strict-ALPHA-chars addl-chars "]"))
1110 (or (memq char 1185 (or
1111 ;; convert string to list 1186 ;; or one of the additional chars being asked to include
1112 (append (vconcat addl-chars) nil)) 1187 (memq char (viper-string-to-list addl-chars))
1113 (memq (char-syntax char) 1188 (and
1114 (append (vconcat viper-ALPHA-char-class) nil))))) 1189 ;; not one of the excluded word chars
1190 (not (memq char viper-non-word-characters))
1191 ;; char of the Viper-word syntax class
1192 (memq (char-syntax char)
1193 (viper-string-to-list viper-ALPHA-char-class))))))
1115 )) 1194 ))
1116 1195
1117 (defun viper-looking-at-separator () 1196 (defun viper-looking-at-separator ()
1118 (let ((char (char-after (point)))) 1197 (let ((char (char-after (point))))
1119 (if char 1198 (if char
1120 (or (eq char ?\n) ; RET is always a separator in Vi 1199 (if (eq viper-syntax-preference 'strict-vi)
1121 (memq (char-syntax char) 1200 (memq char (viper-string-to-list viper-strict-SEP-chars))
1122 (append (vconcat viper-SEP-char-class) nil)))))) 1201 (or (eq char ?\n) ; RET is always a separator in Vi
1202 (memq (char-syntax char)
1203 (viper-string-to-list viper-SEP-char-class)))))
1204 ))
1123 1205
1124 (defsubst viper-looking-at-alphasep (&optional addl-chars) 1206 (defsubst viper-looking-at-alphasep (&optional addl-chars)
1125 (or (viper-looking-at-separator) (viper-looking-at-alpha addl-chars))) 1207 (or (viper-looking-at-separator) (viper-looking-at-alpha addl-chars)))
1126 1208
1127 (defun viper-skip-alpha-forward (&optional addl-chars) 1209 (defun viper-skip-alpha-forward (&optional addl-chars)
1146 (concat viper-strict-ALPHA-chars addl-chars)) 1228 (concat viper-strict-ALPHA-chars addl-chars))
1147 (t addl-chars)))) 1229 (t addl-chars))))
1148 1230
1149 ;; weird syntax tables may confuse strict-vi style 1231 ;; weird syntax tables may confuse strict-vi style
1150 (defsubst viper-skip-all-separators-forward (&optional within-line) 1232 (defsubst viper-skip-all-separators-forward (&optional within-line)
1151 (viper-skip-syntax 'forward 1233 (if (eq viper-syntax-preference 'strict-vi)
1152 viper-SEP-char-class 1234 (if within-line
1153 (or within-line "\n") 1235 (skip-chars-forward viper-strict-SEP-chars-sans-newline)
1154 (if within-line (viper-line-pos 'end)))) 1236 (skip-chars-forward viper-strict-SEP-chars))
1237 (viper-skip-syntax 'forward
1238 viper-SEP-char-class
1239 (or within-line "\n")
1240 (if within-line (viper-line-pos 'end)))))
1155 (defsubst viper-skip-all-separators-backward (&optional within-line) 1241 (defsubst viper-skip-all-separators-backward (&optional within-line)
1156 (viper-skip-syntax 'backward 1242 (if (eq viper-syntax-preference 'strict-vi)
1157 viper-SEP-char-class 1243 (if within-line
1158 (or within-line "\n") 1244 (skip-chars-backward viper-strict-SEP-chars-sans-newline)
1159 (if within-line (viper-line-pos 'start)))) 1245 (skip-chars-backward viper-strict-SEP-chars))
1246 (viper-skip-syntax 'backward
1247 viper-SEP-char-class
1248 (or within-line "\n")
1249 (if within-line (viper-line-pos 'start)))))
1160 (defun viper-skip-nonseparators (direction) 1250 (defun viper-skip-nonseparators (direction)
1161 (let ((func (intern (format "skip-syntax-%S" direction)))) 1251 (viper-skip-syntax
1162 (funcall func (concat "^" viper-SEP-char-class) 1252 direction
1163 (viper-line-pos (if (eq direction 'forward) 'end 'start))))) 1253 (concat "^" viper-SEP-char-class)
1164 1254 nil
1255 (viper-line-pos (if (eq direction 'forward) 'end 'start))))
1256
1257
1258 ;; skip over non-word constituents and non-separators
1165 (defun viper-skip-nonalphasep-forward () 1259 (defun viper-skip-nonalphasep-forward ()
1166 (if (eq viper-syntax-preference 'strict-vi) 1260 (if (eq viper-syntax-preference 'strict-vi)
1167 (skip-chars-forward 1261 (skip-chars-forward
1168 (concat "^" viper-strict-SEP-chars viper-strict-ALPHA-chars)) 1262 (concat "^" viper-strict-SEP-chars viper-strict-ALPHA-chars))
1169 (skip-syntax-forward 1263 (viper-skip-syntax
1170 (concat 1264 'forward
1171 "^" viper-ALPHA-char-class viper-SEP-char-class) (viper-line-pos 'end)))) 1265 (concat "^" viper-ALPHA-char-class viper-SEP-char-class)
1266 ;; Emacs may consider some of these as words, but we don't want them
1267 viper-non-word-characters
1268 (viper-line-pos 'end))))
1172 (defun viper-skip-nonalphasep-backward () 1269 (defun viper-skip-nonalphasep-backward ()
1173 (if (eq viper-syntax-preference 'strict-vi) 1270 (if (eq viper-syntax-preference 'strict-vi)
1174 (skip-chars-backward 1271 (skip-chars-backward
1175 (concat "^" viper-strict-SEP-chars viper-strict-ALPHA-chars)) 1272 (concat "^" viper-strict-SEP-chars viper-strict-ALPHA-chars))
1176 (skip-syntax-backward 1273 (viper-skip-syntax
1177 (concat 1274 'backward
1178 "^" 1275 (concat "^" viper-ALPHA-char-class viper-SEP-char-class)
1179 viper-ALPHA-char-class viper-SEP-char-class) 1276 ;; Emacs may consider some of these as words, but we don't want them
1277 viper-non-word-characters
1180 (viper-line-pos 'start)))) 1278 (viper-line-pos 'start))))
1181 1279
1182 ;; Skip SYNTAX like skip-syntax-* and ADDL-CHARS like skip-chars-* 1280 ;; Skip SYNTAX like skip-syntax-* and ADDL-CHARS like skip-chars-*
1183 ;; Return the number of chars traveled. 1281 ;; Return the number of chars traveled.
1184 ;; Either SYNTAX or ADDL-CHARS can be nil, in which case they are interpreted 1282 ;; Both SYNTAX or ADDL-CHARS can be strings or lists of characters.
1185 ;; as an empty string. 1283 ;; When SYNTAX is "w", then viper-non-word-characters are not considered to be
1284 ;; words, even if Emacs syntax table says they are.
1186 (defun viper-skip-syntax (direction syntax addl-chars &optional limit) 1285 (defun viper-skip-syntax (direction syntax addl-chars &optional limit)
1187 (let ((total 0) 1286 (let ((total 0)
1188 (local 1) 1287 (local 1)
1189 (skip-chars-func (intern (format "skip-chars-%S" direction))) 1288 (skip-chars-func
1190 (skip-syntax-func (intern (format "skip-syntax-%S" direction)))) 1289 (if (eq direction 'forward)
1191 (or (stringp addl-chars) (setq addl-chars "")) 1290 'skip-chars-forward 'skip-chars-backward))
1192 (or (stringp syntax) (setq syntax "")) 1291 (skip-syntax-func
1292 (if (eq direction 'forward)
1293 'viper-forward-char-carefully 'viper-backward-char-carefully))
1294 char-looked-at syntax-of-char-looked-at negated-syntax)
1295 (setq addl-chars
1296 (cond ((listp addl-chars) (viper-charlist-to-string addl-chars))
1297 ((stringp addl-chars) addl-chars)
1298 (t "")))
1299 (setq syntax
1300 (cond ((listp syntax) syntax)
1301 ((stringp syntax) (viper-string-to-list syntax))
1302 (t nil)))
1303 (if (memq ?^ syntax) (setq negated-syntax t))
1304
1193 (while (and (not (= local 0)) (not (eobp))) 1305 (while (and (not (= local 0)) (not (eobp)))
1306 (setq char-looked-at (viper-char-at-pos direction)
1307 ;; if outside the range, set to nil
1308 syntax-of-char-looked-at (if char-looked-at
1309 (char-syntax char-looked-at)))
1194 (setq local 1310 (setq local
1195 (+ (funcall skip-syntax-func syntax limit) 1311 (+ (if (and
1312 (cond ((and limit (eq direction 'forward))
1313 (< (point) limit))
1314 (limit ; backward & limit
1315 (> (point) limit))
1316 (t t)) ; no limit
1317 ;; char under/before cursor has appropriate syntax
1318 (if negated-syntax
1319 (not (memq syntax-of-char-looked-at syntax))
1320 (memq syntax-of-char-looked-at syntax))
1321 ;; if char-syntax class is "word", make sure it is not one
1322 ;; of the excluded characters
1323 (if (and (eq syntax-of-char-looked-at ?w)
1324 (not negated-syntax))
1325 (not (memq char-looked-at viper-non-word-characters))
1326 t))
1327 (funcall skip-syntax-func 1)
1328 0)
1196 (funcall skip-chars-func addl-chars limit))) 1329 (funcall skip-chars-func addl-chars limit)))
1197 (setq total (+ total local))) 1330 (setq total (+ total local)))
1198 total 1331 total
1199 )) 1332 ))
1200 1333