summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2013-04-19 11:39:24 +0300
committerEli Zaretskii <eliz@gnu.org>2013-04-19 11:39:24 +0300
commit4cf86a2fa737296d26e8a02338e2bf6f26e1133a (patch)
tree094502cb2926db798570e62d32c680b2ce72b6c2 /lisp
parentf60f289656d815827a492150f2e564dd081967f8 (diff)
parent7d6883367a54b4eee342aa861ef73e4191151ef0 (diff)
downloademacs-4cf86a2fa737296d26e8a02338e2bf6f26e1133a.tar.gz
emacs-4cf86a2fa737296d26e8a02338e2bf6f26e1133a.tar.bz2
emacs-4cf86a2fa737296d26e8a02338e2bf6f26e1133a.zip
Merge from trunk.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog27
-rw-r--r--lisp/bookmark.el27
-rw-r--r--lisp/progmodes/python.el234
-rw-r--r--lisp/vc/vc-dispatcher.el4
4 files changed, 254 insertions, 38 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 98ba110ab33..a09d37352f7 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,30 @@
+2013-04-19 Thierry Volpiatto <thierry.volpiatto@gmail.com>
+
+ * bookmark.el (bookmark-completing-read): Improve handling of empty
+ string (bug#14176).
+
+2013-04-19 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * vc/vc-dispatcher.el (vc-do-command): Get rid of default sentinel msg.
+
+2013-04-19 Fabián Ezequiel Gallina <fgallina@gnu.org>
+
+ New faster Imenu implementation (bug#14058).
+ * progmodes/python.el:
+ (python-imenu-prev-index-position):
+ (python-imenu-format-item-label-function)
+ (python-imenu-format-parent-item-label-function)
+ (python-imenu-format-parent-item-jump-label-function):
+ New vars.
+ (python-imenu-format-item-label)
+ (python-imenu-format-parent-item-label)
+ (python-imenu-format-parent-item-jump-label)
+ (python-imenu--put-parent, python-imenu--build-tree)
+ (python-imenu-create-index, python-imenu-create-flat-index)
+ (python-util-popn): New functions.
+ (python-mode): Set imenu-create-index-function to
+ python-imenu-create-index.
+
2013-04-18 Stefan Monnier <monnier@iro.umontreal.ca>
* winner.el (winner-active-region): Use region-active-p, activate-mark
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index c1d8a4a0a5e..482cdf92752 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -427,8 +427,8 @@ just return it."
"Prompting with PROMPT, read a bookmark name in completion.
PROMPT will get a \": \" stuck on the end no matter what, so you
probably don't want to include one yourself.
-Optional second arg DEFAULT is a string to return if the user enters
-the empty string."
+Optional arg DEFAULT is a string to return if the user input is empty.
+If DEFAULT is nil then return empty string for empty input."
(bookmark-maybe-load-default-file) ; paranoia
(if (listp last-nonmenu-event)
(bookmark-menu-popup-paned-menu t prompt
@@ -437,22 +437,17 @@ the empty string."
'string-lessp)
(bookmark-all-names)))
(let* ((completion-ignore-case bookmark-completion-ignore-case)
- (default default)
+ (default (unless (equal "" default) default))
(prompt (concat prompt (if default
(format " (%s): " default)
- ": ")))
- (str
- (completing-read prompt
- (lambda (string pred action)
- (if (eq action 'metadata)
- '(metadata (category . bookmark))
- (complete-with-action
- action bookmark-alist string pred)))
- nil
- 0
- nil
- 'bookmark-history)))
- (if (string-equal "" str) default str))))
+ ": "))))
+ (completing-read prompt
+ (lambda (string pred action)
+ (if (eq action 'metadata)
+ '(metadata (category . bookmark))
+ (complete-with-action
+ action bookmark-alist string pred)))
+ nil 0 nil 'bookmark-history default))))
(defmacro bookmark-maybe-historicize-string (string)
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 53aff94ae0e..06d07d6ee3c 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -177,12 +177,14 @@
;; might guessed you should run `python-shell-send-buffer' from time
;; to time to get better results too.
-;; Imenu: This mode supports Imenu in its most basic form, letting it
-;; build the necessary alist via `imenu-default-create-index-function'
-;; by having set `imenu-extract-index-name-function' to
-;; `python-info-current-defun' and
-;; `imenu-prev-index-position-function' to
-;; `python-imenu-prev-index-position'.
+;; Imenu: There are two index building functions to be used as
+;; `imenu-create-index-function': `python-imenu-create-index' (the
+;; default one, builds the alist in form of a tree) and
+;; `python-imenu-create-flat-index'. See also
+;; `python-imenu-format-item-label-function',
+;; `python-imenu-format-parent-item-label-function',
+;; `python-imenu-format-parent-item-jump-label-function' variables for
+;; changing the way labels are formatted in the tree version.
;; If you used python-mode.el you probably will miss auto-indentation
;; when inserting newlines. To achieve the same behavior you have
@@ -1194,7 +1196,7 @@ Returns nil if point is not in a def or class."
(defun python-nav--syntactically (fn poscompfn &optional contextfn)
"Move point using FN avoiding places with specific context.
-FN must take no arguments. POSCOMPFN is a two arguments function
+FN must take no arguments. POSCOMPFN is a two arguments function
used to compare current and previous point after it is moved
using FN, this is normally a less-than or greater-than
comparison. Optional argument CONTEXTFN defaults to
@@ -3008,15 +3010,192 @@ Interactively, prompt for symbol."
;;; Imenu
-(defun python-imenu-prev-index-position ()
- "Python mode's `imenu-prev-index-position-function'."
- (let ((found))
- (while (and (setq found
- (re-search-backward python-nav-beginning-of-defun-regexp nil t))
- (not (python-info-looking-at-beginning-of-defun))))
- (and found
- (python-info-looking-at-beginning-of-defun)
- (python-info-current-defun))))
+(defvar python-imenu-format-item-label-function
+ 'python-imenu-format-item-label
+ "Imenu function used to format an item label.
+It must be a function with two arguments: TYPE and NAME.")
+
+(defvar python-imenu-format-parent-item-label-function
+ 'python-imenu-format-parent-item-label
+ "Imenu function used to format a parent item label.
+It must be a function with two arguments: TYPE and NAME.")
+
+(defvar python-imenu-format-parent-item-jump-label-function
+ 'python-imenu-format-parent-item-jump-label
+ "Imenu function used to format a parent jump item label.
+It must be a function with two arguments: TYPE and NAME.")
+
+(defun python-imenu-format-item-label (type name)
+ "Return imenu label for single node using TYPE and NAME."
+ (format "%s (%s)" name type))
+
+(defun python-imenu-format-parent-item-label (type name)
+ "Return imenu label for parent node using TYPE and NAME."
+ (format "%s..." (python-imenu-format-item-label type name)))
+
+(defun python-imenu-format-parent-item-jump-label (type name)
+ "Return imenu label for parent node jump using TYPE and NAME."
+ (if (string= type "class")
+ "*class definition*"
+ "*function definition*"))
+
+(defun python-imenu--put-parent (type name pos num-children tree &optional root)
+ "Add the parent with TYPE, NAME, POS and NUM-CHILDREN to TREE.
+Optional Argument ROOT must be non-nil when the node being
+processed is the root of the TREE."
+ (let ((label
+ (funcall python-imenu-format-item-label-function type name))
+ (jump-label
+ (funcall python-imenu-format-parent-item-jump-label-function type name)))
+ (if root
+ ;; This is the root, everything is a children.
+ (cons label (cons (cons jump-label pos) tree))
+ ;; This is node a which may contain some children.
+ (cons
+ (cons label (cons (cons jump-label pos)
+ ;; Append all the children
+ (python-util-popn tree num-children)))
+ ;; All previous non-children nodes.
+ (nthcdr num-children tree)))))
+
+(defun python-imenu--build-tree (&optional min-indent prev-indent num-children tree)
+ "Recursively build the tree of nested definitions of a node.
+Arguments MIN-INDENT PREV-INDENT NUM-CHILDREN and TREE are
+internal and should not be passed explicitly unless you know what
+you are doing."
+ (setq num-children (or num-children 0)
+ min-indent (or min-indent 0))
+ (let* ((pos (python-nav-backward-defun))
+ (type)
+ (name (when (and pos (looking-at python-nav-beginning-of-defun-regexp))
+ (let ((split (split-string (match-string-no-properties 0))))
+ (setq type (car split))
+ (cadr split))))
+ (label (when name
+ (funcall python-imenu-format-item-label-function type name)))
+ (indent (current-indentation)))
+ (cond ((not pos)
+ ;; No defun found, nothing to add.
+ tree)
+ ((equal indent 0)
+ (if (> num-children 0)
+ ;; Append it as the parent of everything collected to
+ ;; this point.
+ (python-imenu--put-parent type name pos num-children tree t)
+ ;; There are no children, this is a lonely defun.
+ (cons label pos)))
+ ((equal min-indent indent)
+ ;; Stop collecting nodes after moving to a position with
+ ;; indentation equaling min-indent. This is specially
+ ;; useful for navigating nested definitions recursively.
+ tree)
+ (t
+ (python-imenu--build-tree
+ min-indent
+ indent
+ ;; Add another children, either when this is the
+ ;; first call or when indentation is
+ ;; less-or-equal than previous. And do not
+ ;; discard the number of children, because the
+ ;; way code is scanned, all children are
+ ;; collected until a root node yet to be found
+ ;; appears.
+ (if (or (not prev-indent)
+ (and
+ (> indent min-indent)
+ (<= indent prev-indent)))
+ (1+ num-children)
+ num-children)
+ (cond ((not prev-indent)
+ ;; First call to the function: append this
+ ;; defun to the index.
+ (list (cons label pos)))
+ ((= indent prev-indent)
+ ;; Add another defun with the same depth
+ ;; as the previous.
+ (cons (cons label pos) tree))
+ ((and (< indent prev-indent)
+ (< 0 num-children))
+ ;; There are children to be appended and
+ ;; the previous defun had more
+ ;; indentation, the current one must be a
+ ;; parent.
+ (python-imenu--put-parent type name pos num-children tree))
+ ((> indent prev-indent)
+ ;; There are children defuns deeper than
+ ;; current depth. Fear not, we already
+ ;; know how to treat them.
+ (cons
+ (prog1
+ (python-imenu--build-tree
+ prev-indent indent 1 (list (cons label pos)))
+ ;; Adjustment: after scanning backwards
+ ;; for all deeper children, we need to
+ ;; continue our scan for a parent from
+ ;; the current defun we are looking at.
+ (python-nav-forward-defun))
+ tree))))))))
+
+(defun python-imenu-create-index ()
+ "Return tree Imenu alist for the current python buffer.
+Change `python-imenu-format-item-label-function',
+`python-imenu-format-parent-item-label-function',
+`python-imenu-format-parent-item-jump-label-function' to
+customize how labels are formatted."
+ (goto-char (point-max))
+ (let ((index)
+ (tree))
+ (while (setq tree (python-imenu--build-tree))
+ (setq index (cons tree index)))
+ index))
+
+(defun python-imenu-create-flat-index (&optional alist prefix)
+ "Return flat outline of the current python buffer for Imenu.
+Optional Argument ALIST is the tree to be flattened, when nil
+`python-imenu-build-index' is used with
+`python-imenu-format-parent-item-jump-label-function'
+`python-imenu-format-parent-item-label-function'
+`python-imenu-format-item-label-function' set to (lambda (type
+name) name). Optional Argument PREFIX is used in recursive calls
+and should not be passed explicitly.
+
+Converts this:
+
+ \((\"Foo\" . 103)
+ (\"Bar\" . 138)
+ (\"decorator\"
+ (\"decorator\" . 173)
+ (\"wrap\"
+ (\"wrap\" . 353)
+ (\"wrapped_f\" . 393))))
+
+To this:
+
+ \((\"Foo\" . 103)
+ (\"Bar\" . 138)
+ (\"decorator\" . 173)
+ (\"decorator.wrap\" . 353)
+ (\"decorator.wrapped_f\" . 393))"
+ (apply
+ 'nconc
+ (mapcar
+ (lambda (item)
+ (let ((name (if prefix
+ (concat prefix "." (car item))
+ (car item)))
+ (pos (cdr item)))
+ (cond ((or (numberp pos) (markerp pos))
+ (list (cons name pos)))
+ ((listp pos)
+ (message "%S" item)
+ (cons
+ (cons name (cdar pos))
+ (python-imenu-create-flat-index (cddr item) name))))))
+ (or alist
+ (let ((python-imenu-format-item-label-function (lambda (type name) name))
+ (python-imenu-format-parent-item-label-function (lambda (type name) name))
+ (python-imenu-format-parent-item-jump-label-function (lambda (type name) name)))
+ (python-imenu-create-index))))))
;;; Misc helpers
@@ -3337,6 +3516,22 @@ Optional argument DIRECTION defines the direction to move to."
(goto-char comment-start))
(forward-comment factor)))
+(defun python-util-popn (lst n)
+ "Return LST first N elements.
+N should be an integer, when it's a natural negative number its
+opposite is used. When N is bigger than the length of LST, the
+list is returned as is."
+ (let* ((n (min (abs n)))
+ (len (length lst))
+ (acc))
+ (if (> n len)
+ lst
+ (while (< 0 n)
+ (setq acc (cons (car lst) acc)
+ lst (cdr lst)
+ n (1- n)))
+ (reverse acc))))
+
;;;###autoload
(define-derived-mode python-mode prog-mode "Python"
@@ -3382,11 +3577,8 @@ if that value is non-nil."
(add-hook 'post-self-insert-hook
'python-indent-post-self-insert-function nil 'local)
- (set (make-local-variable 'imenu-extract-index-name-function)
- #'python-info-current-defun)
-
- (set (make-local-variable 'imenu-prev-index-position-function)
- #'python-imenu-prev-index-position)
+ (set (make-local-variable 'imenu-create-index-function)
+ #'python-imenu-create-index)
(set (make-local-variable 'add-log-current-defun-function)
#'python-info-current-defun)
diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el
index b03619e03d9..ed61adec1fe 100644
--- a/lisp/vc/vc-dispatcher.el
+++ b/lisp/vc/vc-dispatcher.el
@@ -329,7 +329,9 @@ case, and the process object in the asynchronous case."
command squeezed))))
(when vc-command-messages
(message "Running %s in background..." full-command))
- ;;(set-process-sentinel proc (lambda (p msg) (delete-process p)))
+ ;; Get rid of the default message insertion, in case we don't
+ ;; set a sentinel explicitly.
+ (set-process-sentinel proc #'ignore)
(set-process-filter proc 'vc-process-filter)
(setq status proc)
(when vc-command-messages