diff options
| author | Fabián Ezequiel Gallina | 2012-07-16 10:13:01 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2012-07-16 10:13:01 -0300 |
| commit | 032d23ab664d571be03f5661034d1962baa4f5ae (patch) | |
| tree | adfd6edbaab5c3edac9297aa30e2d7ce35b804e8 /lisp/progmodes/python.el | |
| parent | 9328d9aabae2f45f82b59aad5214a3f13ee1b2a1 (diff) | |
| download | emacs-032d23ab664d571be03f5661034d1962baa4f5ae.tar.gz emacs-032d23ab664d571be03f5661034d1962baa4f5ae.zip | |
* progmodes/python.el: Enhancements to navigation commands.
(python-nav-backward-sentence)
(python-nav-forward-sentence): Remove.
(python-nav-backward-statement, python-nav-forward-statement)
(python-nav-statement-start, python-nav-statement-end)
(python-nav-backward-block, python-nav-forward-block)
(python-nav-block-start, python-nav-block-end)
(python-nav-forward-sexp-function)
(python-info-current-line-comment-p)
(python-info-current-line-empty-p): New functions.
(python-indent-context): Use `python-nav-statement-start'.
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 226 |
1 files changed, 201 insertions, 25 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index ddedbdb7ddc..fe9faf54046 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -46,11 +46,13 @@ | |||
| 46 | 46 | ||
| 47 | ;; Movement: `beginning-of-defun' and `end-of-defun' functions are | 47 | ;; Movement: `beginning-of-defun' and `end-of-defun' functions are |
| 48 | ;; properly implemented. There are also specialized | 48 | ;; properly implemented. There are also specialized |
| 49 | ;; `forward-sentence' and `backward-sentence' replacements | 49 | ;; `forward-sentence' and `backward-sentence' replacements called |
| 50 | ;; (`python-nav-forward-sentence', `python-nav-backward-sentence' | 50 | ;; `python-nav-forward-block', `python-nav-backward-block' |
| 51 | ;; respectively). Extra functions `python-nav-sentence-start' and | 51 | ;; respectively which navigate between beginning of blocks of code. |
| 52 | ;; `python-nav-sentence-end' are included to move to the beginning and | 52 | ;; Extra functions `python-nav-forward-statement', |
| 53 | ;; to the end of a sentence while taking care of multiline definitions. | 53 | ;; `python-nav-backward-statement', `python-nav-statement-start', |
| 54 | ;; `python-nav-statement-end', `python-nav-block-start' and | ||
| 55 | ;; `python-nav-block-end' are included but no bound to any key. | ||
| 54 | ;; `python-nav-jump-to-defun' is provided and allows jumping to a | 56 | ;; `python-nav-jump-to-defun' is provided and allows jumping to a |
| 55 | ;; function or class definition quickly in the current buffer. | 57 | ;; function or class definition quickly in the current buffer. |
| 56 | 58 | ||
| @@ -227,10 +229,10 @@ | |||
| 227 | (let ((map (make-sparse-keymap))) | 229 | (let ((map (make-sparse-keymap))) |
| 228 | ;; Movement | 230 | ;; Movement |
| 229 | (substitute-key-definition 'backward-sentence | 231 | (substitute-key-definition 'backward-sentence |
| 230 | 'python-nav-backward-sentence | 232 | 'python-nav-backward-block |
| 231 | map global-map) | 233 | map global-map) |
| 232 | (substitute-key-definition 'forward-sentence | 234 | (substitute-key-definition 'forward-sentence |
| 233 | 'python-nav-forward-sentence | 235 | 'python-nav-forward-block |
| 234 | map global-map) | 236 | map global-map) |
| 235 | (define-key map "\C-c\C-j" 'python-nav-jump-to-defun) | 237 | (define-key map "\C-c\C-j" 'python-nav-jump-to-defun) |
| 236 | ;; Indent specific | 238 | ;; Indent specific |
| @@ -664,7 +666,7 @@ START is the buffer position where the sexp starts." | |||
| 664 | ((setq start (save-excursion | 666 | ((setq start (save-excursion |
| 665 | (back-to-indentation) | 667 | (back-to-indentation) |
| 666 | (python-util-forward-comment -1) | 668 | (python-util-forward-comment -1) |
| 667 | (python-nav-sentence-start) | 669 | (python-nav-statement-start) |
| 668 | (point-marker))) | 670 | (point-marker))) |
| 669 | 'after-line) | 671 | 'after-line) |
| 670 | ;; Do not indent | 672 | ;; Do not indent |
| @@ -1097,10 +1099,10 @@ Returns nil if point is not in a def or class." | |||
| 1097 | (python-info-ppss-context-type)) | 1099 | (python-info-ppss-context-type)) |
| 1098 | (forward-line 1))))))) | 1100 | (forward-line 1))))))) |
| 1099 | 1101 | ||
| 1100 | (defun python-nav-sentence-start () | 1102 | (defun python-nav-statement-start () |
| 1101 | "Move to start of current sentence." | 1103 | "Move to start of current statement." |
| 1102 | (interactive "^") | 1104 | (interactive "^") |
| 1103 | (while (and (not (back-to-indentation)) | 1105 | (while (and (or (back-to-indentation) t) |
| 1104 | (not (bobp)) | 1106 | (not (bobp)) |
| 1105 | (when (or | 1107 | (when (or |
| 1106 | (save-excursion | 1108 | (save-excursion |
| @@ -1110,8 +1112,8 @@ Returns nil if point is not in a def or class." | |||
| 1110 | (python-info-ppss-context 'paren)) | 1112 | (python-info-ppss-context 'paren)) |
| 1111 | (forward-line -1))))) | 1113 | (forward-line -1))))) |
| 1112 | 1114 | ||
| 1113 | (defun python-nav-sentence-end () | 1115 | (defun python-nav-statement-end () |
| 1114 | "Move to end of current sentence." | 1116 | "Move to end of current statement." |
| 1115 | (interactive "^") | 1117 | (interactive "^") |
| 1116 | (while (and (goto-char (line-end-position)) | 1118 | (while (and (goto-char (line-end-position)) |
| 1117 | (not (eobp)) | 1119 | (not (eobp)) |
| @@ -1121,28 +1123,185 @@ Returns nil if point is not in a def or class." | |||
| 1121 | (python-info-ppss-context 'paren)) | 1123 | (python-info-ppss-context 'paren)) |
| 1122 | (forward-line 1))))) | 1124 | (forward-line 1))))) |
| 1123 | 1125 | ||
| 1124 | (defun python-nav-backward-sentence (&optional arg) | 1126 | (defun python-nav-backward-statement (&optional arg) |
| 1125 | "Move backward to start of sentence. With ARG, do it arg times. | 1127 | "Move backward to previous statement. |
| 1126 | See `python-nav-forward-sentence' for more information." | 1128 | With ARG, repeat. See `python-nav-forward-statement'." |
| 1127 | (interactive "^p") | 1129 | (interactive "^p") |
| 1128 | (or arg (setq arg 1)) | 1130 | (or arg (setq arg 1)) |
| 1129 | (python-nav-forward-sentence (- arg))) | 1131 | (python-nav-forward-statement (- arg))) |
| 1130 | 1132 | ||
| 1131 | (defun python-nav-forward-sentence (&optional arg) | 1133 | (defun python-nav-forward-statement (&optional arg) |
| 1132 | "Move forward to next end of sentence. With ARG, repeat. | 1134 | "Move forward to next statement. |
| 1133 | With negative argument, move backward repeatedly to start of sentence." | 1135 | With ARG, repeat. With negative argument, move ARG times |
| 1136 | backward to previous statement." | ||
| 1134 | (interactive "^p") | 1137 | (interactive "^p") |
| 1135 | (or arg (setq arg 1)) | 1138 | (or arg (setq arg 1)) |
| 1136 | (while (> arg 0) | 1139 | (while (> arg 0) |
| 1140 | (python-nav-statement-end) | ||
| 1137 | (python-util-forward-comment) | 1141 | (python-util-forward-comment) |
| 1138 | (python-nav-sentence-end) | 1142 | (python-nav-statement-start) |
| 1139 | (forward-line 1) | ||
| 1140 | (setq arg (1- arg))) | 1143 | (setq arg (1- arg))) |
| 1141 | (while (< arg 0) | 1144 | (while (< arg 0) |
| 1142 | (python-nav-sentence-end) | 1145 | (python-nav-statement-start) |
| 1143 | (python-util-forward-comment -1) | 1146 | (python-util-forward-comment -1) |
| 1144 | (python-nav-sentence-start) | 1147 | (python-nav-statement-start) |
| 1145 | (forward-line -1) | 1148 | (setq arg (1+ arg)))) |
| 1149 | |||
| 1150 | (defun python-nav-block-start () | ||
| 1151 | "Move to start of current block." | ||
| 1152 | (interactive "^") | ||
| 1153 | (let ((starting-pos (point)) | ||
| 1154 | (block-regexp (python-rx | ||
| 1155 | line-start (* whitespace) block-start))) | ||
| 1156 | (if (progn | ||
| 1157 | (python-nav-statement-start) | ||
| 1158 | (looking-at (python-rx block-start))) | ||
| 1159 | (point-marker) | ||
| 1160 | ;; Go to first line beginning a statement | ||
| 1161 | (while (and (not (bobp)) | ||
| 1162 | (or (and (python-nav-statement-start) nil) | ||
| 1163 | (python-info-current-line-comment-p) | ||
| 1164 | (python-info-current-line-empty-p))) | ||
| 1165 | (forward-line -1)) | ||
| 1166 | (let ((block-matching-indent | ||
| 1167 | (- (current-indentation) python-indent-offset))) | ||
| 1168 | (while | ||
| 1169 | (and (python-nav-backward-block) | ||
| 1170 | (> (current-indentation) block-matching-indent))) | ||
| 1171 | (if (and (looking-at (python-rx block-start)) | ||
| 1172 | (= (current-indentation) block-matching-indent)) | ||
| 1173 | (point-marker) | ||
| 1174 | (and (goto-char starting-pos) nil)))))) | ||
| 1175 | |||
| 1176 | (defun python-nav-block-end () | ||
| 1177 | "Move to end of current block." | ||
| 1178 | (interactive "^") | ||
| 1179 | (when (python-nav-block-start) | ||
| 1180 | (let ((block-indentation (current-indentation))) | ||
| 1181 | (python-nav-statement-end) | ||
| 1182 | (while (and (forward-line 1) | ||
| 1183 | (not (eobp)) | ||
| 1184 | (or (and (> (current-indentation) block-indentation) | ||
| 1185 | (or (python-nav-statement-end) t)) | ||
| 1186 | (python-info-current-line-comment-p) | ||
| 1187 | (python-info-current-line-empty-p)))) | ||
| 1188 | (python-util-forward-comment -1) | ||
| 1189 | (point-marker)))) | ||
| 1190 | |||
| 1191 | (defun python-nav-backward-block (&optional arg) | ||
| 1192 | "Move backward to previous block of code. | ||
| 1193 | With ARG, repeat. See `python-nav-forward-block'." | ||
| 1194 | (interactive "^p") | ||
| 1195 | (or arg (setq arg 1)) | ||
| 1196 | (python-nav-forward-block (- arg))) | ||
| 1197 | |||
| 1198 | (defun python-nav-forward-block (&optional arg) | ||
| 1199 | "Move forward to next block of code. | ||
| 1200 | With ARG, repeat. With negative argument, move ARG times | ||
| 1201 | backward to previous block." | ||
| 1202 | (interactive "^p") | ||
| 1203 | (or arg (setq arg 1)) | ||
| 1204 | (let ((block-start-regexp | ||
| 1205 | (python-rx line-start (* whitespace) block-start)) | ||
| 1206 | (starting-pos (point))) | ||
| 1207 | (while (> arg 0) | ||
| 1208 | (python-nav-statement-end) | ||
| 1209 | (while (and | ||
| 1210 | (re-search-forward block-start-regexp nil t) | ||
| 1211 | (or (python-info-ppss-context 'string) | ||
| 1212 | (python-info-ppss-context 'comment) | ||
| 1213 | (python-info-ppss-context 'paren)))) | ||
| 1214 | (setq arg (1- arg))) | ||
| 1215 | (while (< arg 0) | ||
| 1216 | (python-nav-statement-start) | ||
| 1217 | (while (and | ||
| 1218 | (re-search-backward block-start-regexp nil t) | ||
| 1219 | (or (python-info-ppss-context 'string) | ||
| 1220 | (python-info-ppss-context 'comment) | ||
| 1221 | (python-info-ppss-context 'paren)))) | ||
| 1222 | (setq arg (1+ arg))) | ||
| 1223 | (python-nav-statement-start) | ||
| 1224 | (if (not (looking-at (python-rx block-start))) | ||
| 1225 | (and (goto-char starting-pos) nil) | ||
| 1226 | (and (not (= (point) starting-pos)) (point-marker))))) | ||
| 1227 | |||
| 1228 | (defun python-nav-forward-sexp-function (&optional arg) | ||
| 1229 | "Move forward across one block of code. | ||
| 1230 | With ARG, do it that many times. Negative arg -N means | ||
| 1231 | move backward N times." | ||
| 1232 | (interactive "^p") | ||
| 1233 | (or arg (setq arg 1)) | ||
| 1234 | (while (> arg 0) | ||
| 1235 | (let ((block-starting-pos | ||
| 1236 | (save-excursion (python-nav-block-start))) | ||
| 1237 | (block-ending-pos | ||
| 1238 | (save-excursion (python-nav-block-end))) | ||
| 1239 | (next-block-starting-pos | ||
| 1240 | (save-excursion (python-nav-forward-block)))) | ||
| 1241 | (cond ((not block-starting-pos) | ||
| 1242 | (python-nav-forward-block)) | ||
| 1243 | ((= (point) block-starting-pos) | ||
| 1244 | (if (or (not next-block-starting-pos) | ||
| 1245 | (< block-ending-pos next-block-starting-pos)) | ||
| 1246 | (python-nav-block-end) | ||
| 1247 | (python-nav-forward-block))) | ||
| 1248 | ((= block-ending-pos (point)) | ||
| 1249 | (let ((parent-block-end-pos | ||
| 1250 | (save-excursion | ||
| 1251 | (python-util-forward-comment) | ||
| 1252 | (python-nav-block-start) | ||
| 1253 | (python-nav-block-end)))) | ||
| 1254 | (if (and parent-block-end-pos | ||
| 1255 | (or (not next-block-starting-pos) | ||
| 1256 | (> next-block-starting-pos parent-block-end-pos))) | ||
| 1257 | (goto-char parent-block-end-pos) | ||
| 1258 | (python-nav-forward-block)))) | ||
| 1259 | (t (python-nav-block-end)))) | ||
| 1260 | (setq arg (1- arg))) | ||
| 1261 | (while (< arg 0) | ||
| 1262 | (let* ((block-starting-pos | ||
| 1263 | (save-excursion (python-nav-block-start))) | ||
| 1264 | (block-ending-pos | ||
| 1265 | (save-excursion (python-nav-block-end))) | ||
| 1266 | (prev-block-ending-pos | ||
| 1267 | (save-excursion (when (python-nav-backward-block) | ||
| 1268 | (python-nav-block-end)))) | ||
| 1269 | (prev-block-parent-ending-pos | ||
| 1270 | (save-excursion | ||
| 1271 | (when prev-block-ending-pos | ||
| 1272 | (goto-char prev-block-ending-pos) | ||
| 1273 | (python-util-forward-comment) | ||
| 1274 | (python-nav-block-start) | ||
| 1275 | (python-nav-block-end))))) | ||
| 1276 | (cond ((not block-ending-pos) | ||
| 1277 | (and (python-nav-backward-block) | ||
| 1278 | (python-nav-block-end))) | ||
| 1279 | ((= (point) block-ending-pos) | ||
| 1280 | (let ((candidates)) | ||
| 1281 | (dolist (name | ||
| 1282 | '(prev-block-parent-ending-pos | ||
| 1283 | prev-block-ending-pos | ||
| 1284 | block-ending-pos | ||
| 1285 | block-starting-pos)) | ||
| 1286 | (when (and (symbol-value name) | ||
| 1287 | (< (symbol-value name) (point))) | ||
| 1288 | (add-to-list 'candidates (symbol-value name)))) | ||
| 1289 | (goto-char (apply 'max candidates)))) | ||
| 1290 | ((> (point) block-ending-pos) | ||
| 1291 | (python-nav-block-end)) | ||
| 1292 | ((= (point) block-starting-pos) | ||
| 1293 | (if (not (> (point) (or prev-block-ending-pos (point)))) | ||
| 1294 | (python-nav-backward-block) | ||
| 1295 | (goto-char prev-block-ending-pos) | ||
| 1296 | (let ((parent-block-ending-pos | ||
| 1297 | (save-excursion | ||
| 1298 | (python-nav-forward-sexp-function) | ||
| 1299 | (and (not (looking-at (python-rx block-start))) | ||
| 1300 | (point))))) | ||
| 1301 | (when (and parent-block-ending-pos | ||
| 1302 | (> parent-block-ending-pos prev-block-ending-pos)) | ||
| 1303 | (goto-char parent-block-ending-pos))))) | ||
| 1304 | (t (python-nav-block-start)))) | ||
| 1146 | (setq arg (1+ arg)))) | 1305 | (setq arg (1+ arg)))) |
| 1147 | 1306 | ||
| 1148 | (defvar python-nav-list-defun-positions-cache nil) | 1307 | (defvar python-nav-list-defun-positions-cache nil) |
| @@ -2766,6 +2925,20 @@ The type returned can be 'comment, 'string or 'paren." | |||
| 2766 | (beginning-of-line 1) | 2925 | (beginning-of-line 1) |
| 2767 | (looking-at python-nav-beginning-of-defun-regexp)))) | 2926 | (looking-at python-nav-beginning-of-defun-regexp)))) |
| 2768 | 2927 | ||
| 2928 | (defun python-info-current-line-comment-p () | ||
| 2929 | "Check if current line is a comment line." | ||
| 2930 | (char-equal (or (char-after (+ (point) (current-indentation))) ?_) ?#)) | ||
| 2931 | |||
| 2932 | (defun python-info-current-line-empty-p () | ||
| 2933 | "Check if current line is empty, ignoring whitespace." | ||
| 2934 | (save-excursion | ||
| 2935 | (beginning-of-line 1) | ||
| 2936 | (looking-at | ||
| 2937 | (python-rx line-start (* whitespace) | ||
| 2938 | (group (* not-newline)) | ||
| 2939 | (* whitespace) line-end)) | ||
| 2940 | (string-equal "" (match-string-no-properties 1)))) | ||
| 2941 | |||
| 2769 | 2942 | ||
| 2770 | ;;; Utility functions | 2943 | ;;; Utility functions |
| 2771 | 2944 | ||
| @@ -2818,6 +2991,9 @@ if that value is non-nil." | |||
| 2818 | (set (make-local-variable 'parse-sexp-lookup-properties) t) | 2991 | (set (make-local-variable 'parse-sexp-lookup-properties) t) |
| 2819 | (set (make-local-variable 'parse-sexp-ignore-comments) t) | 2992 | (set (make-local-variable 'parse-sexp-ignore-comments) t) |
| 2820 | 2993 | ||
| 2994 | (set (make-local-variable 'forward-sexp-function) | ||
| 2995 | 'python-nav-forward-sexp-function) | ||
| 2996 | |||
| 2821 | (set (make-local-variable 'font-lock-defaults) | 2997 | (set (make-local-variable 'font-lock-defaults) |
| 2822 | '(python-font-lock-keywords nil nil nil nil)) | 2998 | '(python-font-lock-keywords nil nil nil nil)) |
| 2823 | 2999 | ||