aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabián Ezequiel Gallina2015-07-06 01:03:46 -0300
committerFabián Ezequiel Gallina2015-07-06 01:04:00 -0300
commita5e39bfae8fe8950a01e01b1ae1ad864f5f523b4 (patch)
tree7452a926b25a45f793fe5c3a9d6fb4e25bc5ea0a
parent342ed936e1957c0af32b96d6dee13fa0c84452c1 (diff)
downloademacs-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.el16
-rw-r--r--test/automated/python-tests.el152
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.
1259The defun marked is the one that contains point or follows point.
1260
1261Interactively (or with ALLOW-EXTEND non-nil), if this command is
1262repeated or (in Transient Mark mode) if the mark is active, it
1263marks 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 "
1235def foo(x):
1236 return x
1237
1238class A:
1239 pass
1240
1241class B:
1242
1243 def __init__(self):
1244 self.b = 'b'
1245
1246 def fun(self):
1247 return self.b
1248
1249class 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 "
1291def foo(x):
1292 return x
1293
1294class A:
1295 pass
1296
1297class B:
1298
1299 def __init__(self):
1300 self.b = 'b'
1301
1302 def fun(self):
1303 return self.b
1304
1305class 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 "
1347def foo(x):
1348 return x
1349
1350class A:
1351 pass
1352
1353class B:
1354
1355 def __init__(self):
1356 self.b = 'b'
1357
1358 def fun(self):
1359 return self.b
1360
1361class 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 ()