org-index.el, version 5.3.0: focus can now be a list; cleaned up dependencies

This commit is contained in:
U-IHM-NOTEBOOK\Olli 2017-03-28 20:57:37 +02:00
parent 4ac47e507d
commit 0ea6845711
1 changed files with 136 additions and 75 deletions

View File

@ -3,7 +3,7 @@
;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
;; Author: Marc Ihm <org-index@2484.de>
;; Version: 5.2.3
;; Version: 5.3.0
;; Keywords: outlines index
;; This file is not part of GNU Emacs.
@ -85,6 +85,10 @@
;;; Change Log:
;; [2017-03-26 Su] Version 5.3.0
;; - Focused can now be on a list of nodes (instead of a single one)
;; - Cleaned up undeclared dependencies
;;
;; [2017-02-18 Sa] Version 5.2.3
;; - New command 'focus'
;; - Speeded up org-index--parse-table with the stored property "max-ref"
@ -175,11 +179,12 @@
;;; Code:
(require 'org-table)
(require 'org-id)
(require 'cl-lib)
(require 'widget)
;; Version of this package
(defvar org-index-version "5.2.3" "Version of `org-index', format is major.minor.bugfix, where \"major\" are incompatible changes and \"minor\" are new features.")
(defvar org-index-version "5.3.0" "Version of `org-index', format is major.minor.bugfix, where \"major\" are incompatible changes and \"minor\" are new features.")
;; customizable options
(defgroup org-index nil
@ -224,14 +229,14 @@ mixed First, show all index entries, which have been
:type 'key-sequence)
(defcustom org-index-idle-delay 68
"Delay in seconds after which buffer will sorted or fontified when emacs is idle."
"Delay in seconds after which buffer will sorted or fontified when Emacs is idle."
:group 'org-index
:type 'integer)
(defcustom org-index-prepare-when-idle nil
"Optionally fontify and sort index-table when idle, so that first interactive call is faster.
You only need this if your index has grown so large, that first invocation of org-index needs
a noticable amount of time."
"Fontify and sort index-table when idle to make first call faster.
You only need this if your index has grown so large, that first
invocation of `org-index' needs a noticable amount of time."
:group 'org-index
:initialize 'custom-initialize-set
:set (lambda (var val)
@ -303,7 +308,8 @@ those pieces."
(defvar org-index--saved-positions nil "Saved positions within current buffer and index buffer; filled by org-index--save-positions.")
(defvar org-index--headings nil "Headlines of index-table as a string.")
(defvar org-index--headings-visible nil "Visible part of headlines of index-table as a string.")
(defvar org-index--id-focused-node nil "Id of focused node (if any).")
(defvar org-index--ids-focused-nodes nil "Ids of focused node (if any).")
(defvar org-index--id-last-goto-focus nil "Id of last node, that has been jumped to.")
;; Variables to hold context and state
(defvar org-index--last-fingerprint nil "Fingerprint of last line created.")
@ -367,31 +373,31 @@ if VALUE cannot be found."
(defun org-index (&optional command search-ref arg)
"Fast search-index for selected org nodes and things outside of org.
org-index creates and updates an index table with keywords; each line
either points to a heading in org, references something outside or
carries a snippet of text to yank. The index table is searched for
keywords through an incremental occur; results are sorted by usage
count and date, so that frequently used entries appear first among
the results.
This function creates and updates an index table with keywords;
each line either points to a heading in org, references something
outside or carries a snippet of text to yank. The index table is
searched for keywords by means of an incremental occur; results
are sorted by usage count and date, so that frequently used
entries appear first.
References are decorated numbers (e.g. 'R237' or '--455--'); they are
well suited to be used outside of org, e.g. in folder names, ticket
systems or on printed documents.
On first invocation org-index will help to create a dedicated node
On first invocation this function will help to create a dedicated node
for its index table.
To start building up your index, use subcommands 'add', 'ref' and
'yank' to create entries and use 'occur' to find them.
This is version 5.2.3 of org-index.el.
This is version 5.3.0 of org-index.el.
The function `org-index' is the only interactive function of this
package and its main entry point; it will present you with a list
of subcommands to choose from:
\(Note the one-letter shortcuts, e.g. [o]; used like 'C-c i o'.)
\(Note the one-letter shortcuts, e.g. [o]; used like `\\[org-index-dispatch] o'.)
occur: [o] Incrementally show matching lines from index.
Result is updated after every keystroke. You may enter a
@ -400,7 +406,7 @@ of subcommands to choose from:
add: [a] Add the current node to index.
So that (e.g.) it can be found through the subcommand
'occur'. Update index, if node is already present.
'occur'. Update index, if node is already present.
kill: [k] Kill (delete) the current node from index.
Can be invoked from index, from occur or from a headline.
@ -428,16 +434,20 @@ of subcommands to choose from:
edit: [e] Present current line in edit buffer.
Can be invoked from index, from occur or from a headline.
help: Show complete help text of org-index.
help: Show complete help text of `org-index'.
focus: [f] Return to focus-node; need to set-focus before.
The focused node is a single and special node, the location
of which is remembered and which can be found with a single
key-sequence; it need not be part of the index though. This
can be useful, if you mostly work in a single node, but make
frequent excursions to others.
focus: [f] Return to first focused node; repeat to see them all.
With prefix: reverse order. You Need to set-focus before.
The focused nodes are kept in a short list and can be found
by hitting a single key; they need not be part of the index
though. This can be useful, if you work in one or few nodes,
but make frequent excursions to others, which are part of the
index.
set-focus: [F] Set focus-node for command focus.
set-focus: [F] Set focus to current node, with prefix: append.
To truncate the list of focused nodes, just focus on a single
node; to remove current node from focus list supply a double
prefix.
short-help: [?] Show one-line description of each subcommand.
I.e. show this list but only first sentence each.
@ -450,7 +460,7 @@ of subcommands to choose from:
by count, reference or last access.
find-ref: Search for given reference in all org-buffers.
A wrapper to employ emacs standard `multi-occur' function;
A wrapper to employ Emacs standard `multi-occur' function;
asks for reference.
highlight: Highlight or unhighlight all references.
@ -463,18 +473,18 @@ of subcommands to choose from:
If you invoke `org-index' for the first time, an assistant will be
invoked, that helps you to create your own index.
Invoke `org-customize' to tweak the behaviour of org-index.
Invoke `org-customize' to tweak the behaviour of `org-index'.
Optionally bind `org-index-dispatch' to a key, e.g. 'C-c i' in
the global keymap to invoke the most important subcommands with
a single key.
This includes the global key `org-index-dispatch-key' to invoke
the most important subcommands with one additional key.
A numeric prefix argument is used as a reference number for
commands, that need one (e.g. 'head').
commands, that need one (e.g. 'head') or to modify their
behaviour (e.g. 'focus').
Use from elisp: Optional argument COMMAND is a symbol naming the
command to execute. SEARCH-REF specifies a reference to search
for, if needed. ARG allows passing in a prefix argument as in
command to execute. SEARCH-REF specifies a reference to search
for, if needed. ARG allows passing in a prefix argument as in
interactive calls."
(interactive "i\ni\nP")
@ -557,9 +567,9 @@ interactive calls."
(unless search-ref
(if (eq command 'index)
(let ((r (org-index--read-search-for-index)))
(setq search-ref (first r))
(setq search-id (second r))
(setq search-fingerprint (third r)))
(setq search-ref (cl-first r))
(setq search-id (cl-second r))
(setq search-fingerprint (cl-third r)))
(unless (and (eq command 'head)
org-index--within-index-node
(org-at-table-p))
@ -710,7 +720,7 @@ interactive calls."
((eq command 'ping)
(let ((moved-up 0) id info reached-top)
(let ((moved-up 0) id info reached-top done)
(unless (string= major-mode "org-mode") (error "No node at point"))
;; take id from current node or reference
@ -721,17 +731,16 @@ interactive calls."
;; move up until we find a node in index
(save-excursion
(outline-back-to-heading)
(while (not (or info
reached-top))
(while (not done)
(if id
(setq info (org-index--on 'id id
(mapcar (lambda (x) (org-index--get-or-set-field x))
(list 'ref 'count 'created 'last-accessed 'category 'keywords 'ref)))))
(list 'keywords 'count 'created 'last-accessed 'category 'ref)))))
(setq reached-top (= (org-outline-level) 1))
(unless (or info
reached-top)
(if (or info reached-top)
(setq done t)
(outline-up-heading 1 t)
(cl-incf moved-up))
@ -741,9 +750,9 @@ interactive calls."
(progn
(setq message-text
(apply 'format
(append (list "'%s'%shas been accessed %s times between %s and %s; category is '%s', keywords are '%s'"
(append (list "'%s'%s has been accessed %s times between %s and %s; category is '%s', reference is '%s'"
(pop info)
(if (> moved-up 0) (format " (parent node, %d level up) " moved-up) " "))
(if (> moved-up 0) (format " (parent node, %d level up)" moved-up) ""))
info)))
(setq kill-new-text (car (last info))))
(setq message-text "Neither this node nor any of its parents is part of index"))))
@ -835,9 +844,9 @@ interactive calls."
(symbol-name sort)
org-index-sort-by
org-index-idle-delay
(second groups-and-counts)
(cl-second groups-and-counts)
(symbol-name sort)
(third groups-and-counts))))
(cl-third groups-and-counts))))
((memq sort-what '(region buffer))
(org-index--do-sort-lines sort-what)
@ -863,25 +872,11 @@ interactive calls."
((eq command 'focus)
(if org-index--id-focused-node
(let (marker)
(setq marker (org-id-find org-index--id-focused-node 'marker))
(unless marker (error "Could not find focus-node"))
(pop-to-buffer-same-window (marker-buffer marker))
(goto-char (marker-position marker))
(org-index--unfold-buffer)
(move-marker marker nil)
(setq message-text "Jumped to focus-node"))
(setq message-text "No focus-node, use set-focus")))
(setq message-text (org-index--goto-focus arg)))
((eq command 'set-focus)
(let ((focus-id (org-id-get-create)))
(with-current-buffer org-index--buffer
(org-entry-put org-index--point "id-focused-node" focus-id)
(setq org-index--id-focused-node focus-id)
(setq message-text "Focus has been set on current node"))))
(setq message-text (org-index--set-focus arg)))
((eq command 'maintain)
@ -1033,7 +1028,7 @@ Optional argument WITH-SHORT-HELP displays help screen upfront."
(with-temp-buffer
(insert (documentation 'org-index))
(goto-char (point-min))
(search-forward (concat " " (symbol-name (first org-index--commands)) ": "))
(search-forward (concat " " (symbol-name (cl-first org-index--commands)) ": "))
(forward-line 0)
(kill-region (point-min) (point))
(search-forward (concat " " (symbol-name (car (last org-index--commands))) ": "))
@ -1061,7 +1056,7 @@ Optional argument WITH-SHORT-HELP displays help screen upfront."
(insert (org-index--get-short-help-text))
(goto-char (point-min))
(while (< (point) (point-max))
(when (looking-at "^ \\([-a-z]+\\) +: +\\[\\([a-z?]\\)\\] ")
(when (looking-at "^ \\([-a-z]+\\)[ \t]+: +\\[\\([a-z?]\\)\\] ")
(setq org-index--shortcut-chars
(cons (cons (match-string 2) (intern (match-string 1)))
org-index--shortcut-chars)))
@ -1071,6 +1066,71 @@ Optional argument WITH-SHORT-HELP displays help screen upfront."
org-index--shortcut-chars)))
(defun org-index--goto-focus (arg)
"Goto focus node, one after the other; with ARG: reverse."
(if org-index--ids-focused-nodes
(let ((maybe-reverse (lambda (&rest x) (if (equal arg '(4)) (reverse x) x)))
last-id next-ids marker)
(setq last-id (or org-index--id-last-goto-focus
(last org-index--ids-focused-nodes)))
(setq next-id
(car (or (cdr-safe (member last-id
(apply maybe-reverse
(append org-index--ids-focused-nodes
org-index--ids-focused-nodes))))
(apply maybe-reverse org-index--ids-focused-nodes))))
(or (setq marker (org-id-find next-id 'marker))
(error "Could not find focus-node with id %s" next-id))
(setq org-index--id-last-goto-focus next-id)
(pop-to-buffer-same-window (marker-buffer marker))
(goto-char (marker-position marker))
(org-index--unfold-buffer)
(move-marker marker nil)
(if (cdr org-index--ids-focused-nodes)
(format "Jumped to %s focus-node (out of %d)"
(if (equal arg '(4)) "previous" "next")
(length org-index--ids-focused-nodes))
"Jumped to single focus-node"))
"No nodes in focus, use set-focus"))
(defun org-index--set-focus (arg)
"Set focus node, with prefix ARG, append to list, with double prefix: delete."
(let (id text)
(setq text
(cond
((not arg)
(setq id (org-id-get-create))
(setq org-index--ids-focused-nodes (list id))
"Focus has been set on current node (1 node in focus)")
((equal arg '(4))
(setq id (org-id-get-create))
(unless (member id org-index--ids-focused-nodes)
(setq org-index--ids-focused-nodes (cons id org-index--ids-focused-nodes)))
(setq org-index--id-last-goto-focus id)
"Current node has been appended to list of focused nodes (%d node%s in focus)")
((equal arg '(16))
(setq id (org-id-get))
(if (and id (member id org-index--ids-focused-nodes))
(progn
(setq org-index--id-last-goto-focus
(or (car-safe (cdr-safe (member id (reverse (append org-index--ids-focused-nodes
org-index--ids-focused-nodes)))))
org-index--id-last-goto-focus))
(setq org-index--ids-focused-nodes (delete id org-index--ids-focused-nodes))
"Current node has been removed from list of focused nodes (%d node%s in focus)")
"Current node has not been in list of focused nodes (%d node%s in focus)"))))
(with-current-buffer org-index--buffer
(org-entry-put org-index--point "ids-focused-nodes" (string-join org-index--ids-focused-nodes " ")))
(format text (length org-index--ids-focused-nodes) (if (cdr org-index--ids-focused-nodes) "s" ""))))
(defun org-index--do-edit ()
"Perform command edit."
(let ((maxlen 0) cols-vals buffer-keymap field-keymap keywords-pos val)
@ -1107,13 +1167,13 @@ Optional argument WITH-SHORT-HELP displays help screen upfront."
;; we need two different keymaps
(setq buffer-keymap (make-sparse-keymap))
(set-keymap-parent buffer-keymap widget-keymap)
(define-key buffer-keymap (kbd "C-c C-c") 'org-index--edit-c-c-c-c)
(define-key buffer-keymap (kbd "C-c C-k") 'org-index--edit-c-c-c-k)
(define-key buffer-keymap (kbd "C-c C-c") 'org-index--edit-accept)
(define-key buffer-keymap (kbd "C-c C-k") 'org-index--edit-abort)
(setq field-keymap (make-sparse-keymap))
(set-keymap-parent field-keymap widget-field-keymap)
(define-key field-keymap (kbd "C-c C-c") 'org-index--edit-c-c-c-c)
(define-key field-keymap (kbd "C-c C-k") 'org-index--edit-c-c-c-k)
(define-key field-keymap (kbd "C-c C-c") 'org-index--edit-accept)
(define-key field-keymap (kbd "C-c C-k") 'org-index--edit-abort)
;; prepare buffer
(setq org-index--context-index (cons (point) (org-index--line-in-canonical-form)))
@ -1141,8 +1201,8 @@ Optional argument WITH-SHORT-HELP displays help screen upfront."
"Editing a single line from index"))
(defun org-index--edit-c-c-c-c ()
"Function to invoke on C-c C-c in Edit buffer."
(defun org-index--edit-accept ()
"Function to accept editing in Edit buffer."
(interactive)
(let ((obuf (get-buffer org-index--occur-buffer-name))
@ -1204,8 +1264,8 @@ Optional argument WITH-SHORT-HELP displays help screen upfront."
(message "Index line has been edited.")))
(defun org-index--edit-c-c-c-k ()
"Function invoked on C-c C-k in Edit buffer."
(defun org-index--edit-abort ()
"Function to abort editing in Edit buffer."
(interactive)
(kill-buffer org-index--edit-buffer-name)
(setq org-index--context-index nil)
@ -1472,8 +1532,9 @@ Optional argument CHECK-SORT-MIXED triggers resorting if mixed and stale."
(unless org-index--head (org-index--get-decoration-from-ref-field ref-field))
(setq org-index--maxrefnum (org-index--extract-refnum ref-field))
;; Get id of focused node (if any)
(setq org-index--id-focused-node (org-entry-get nil "id-focused-node"))
;; Get ids of focused node (if any)
(setq org-index--ids-focused-nodes (split-string (or (org-entry-get nil "ids-focused-nodes") "")))
(org-entry-delete (point) "id-focused-node") ; migrate (kind of) from previous versions
;; save position below hline
(org-index--go-below-hline)
@ -2972,7 +3033,7 @@ If OTHER in separate window."
(setq yank (replace-regexp-in-string (regexp-quote "\\vert") "|" yank nil 'literal))
(kill-new yank)
(org-mark-ring-goto)
(if (s-starts-with-p "http" yank)
(if (string= (substring yank 0 3) "http")
(progn
(browse-url yank)
(format "Opened '%s' in browser (and copied it too)" yank))