Mercurial > emacs
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 |