diff options
| author | Fabián Ezequiel Gallina | 2015-07-06 01:03:46 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2015-07-06 01:04:00 -0300 |
| commit | a5e39bfae8fe8950a01e01b1ae1ad864f5f523b4 (patch) | |
| tree | 7452a926b25a45f793fe5c3a9d6fb4e25bc5ea0a | |
| parent | 342ed936e1957c0af32b96d6dee13fa0c84452c1 (diff) | |
| download | emacs-a5e39bfae8fe8950a01e01b1ae1ad864f5f523b4.tar.gz emacs-a5e39bfae8fe8950a01e01b1ae1ad864f5f523b4.zip | |
python.el: Fix mark-defun behavior (Bug#19665)
* lisp/progmodes/python.el: (python-mark-defun): New function.
* test/automated/python-tests.el (python-mark-defun-1)
(python-mark-defun-2, python-mark-defun-3): New tests.
| -rw-r--r-- | lisp/progmodes/python.el | 16 | ||||
| -rw-r--r-- | test/automated/python-tests.el | 152 |
2 files changed, 168 insertions, 0 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index f641880428c..fbf944f9c68 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -284,6 +284,7 @@ | |||
| 284 | (define-key map [remap backward-sentence] 'python-nav-backward-block) | 284 | (define-key map [remap backward-sentence] 'python-nav-backward-block) |
| 285 | (define-key map [remap forward-sentence] 'python-nav-forward-block) | 285 | (define-key map [remap forward-sentence] 'python-nav-forward-block) |
| 286 | (define-key map [remap backward-up-list] 'python-nav-backward-up-list) | 286 | (define-key map [remap backward-up-list] 'python-nav-backward-up-list) |
| 287 | (define-key map [remap mark-defun] 'python-mark-defun) | ||
| 287 | (define-key map "\C-c\C-j" 'imenu) | 288 | (define-key map "\C-c\C-j" 'imenu) |
| 288 | ;; Indent specific | 289 | ;; Indent specific |
| 289 | (define-key map "\177" 'python-indent-dedent-line-backspace) | 290 | (define-key map "\177" 'python-indent-dedent-line-backspace) |
| @@ -1251,6 +1252,21 @@ the line will be re-indented automatically if needed." | |||
| 1251 | (python-indent-region dedenter-pos current-pos))))))))) | 1252 | (python-indent-region dedenter-pos current-pos))))))))) |
| 1252 | 1253 | ||
| 1253 | 1254 | ||
| 1255 | ;;; Mark | ||
| 1256 | |||
| 1257 | (defun python-mark-defun (&optional allow-extend) | ||
| 1258 | "Put mark at end of this defun, point at beginning. | ||
| 1259 | The defun marked is the one that contains point or follows point. | ||
| 1260 | |||
| 1261 | Interactively (or with ALLOW-EXTEND non-nil), if this command is | ||
| 1262 | repeated or (in Transient Mark mode) if the mark is active, it | ||
| 1263 | marks the next defun after the ones already marked." | ||
| 1264 | (interactive "p") | ||
| 1265 | (when (python-info-looking-at-beginning-of-defun) | ||
| 1266 | (end-of-line 1)) | ||
| 1267 | (mark-defun allow-extend)) | ||
| 1268 | |||
| 1269 | |||
| 1254 | ;;; Navigation | 1270 | ;;; Navigation |
| 1255 | 1271 | ||
| 1256 | (defvar python-nav-beginning-of-defun-regexp | 1272 | (defvar python-nav-beginning-of-defun-regexp |
diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el index 4585e7f9614..2ed07464df6 100644 --- a/test/automated/python-tests.el +++ b/test/automated/python-tests.el | |||
| @@ -1226,6 +1226,158 @@ this is an arbitrarily | |||
| 1226 | expected))))) | 1226 | expected))))) |
| 1227 | 1227 | ||
| 1228 | 1228 | ||
| 1229 | ;;; Mark | ||
| 1230 | |||
| 1231 | (ert-deftest python-mark-defun-1 () | ||
| 1232 | """Test `python-mark-defun' with point at defun symbol start.""" | ||
| 1233 | (python-tests-with-temp-buffer | ||
| 1234 | " | ||
| 1235 | def foo(x): | ||
| 1236 | return x | ||
| 1237 | |||
| 1238 | class A: | ||
| 1239 | pass | ||
| 1240 | |||
| 1241 | class B: | ||
| 1242 | |||
| 1243 | def __init__(self): | ||
| 1244 | self.b = 'b' | ||
| 1245 | |||
| 1246 | def fun(self): | ||
| 1247 | return self.b | ||
| 1248 | |||
| 1249 | class C: | ||
| 1250 | '''docstring''' | ||
| 1251 | " | ||
| 1252 | (let ((expected-mark-beginning-position | ||
| 1253 | (progn | ||
| 1254 | (python-tests-look-at "class A:") | ||
| 1255 | (1- (point)))) | ||
| 1256 | (expected-mark-end-position-1 | ||
| 1257 | (save-excursion | ||
| 1258 | (python-tests-look-at "pass") | ||
| 1259 | (forward-line) | ||
| 1260 | (point))) | ||
| 1261 | (expected-mark-end-position-2 | ||
| 1262 | (save-excursion | ||
| 1263 | (python-tests-look-at "return self.b") | ||
| 1264 | (forward-line) | ||
| 1265 | (point))) | ||
| 1266 | (expected-mark-end-position-3 | ||
| 1267 | (save-excursion | ||
| 1268 | (python-tests-look-at "'''docstring'''") | ||
| 1269 | (forward-line) | ||
| 1270 | (point)))) | ||
| 1271 | ;; Select class A only, with point at bol. | ||
| 1272 | (python-mark-defun 1) | ||
| 1273 | (should (= (point) expected-mark-beginning-position)) | ||
| 1274 | (should (= (marker-position (mark-marker)) | ||
| 1275 | expected-mark-end-position-1)) | ||
| 1276 | ;; expand to class B, start position should remain the same. | ||
| 1277 | (python-mark-defun 1) | ||
| 1278 | (should (= (point) expected-mark-beginning-position)) | ||
| 1279 | (should (= (marker-position (mark-marker)) | ||
| 1280 | expected-mark-end-position-2)) | ||
| 1281 | ;; expand to class C, start position should remain the same. | ||
| 1282 | (python-mark-defun 1) | ||
| 1283 | (should (= (point) expected-mark-beginning-position)) | ||
| 1284 | (should (= (marker-position (mark-marker)) | ||
| 1285 | expected-mark-end-position-3))))) | ||
| 1286 | |||
| 1287 | (ert-deftest python-mark-defun-2 () | ||
| 1288 | """Test `python-mark-defun' with point at nested defun symbol start.""" | ||
| 1289 | (python-tests-with-temp-buffer | ||
| 1290 | " | ||
| 1291 | def foo(x): | ||
| 1292 | return x | ||
| 1293 | |||
| 1294 | class A: | ||
| 1295 | pass | ||
| 1296 | |||
| 1297 | class B: | ||
| 1298 | |||
| 1299 | def __init__(self): | ||
| 1300 | self.b = 'b' | ||
| 1301 | |||
| 1302 | def fun(self): | ||
| 1303 | return self.b | ||
| 1304 | |||
| 1305 | class C: | ||
| 1306 | '''docstring''' | ||
| 1307 | " | ||
| 1308 | (let ((expected-mark-beginning-position | ||
| 1309 | (progn | ||
| 1310 | (python-tests-look-at "def __init__(self):") | ||
| 1311 | (1- (line-beginning-position)))) | ||
| 1312 | (expected-mark-end-position-1 | ||
| 1313 | (save-excursion | ||
| 1314 | (python-tests-look-at "self.b = 'b'") | ||
| 1315 | (forward-line) | ||
| 1316 | (point))) | ||
| 1317 | (expected-mark-end-position-2 | ||
| 1318 | (save-excursion | ||
| 1319 | (python-tests-look-at "return self.b") | ||
| 1320 | (forward-line) | ||
| 1321 | (point))) | ||
| 1322 | (expected-mark-end-position-3 | ||
| 1323 | (save-excursion | ||
| 1324 | (python-tests-look-at "'''docstring'''") | ||
| 1325 | (forward-line) | ||
| 1326 | (point)))) | ||
| 1327 | ;; Select B.__init only, with point at its start. | ||
| 1328 | (python-mark-defun 1) | ||
| 1329 | (should (= (point) expected-mark-beginning-position)) | ||
| 1330 | (should (= (marker-position (mark-marker)) | ||
| 1331 | expected-mark-end-position-1)) | ||
| 1332 | ;; expand to B.fun, start position should remain the same. | ||
| 1333 | (python-mark-defun 1) | ||
| 1334 | (should (= (point) expected-mark-beginning-position)) | ||
| 1335 | (should (= (marker-position (mark-marker)) | ||
| 1336 | expected-mark-end-position-2)) | ||
| 1337 | ;; expand to class C, start position should remain the same. | ||
| 1338 | (python-mark-defun 1) | ||
| 1339 | (should (= (point) expected-mark-beginning-position)) | ||
| 1340 | (should (= (marker-position (mark-marker)) | ||
| 1341 | expected-mark-end-position-3))))) | ||
| 1342 | |||
| 1343 | (ert-deftest python-mark-defun-3 () | ||
| 1344 | """Test `python-mark-defun' with point inside defun symbol.""" | ||
| 1345 | (python-tests-with-temp-buffer | ||
| 1346 | " | ||
| 1347 | def foo(x): | ||
| 1348 | return x | ||
| 1349 | |||
| 1350 | class A: | ||
| 1351 | pass | ||
| 1352 | |||
| 1353 | class B: | ||
| 1354 | |||
| 1355 | def __init__(self): | ||
| 1356 | self.b = 'b' | ||
| 1357 | |||
| 1358 | def fun(self): | ||
| 1359 | return self.b | ||
| 1360 | |||
| 1361 | class C: | ||
| 1362 | '''docstring''' | ||
| 1363 | " | ||
| 1364 | (let ((expected-mark-beginning-position | ||
| 1365 | (progn | ||
| 1366 | (python-tests-look-at "def fun(self):") | ||
| 1367 | (python-tests-look-at "(self):") | ||
| 1368 | (1- (line-beginning-position)))) | ||
| 1369 | (expected-mark-end-position | ||
| 1370 | (save-excursion | ||
| 1371 | (python-tests-look-at "return self.b") | ||
| 1372 | (forward-line) | ||
| 1373 | (point)))) | ||
| 1374 | ;; Should select B.fun, despite point is inside the defun symbol. | ||
| 1375 | (python-mark-defun 1) | ||
| 1376 | (should (= (point) expected-mark-beginning-position)) | ||
| 1377 | (should (= (marker-position (mark-marker)) | ||
| 1378 | expected-mark-end-position))))) | ||
| 1379 | |||
| 1380 | |||
| 1229 | ;;; Navigation | 1381 | ;;; Navigation |
| 1230 | 1382 | ||
| 1231 | (ert-deftest python-nav-beginning-of-defun-1 () | 1383 | (ert-deftest python-nav-beginning-of-defun-1 () |