Merge branch 'maint'

This commit is contained in:
Marco Wahl 2015-12-16 08:41:19 +01:00
commit 986475a699
1 changed files with 233 additions and 154 deletions

View File

@ -4,7 +4,7 @@
;; Author: Paul M. Rodriguez <paulmrodriguez@gmail.com> ;; Author: Paul M. Rodriguez <paulmrodriguez@gmail.com>
;; Created: 2010-05-05 ;; Created: 2010-05-05
;; Version: 4.0 ;; Version: 4.1
;; This file is not part of GNU Emacs. ;; This file is not part of GNU Emacs.
@ -78,12 +78,6 @@
:group 'org-velocity :group 'org-velocity
:type 'file) :type 'file)
(defcustom org-velocity-search-is-incremental t
"Show results incrementally when possible?"
:group 'org-velocity
:type 'boolean
:safe 'booleanp)
(defcustom org-velocity-show-previews t (defcustom org-velocity-show-previews t
"Show previews of the text of each heading?" "Show previews of the text of each heading?"
:group 'velocity :group 'velocity
@ -168,20 +162,27 @@ See the documentation for `org-capture-templates'."
The length of the preview is determined by `window-width'. The length of the preview is determined by `window-width'.
Replace all contiguous whitespace with single spaces." Replace all contiguous whitespace with single spaces."
(let ((start (progn (let* ((start (progn
(forward-line 1) (forward-line 1)
(if (looking-at org-property-start-re) (if (looking-at org-property-start-re)
(re-search-forward org-property-end-re) (re-search-forward org-property-end-re)
(1- (point)))))) (1- (point)))))
(mapconcat (string+props (buffer-substring
#'identity start
(split-string (min
(buffer-substring-no-properties (+ start (window-width))
start (point-max)))))
(min ;; We want to preserve the text properties so that, for example,
(+ start (window-width)) ;; we don't end up with the raw text of links in the preview.
(point-max)))) (with-temp-buffer
" "))) (insert string+props)
(goto-char (point-min))
(save-match-data
(while (re-search-forward split-string-default-separators
(point-max)
t)
(replace-match " ")))
(buffer-string))))
(cl-defstruct org-velocity-heading buffer position name level preview) (cl-defstruct org-velocity-heading buffer position name level preview)
@ -233,9 +234,16 @@ of the base buffer; in the latter, return the file name of
(defun org-velocity-minibuffer-contents () (defun org-velocity-minibuffer-contents ()
"Return the contents of the minibuffer when it is active." "Return the contents of the minibuffer when it is active."
(if (active-minibuffer-window) (when (active-minibuffer-window)
(with-current-buffer (window-buffer (active-minibuffer-window)) (with-current-buffer (window-buffer (active-minibuffer-window))
(minibuffer-contents)))) (minibuffer-contents))))
(defun org-velocity-nix-minibuffer ()
"Return the contents of the minibuffer and clear it."
(when (active-minibuffer-window)
(with-current-buffer (window-buffer (active-minibuffer-window))
(prog1 (minibuffer-contents)
(delete-minibuffer-contents)))))
(defun org-velocity-bucket-file () (defun org-velocity-bucket-file ()
"Return the proper file for Org-Velocity to search. "Return the proper file for Org-Velocity to search.
@ -259,6 +267,7 @@ use it."
(error "No bucket and not an Org file")))))) (error "No bucket and not an Org file"))))))
(defvar org-velocity-bucket-buffer nil) (defvar org-velocity-bucket-buffer nil)
(defvar org-velocity-navigating nil)
(defsubst org-velocity-bucket-buffer () (defsubst org-velocity-bucket-buffer ()
(or org-velocity-bucket-buffer (or org-velocity-bucket-buffer
@ -271,9 +280,6 @@ use it."
(defsubst org-velocity-match-window () (defsubst org-velocity-match-window ()
(get-buffer-window (org-velocity-match-buffer))) (get-buffer-window (org-velocity-match-buffer)))
(defsubst org-velocity-match-staging-buffer ()
(get-buffer-create " Velocity matches"))
(defun org-velocity-beginning-of-headings () (defun org-velocity-beginning-of-headings ()
"Goto the start of the first heading." "Goto the start of the first heading."
(goto-char (point-min)) (goto-char (point-min))
@ -310,29 +316,47 @@ use it."
(make-variable-buffer-local 'org-velocity-saved-winconf) (make-variable-buffer-local 'org-velocity-saved-winconf)
(defun org-velocity-edit-entry (heading) (defun org-velocity-edit-entry (heading)
(if org-velocity-navigating
(org-velocity-edit-entry/inline heading)
(org-velocity-edit-entry/indirect heading)))
(cl-defun org-velocity-goto-entry (heading &key narrow)
(goto-char (org-velocity-heading-position heading))
(save-excursion
(when narrow
(org-narrow-to-subtree))
(outline-show-all)))
(defun org-velocity-edit-entry/inline (heading)
"Edit entry at HEADING in the original buffer."
(let ((buffer (org-velocity-heading-buffer heading)))
(pop-to-buffer buffer)
(with-current-buffer buffer
(org-velocity-goto-entry heading))))
(defun org-velocity-format-header-line (control-string &rest args)
(set (make-local-variable 'header-line-format)
(apply #'format control-string args)))
(defun org-velocity-edit-entry/indirect (heading)
"Edit entry at HEADING in an indirect buffer." "Edit entry at HEADING in an indirect buffer."
(let ((winconf (current-window-configuration)) (let ((winconf (current-window-configuration))
(dd default-directory)
(buffer (org-velocity-make-indirect-buffer heading)) (buffer (org-velocity-make-indirect-buffer heading))
(inhibit-point-motion-hooks t) (inhibit-point-motion-hooks t)
(inhibit-field-text-motion t)) (inhibit-field-text-motion t))
(with-current-buffer buffer (with-current-buffer buffer
(setq default-directory dd) ;Inherit default directory.
(setq org-velocity-saved-winconf winconf) (setq org-velocity-saved-winconf winconf)
(goto-char (org-velocity-heading-position heading)) (org-velocity-goto-entry heading :narrow t)
(let ((start (point))
(end (save-excursion
(org-end-of-subtree t)
(point))))
;; Outline view and narrow-to-region interact poorly.
(outline-flag-region start end nil)
(narrow-to-region start end))
(goto-char (point-max)) (goto-char (point-max))
(add-hook 'org-ctrl-c-ctrl-c-hook 'org-velocity-dismiss nil t)) (add-hook 'org-ctrl-c-ctrl-c-hook 'org-velocity-dismiss nil t))
(pop-to-buffer buffer) (pop-to-buffer buffer)
(set (make-local-variable 'header-line-format) (org-velocity-format-header-line
(format "%s Use C-c C-c to finish." "%s Use C-c C-c to finish."
(abbreviate-file-name (abbreviate-file-name
(buffer-file-name (buffer-file-name
(org-velocity-heading-buffer heading))))))) (org-velocity-heading-buffer heading))))))
(defun org-velocity-dismiss () (defun org-velocity-dismiss ()
"Save current entry and close indirect buffer." "Save current entry and close indirect buffer."
@ -350,9 +374,7 @@ use it."
(button-get button 'search) (button-get button 'search)
search-ring-max)) search-ring-max))
(let ((match (button-get button 'match))) (let ((match (button-get button 'match)))
(throw 'org-velocity-done (throw 'org-velocity-done match)))
(lambda ()
(org-velocity-edit-entry match)))))
(define-button-type 'org-velocity-button (define-button-type 'org-velocity-button
'action #'org-velocity-visit-button 'action #'org-velocity-visit-button
@ -374,57 +396,113 @@ use it."
(org-velocity-heading-preview heading) (org-velocity-heading-preview heading)
'face 'shadow)))) 'face 'shadow))))
(defvar org-velocity-recursive-headings nil)
(defvar org-velocity-recursive-search nil)
(cl-defun org-velocity-search-with (fun style search
&key (headings org-velocity-recursive-headings))
(if headings
(save-restriction
(dolist (heading headings)
(widen)
(let ((start (org-velocity-heading-position heading)))
(goto-char start)
(let ((end (save-excursion
(org-end-of-subtree)
(point))))
(narrow-to-region start end)
(org-velocity-search-with fun style search
:headings nil)))))
(cl-ecase style
((phrase any regexp)
(cl-block nil
(while (re-search-forward search nil t)
(let ((match (org-velocity-nearest-heading (point))))
(funcall fun match))
;; Skip to the next heading.
(unless (re-search-forward (org-velocity-heading-regexp) nil t)
(cl-return)))))
((all)
(let ((keywords
(cl-loop for word in (split-string search)
collect (concat "\\<" (regexp-quote word) "\\>"))))
(org-map-entries
(lambda ()
;; Only search the subtree once.
(setq org-map-continue-from
(save-excursion
(org-end-of-subtree)
(point)))
(when (cl-loop for word in keywords
always (save-excursion
(re-search-forward word org-map-continue-from t)))
(let ((match (org-velocity-nearest-heading (match-end 0))))
(funcall fun match))))))))))
(defun org-velocity-all-results (style search)
(with-current-buffer (org-velocity-bucket-buffer)
(save-excursion
(goto-char (point-min))
(let (matches)
(org-velocity-search-with (lambda (match)
(push match matches))
style
search)
(nreverse matches)))))
(defsubst org-velocity-present-match (hint match) (defsubst org-velocity-present-match (hint match)
(with-current-buffer (org-velocity-match-staging-buffer) (with-current-buffer (org-velocity-match-buffer)
(when hint (insert "#" hint " ")) (when hint (insert "#" hint " "))
(org-velocity-buttonize match) (org-velocity-buttonize match)
(org-velocity-insert-preview match) (org-velocity-insert-preview match)
(newline))) (newline)))
(defun org-velocity-generic-search (search &optional hide-hints) (defun org-velocity-present-search (style search hide-hints)
"Display any entry containing SEARCH."
(let ((hints org-velocity-index) matches) (let ((hints org-velocity-index) matches)
(cl-block nil (cl-block nil
(while (and hints (re-search-forward search nil t)) (org-velocity-search-with (lambda (match)
(let ((match (org-velocity-nearest-heading (point)))) (unless hints
(org-velocity-present-match (cl-return))
(unless hide-hints (car hints)) (let ((hint (if hide-hints
match) nil
(push match matches)) (car hints))))
(setq hints (cdr hints)) (org-velocity-present-match hint match))
(unless (re-search-forward (org-velocity-heading-regexp) nil t) (pop hints)
(return)))) (push match matches))
style
search))
(nreverse matches))) (nreverse matches)))
(cl-defun org-velocity-all-search (search &optional hide-hints) (defun org-velocity-restrict-search ()
"Display only entries containing every word in SEARCH." (interactive)
(let ((keywords (mapcar 'regexp-quote (split-string search))) (let ((search (org-velocity-nix-minibuffer)))
(hints org-velocity-index) (when (equal search "")
matches) (error "No search to restrict to"))
(org-map-entries (push search org-velocity-recursive-search)
(lambda () (setq org-velocity-recursive-headings
;; Return if we've run out of hints. (org-velocity-all-results
(when (null hints) org-velocity-search-method
(return-from org-velocity-all-search (nreverse matches))) search))
;; Only search the subtree once. ;; TODO We could extend the current search instead of starting
(setq org-map-continue-from ;; over.
(save-excursion (org-velocity-update-match-header)
(goto-char (line-end-position)) (minibuffer-message "Restricting search to %s" search)))
(if (re-search-forward (org-velocity-heading-regexp) nil t)
(line-end-position) (cl-defun org-velocity-update-match-header (&key (match-buffer (org-velocity-match-buffer))
(point-max)))) (bucket-buffer (org-velocity-bucket-buffer))
(when (cl-loop for word in keywords (search-method org-velocity-search-method))
always (save-excursion (let ((navigating? org-velocity-navigating)
(re-search-forward (recursive? org-velocity-recursive-search))
(concat "\\<" word "\\>") (with-current-buffer match-buffer
org-map-continue-from t))) (org-velocity-format-header-line
(let ((match (org-velocity-nearest-heading (match-end 0)))) "%s search in %s%s (%s mode)"
(org-velocity-present-match (capitalize (symbol-name search-method))
(unless hide-hints (car hints)) (abbreviate-file-name (buffer-file-name bucket-buffer))
match) (if (not recursive?)
(push match matches) ""
(setq hints (cdr hints)))))) (let ((sep " > "))
(nreverse matches))) (concat sep (string-join (reverse recursive?) sep))))
(if navigating? "nav" "notes")))))
(cl-defun org-velocity-present (search &key hide-hints) (cl-defun org-velocity-present (search &key hide-hints)
"Buttonize matches for SEARCH in `org-velocity-match-buffer'. "Buttonize matches for SEARCH in `org-velocity-match-buffer'.
@ -432,40 +510,49 @@ If HIDE-HINTS is non-nil, display entries without indices. SEARCH
binds `org-velocity-search'. binds `org-velocity-search'.
Return matches." Return matches."
(if (and (stringp search) (not (string= "" search))) (let ((match-buffer (org-velocity-match-buffer))
;; Fold case when the search string is all lowercase. (bucket-buffer (org-velocity-bucket-buffer))
(let ((case-fold-search (equal search (downcase search))) (search-method org-velocity-search-method))
(truncate-partial-width-windows t)) (if (and (stringp search) (not (string= "" search)))
(with-current-buffer (org-velocity-match-buffer) ;; Fold case when the search string is all lowercase.
(erase-buffer) (let ((case-fold-search (equal search (downcase search)))
;; Permanent locals. (truncate-partial-width-windows t))
(setq cursor-type nil (with-current-buffer match-buffer
truncate-lines t)) (erase-buffer)
(prog1 ;; Permanent locals.
(with-current-buffer (org-velocity-bucket-buffer) (setq cursor-type nil
(let ((inhibit-point-motion-hooks t) truncate-lines t)
(inhibit-field-text-motion t)) (org-velocity-update-match-header
(save-excursion :match-buffer match-buffer
(org-velocity-beginning-of-headings) :bucket-buffer bucket-buffer
(cl-case org-velocity-search-method :search-method search-method))
(all (org-velocity-all-search search hide-hints)) (prog1
(phrase (org-velocity-generic-search (with-current-buffer bucket-buffer
(concat "\\<" (regexp-quote search)) (widen)
hide-hints)) (let* ((inhibit-point-motion-hooks t)
(any (org-velocity-generic-search (inhibit-field-text-motion t)
(concat "\\<" (anchored? (string-match-p "^\\s-" search))
(regexp-opt (split-string search))) (search
hide-hints)) (cl-ecase search-method
(regexp (condition-case lossage (all search)
(org-velocity-generic-search (phrase
search hide-hints) (if anchored?
(invalid-regexp (regexp-quote search)
(minibuffer-message "%s" lossage)))))))) ;; Anchor the search to the start of a word.
(with-current-buffer (org-velocity-match-buffer) (concat "\\<" (regexp-quote search))))
(buffer-swap-text (org-velocity-match-staging-buffer)) (any
(goto-char (point-min))))) (concat "\\<" (regexp-opt (split-string search))))
(with-current-buffer (org-velocity-match-buffer) (regexp search))))
(erase-buffer)))) (save-excursion
(org-velocity-beginning-of-headings)
(condition-case lossage
(org-velocity-present-search search-method search hide-hints)
(invalid-regexp
(minibuffer-message "%s" lossage))))))
(with-current-buffer match-buffer
(goto-char (point-min)))))
(with-current-buffer match-buffer
(erase-buffer)))))
(defun org-velocity-store-link () (defun org-velocity-store-link ()
"Function for `org-store-link-functions'." "Function for `org-store-link-functions'."
@ -603,7 +690,7 @@ If ASK is non-nil, ask first."
(matches (org-velocity-present search :hide-hints t))) (matches (org-velocity-present search :hide-hints t)))
(cond ((null matches) (cond ((null matches)
(select-window (active-minibuffer-window)) (select-window (active-minibuffer-window))
(unless (or (null search) (string= "" search)) (unless (or (null search) (= (length search) 0))
(minibuffer-message "No match; RET to create"))) (minibuffer-message "No match; RET to create")))
((and (null (cdr matches)) ((and (null (cdr matches))
org-velocity-exit-on-match) org-velocity-exit-on-match)
@ -625,7 +712,10 @@ If ASK is non-nil, ask first."
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
(set-keymap-parent map minibuffer-local-completion-map) (set-keymap-parent map minibuffer-local-completion-map)
(define-key map " " 'self-insert-command) (define-key map " " 'self-insert-command)
(define-key map "?" 'self-insert-command)
(define-key map [remap minibuffer-complete] 'minibuffer-complete-word) (define-key map [remap minibuffer-complete] 'minibuffer-complete-word)
(define-key map [(control ?@)] 'org-velocity-restrict-search)
(define-key map [(control ?\s)] 'org-velocity-restrict-search)
map) map)
"Keymap for completion with `completing-read'.") "Keymap for completion with `completing-read'.")
@ -635,30 +725,9 @@ If ASK is non-nil, ask first."
org-velocity-local-completion-map) org-velocity-local-completion-map)
(completion-no-auto-exit t) (completion-no-auto-exit t)
(crm-separator " ")) (crm-separator " "))
(funcall (completing-read prompt
(cl-case org-velocity-search-method (completion-table-dynamic
(phrase #'completing-read) 'org-velocity-dabbrev-completion-list))))
(any #'completing-read-multiple)
(all #'completing-read-multiple))
prompt
(completion-table-dynamic
'org-velocity-dabbrev-completion-list))))
(defun org-velocity-read-string (prompt &optional initial-input)
"Read string with PROMPT followed by INITIAL-INPUT."
;; The use of initial inputs to the minibuffer is deprecated (see
;; `read-from-minibuffer'), but in this case it is the user-friendly
;; thing to do.
(minibuffer-with-setup-hook
(let ((initial-input initial-input))
(lambda ()
(and initial-input (insert initial-input))
(goto-char (point-max))))
(if (eq org-velocity-search-method 'regexp)
(read-regexp prompt)
(if org-velocity-use-completion
(org-velocity-read-with-completion prompt)
(read-string prompt)))))
(cl-defun org-velocity-adjust-index (cl-defun org-velocity-adjust-index
(&optional (match-window (org-velocity-match-window))) (&optional (match-window (org-velocity-match-window)))
@ -719,18 +788,28 @@ then the current file is used instead, and vice versa."
arg))) arg)))
;; complain if inappropriate ;; complain if inappropriate
(cl-assert (org-velocity-bucket-file)) (cl-assert (org-velocity-bucket-file))
(let ((org-velocity-bucket-buffer (let* ((starting-buffer (current-buffer))
(find-file-noselect (org-velocity-bucket-file)))) (org-velocity-bucket-buffer
(find-file-noselect (org-velocity-bucket-file)))
(org-velocity-navigating
(eq starting-buffer org-velocity-bucket-buffer))
(org-velocity-recursive-headings '())
(org-velocity-recursive-search '())
(org-velocity-heading-level
(if org-velocity-navigating
0
org-velocity-heading-level))
(dabbrev-search-these-buffers-only
(list org-velocity-bucket-buffer)))
(unwind-protect (unwind-protect
(let ((dabbrev-search-these-buffers-only (let ((match
(list (org-velocity-bucket-buffer)))) (catch 'org-velocity-done
(funcall (org-velocity-engine
(catch 'org-velocity-done (or search
(org-velocity-engine (org-velocity-incremental-read "Velocity search: ")))
(if org-velocity-search-is-incremental nil)))
(org-velocity-incremental-read "Velocity search: ") (when (org-velocity-heading-p match)
(org-velocity-read-string "Velocity search: " search))) (org-velocity-edit-entry match)))
#'ignore)))
(kill-buffer (org-velocity-match-buffer)))))) (kill-buffer (org-velocity-match-buffer))))))
(defalias 'org-velocity-read 'org-velocity) (defalias 'org-velocity-read 'org-velocity)