[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] scratch/hyperbole-lexbind c547ad4 10/20: Merge branch '7.0.3a' in
From: |
Stefan Monnier |
Subject: |
[elpa] scratch/hyperbole-lexbind c547ad4 10/20: Merge branch '7.0.3a' into prepare-pr-for-merging |
Date: |
Wed, 14 Aug 2019 04:30:22 -0400 (EDT) |
branch: scratch/hyperbole-lexbind
commit c547ad4fab47ea266d30eeabe9402a2a215b8ddc
Merge: 9ad2bf0 da8f3fa
Author: Robert Weiner <address@hidden>
Commit: GitHub <address@hidden>
Merge branch '7.0.3a' into prepare-pr-for-merging
---
Changes | 201 +++++++++++++++++
DEMO | 5 +-
HY-ANNOUNCE | 207 +++++++++++++++++
HY-NEWS | 14 +-
hactypes.el | 53 ++++-
hargs.el | 7 +-
hbut.el | 644 ++++++++++++++++++++++++++++++++++++-----------------
hib-kbd.el | 17 +-
hibtypes.el | 141 ++++++++++--
hpath.el | 46 ++--
hsys-org.el | 211 ++++++++++++++++--
htz.el | 45 ++--
hui-mouse.el | 4 +-
hui.el | 22 +-
hypb.el | 17 +-
hyperbole.el | 2 +-
hyrolo.el | 59 +++--
kotl/kfill.el | 97 ++++----
kotl/kotl-mode.el | 14 +-
kotl/kvspec.el | 59 +++--
man/hyperbole.texi | 107 +++++----
21 files changed, 1481 insertions(+), 491 deletions(-)
diff --git a/Changes b/Changes
index 2989b2b..0815d4e 100644
--- a/Changes
+++ b/Changes
@@ -1,3 +1,204 @@
+2019-07-13 Bob Weiner <address@hidden>
+
+* hsys-org.el (org-set-ibut-label): Added and used in org-mode ibtype.
+ (org-mode, org-at-block-start-p): Added Action Key activation of
Org blocks when
+ on 1st line of def.
+
+* hibtypes.el (link-to-gbut, glink:start, glink:end): Added for in-buffer
links to global buttons.
+ (link-to-ebut, elink:start, elink:end): Added for in-buffer
links to explicit buttons.
+ (link-to-ibut, ilink:start, ilink:end): Added for in-buffer
links to implicit buttons.
+
+* hbut.el (ebut:label-p): Updated to better handle whether point is
+ between specified delimiters.
+
+2019-07-12 Bob Weiner <address@hidden>
+
+* hbut.el (ebut:key-src-set-buffer, hbut:key-src-set-buffer, hbut:key-list,
+ hbut:ebut-key-list, hbut:ibut-key-list, hbut:label-list): Added
+ to allow selection of labeled Hyperbole buttons in currrent buffer by name.
+ (ibut:to): Added to move to an implicit button in the current buffer
+ matching a label key.
+
+2019-07-11 Bob Weiner <address@hidden>
+
+* hargs.el (hargs:at-p): Added support for reading global button arguments.
+
+* hactypes.el (link-to-gbut): Updated to handle global labeled implicit
buttons.
+
+* hbut.el (gbut:get): Added.
+
+2019-07-10 Bob Weiner <address@hidden>
+
+* man/hyperbole.texi (Invisible Text Searches): Added missing {M-s i} key
sequence.
+
+* hibtypes.el (Info-node): Modified to skip costly hpath:is-p if ref
+ string is not of the right format.
+ (hibtypes-path-line-and-col-regexp, pathname-line-and-column):
Updated
+ to handle Elisp variables with colons.
+
+2019-07-09 Bob Weiner <address@hidden>
+
+* hbut.el (ibut:at-p): Conditionalized on (not (hbut:outside-comment-p)).
+ (hbut:map, ibut:label-map): Added.
+ (ibut:key-src, ibut:key-to-label, ibut:label-to-key, ibut:summarize):
Added.
+ Global, labeled implicit buttons now exist!
+
+2019-07-08 Bob Weiner <address@hidden>
+
+* hbut.el (ibut:label-separator, hbut:outside-comment-p): Added.
+
+2019-07-01 Bob Weiner <address@hidden>
+
+* hbut.el (gbut:ibut-key-list): Added.
+
+* hui.el (hui:hbut-term-highlight, hui:hbut-term-unhighlight): Fixed so
save-excursion is outermost.
+
+2019-06-29 Bob Weiner <address@hidden>
+
+* hbut.el (ebut:get, ebut:at-p, ebut:label-to-key, ibut:at-type-p): Simplified
conditionals using 'when'.
+ (ibut:label-start, ibut:label-end, ibut:label-p, ibut:get,
+ ibut:next-occurrence, ibut:label-regexp): Added.
+ (hbut:label-regexp): Added to support labeled implicit buttons too.
+ (ebut:label-regexp): Aliased to hbut:label-regexp.
+ (hbut:label-p): Updated to handle implicit button labels.
+
+2019-06-23 Bob Weiner <address@hidden>
+
+* hsys-org.el: Added many new predicates and code to handle navigation between
Org
+ mode internal links and their targets, as well as radio target definitions
and their links.
+ (hsys-org-mode-function, hsys-org-mode-p): Added to determine when
hsys-org actions
+ are activated.
+
+* hypb.el (hypb:region-with-text-property-value): Added and used in
hysy-org.el.
+
+* kotl/kfill.el (set-fill-prefix): Updated to better match standard Emacs
functiion.
+
+2019-06-22 Bob Weiner <address@hidden>
+
+* hyrolo.el (hyrolo-add): Fixed bug in call to match-string-no-properties.
+
+2019-06-21 Bob Weiner <address@hidden>
+
+* kotl/kotl-mode.el (kotl-mode): Set fill-paragraph-function rather than
overloading
+ fill-paragraph.
+ kotl/kfill.el (kfill:fill-paragraph): Renamed and used only in kotl-mode.
Also
+ temporarily set fill-paragraph-handle-comment to t and made prefix arg
optional.
+ (kfill:funcall): Removed.
+ (kfill:function-table): Removed.
+ (kfill:do-auto-fill): Temporarily set
fill-paragraph-handle-comment to t.
+
+2019-06-20 Bob Weiner <address@hidden>
+
+* hsys-org.el (org-link): Changed to call org-open-at-point which handles
internal
+ org links, fixing following links such as radio targets.
+ (org-thing-at-p, org-target-at-p): Added.
+
+* hpath.el (hpath:texinfo-section-pattern): Added and used in
hpath:to-markup-anchor to
+ jump to specific Texinfo sections.
+
+2019-06-19 Bob Weiner <address@hidden>
+
+* man/hyperbole.texi (Referent Display): Added doc of
hpath:native-image-suffixes.
+
+* hpath.el (hpath:find-program): Changed to prioritize
hpath:native-image-suffixes over
+ hpath:internal-display-alist over hpath:external-display-alist-macos
instead of the
+ reverse. This prevents external viewers from being used when internal
viewers are
+ also in effect.
+
+2019-06-18 Bob Weiner <address@hidden>
+
+* hibtypes.el (grep-msg): Allowed for null char in place of first colon in
colored grep output lines.
+
+2019-06-17 Bob Weiner <address@hidden>
+
+* hactypes.el (link-to-gbut): Added.
+ hui.el (hui:link-possible-types): Added link-to-gbut.
+
+2019-06-16 Bob Weiner <address@hidden>
+
+* hyrolo.el: Replaced buffer-substring-no-properties with
match-string-no-properties where possible.
+ (hyrolo-entry-regexp): Changed to require whitespace following
the entry prefix.
+ (hyrolo-entry-group-number): Added.
+
+2019-06-12 Bob Weiner <address@hidden>
+
+* hib-kbd.el (kbd-key): Fixed preceding character test to not depend on the
buffer's syntax table,
+ potentially missing kbd-key ibuts, notably ones using the universal
argument.
+
+* hbut.el (ibut:at-type-p): Added to test if point is on a specific type of
implicit button.
+
+* hib-kbd.el (kbd-key:normalize): Removed aggregation of C-u arguments into
something like: C-u(16)
+ as this no longer works in current Emacs and causes an error. Now this
just stays as "C-u C-u".
+
+2019-06-11 Bob Weiner <address@hidden>
+
+* hypb.el (hypb:format-quote): Modified to return non-string args as is rather
than ignoring them so
+ this can be used across any argument set. Used in hypb:error.
+
+2019-06-10 Bob Weiner <address@hidden>
+
+* htz.el (htz:date-parse): Fixed bug, missing seconds in format 4 leading to
invalid time strings saved
+ on MSWindows machines (and maybe more). Allow for this in style 5 which
is how Hyperbole stores dates.
+ (htz:time-make-string): Chop off any spurious digits at the right.
+
+* hactypes.el (link-to-ibut): Added.
+ hui.el (hui:link-possible-types): Added ibut:at-p call for link-to-ibut.
+
+2019-06-07 Bob Weiner <address@hidden>
+
+* hibtypes.el (debugger-source): Added support for pytype package errors
(close to Python pdb ones)
+
+2019-06-06 Bob Weiner <address@hidden>
+
+* hpath.el (hpath:find): Removed file-relative-name from error calls
+ because does not work when current-directory and filename are on different
+ drives under Windows at least through Emacs 26.
+ (hpath:find): Fixed that default-directory was not set to current
+ button's location, so path was expanded relative to another
+ directory, notably in hpath:validate call.
+
+2019-06-05 Bob Weiner <address@hidden>
+
+* hpath.el (hpath:is-p): Tightened remote-path check to prevent matches that
end with :line-num or :col-num.
+
+2019-06-04 Bob Weiner <address@hidden>
+
+* hactypes.el (annot-bib): Changed to find referent from the end of the buffer
rather than beginning,
+ to avoid multiple earlier annot-bib buttons
+* DEMO (Hyperbole Source Buttons): Changed example button from annot-bib to
kbd-key.
+
+* kotl/kvspec.el (kvspec:hide-levels): Changed behavior so view updates to
default level clipping when
+ 'l' is excluded from the viewspec.
+
+2019-06-02 Bob Weiner <address@hidden>
+
+* kotl/kvspec.el (kvspec:lines-to-show): Changed behavior so view updates to
default cell clipping when
+ 'c' is excluded from the viewspec.
+
+* kotl/kotl-mode.el (kotl-mode:show-all): Limited (kvspec:update t) call to
interactive usage only.
+ When kotl-mode:show-all is called in kvspec:update-view, it doesn't
overwrite the to be set viewspec.
+
+* kotl/kvspec.el (kvspec:show-lines-per-cell)
+ (kvspec:show-lines-this-cell): Fixed viewspec 'c0' to expand
visible cells properly.
+
+2019-06-01 Bob Weiner <address@hidden>
+
+* hibtypes.el (ipython_stack_frame): Added to handle ipython stack traces and
exceptions.
+
+2019-05-30 Bob Weiner <address@hidden>
+
+* hyperbole.el (hkey-maybe-global-set-key): Fix missing no-add argument
+ to hkey-global-set-key call.
+
+2019-05-26 Bob Weiner <address@hidden>
+
+* hui-mouse.el (hkey-alist): For Python files, use derived-mode-p and add
+ support for helm-pydoc buffers.
+
+==============================================================================
+V7.0.3a changes ^^^^:
+==============================================================================
+
2019-05-11 Bob Weiner <address@hidden>
* man/hyperbole.texi (External Viewers): Commented out reference to mailcap use
diff --git a/DEMO b/DEMO
index 1d3b4a1..22b9d51 100644
--- a/DEMO
+++ b/DEMO
@@ -816,8 +816,9 @@ displayed. Test this technique with a {C-x C-f}
(find-file) and then a {?}.
** Hyperbole Source Buttons
-If you ask for help with the Assist Key or {C-u C-h A} from within the
-[FSF 19] button, the first line of the help buffer will look like this:
+If you ask for help with the Assist Key or {C-h A} from within this button,
+{M-x dired-other-window RET ~ RET}, the first line of the help buffer will
+look like this:
@loc> "DEMO"
diff --git a/HY-ANNOUNCE b/HY-ANNOUNCE
index 7afa2a3..66feeb0 100644
--- a/HY-ANNOUNCE
+++ b/HY-ANNOUNCE
@@ -1,4 +1,211 @@
----------------------------------------------------------------------
+7.0.3 Announcement
+----------------------------------------------------------------------
+From: Bob Weiner <address@hidden>
+To: address@hidden, address@hidden, address@hidden, address@hidden,
address@hidden
+Subject: GNU Hyperbole 7.0.3: link your world quickly and easily
+--text follows this line--
+========================================================================
+* Introduction
+========================================================================
+
+GNU Hyperbole 7.0.3 is released and ready for action.
+
+Hyperbole is an amazing hypertextual information management system
+that installs quickly and easily as an Emacs package. It is part of
+GNU Elpa, the Emacs Lisp Package Archive.
+
+Hyperbole interlinks all your working information within Emacs for
+fast access and editing, not just within special modes. An hour
+invested exploring Hyperbole's built-in interactive DEMO file will
+save you hundreds of hours in your future work.
+
+7.0.3 is a significant release with a number of interesting
+improvements. What's new in this release is described here:
+
+ www.gnu.org/s/hyperbole/HY-NEWS.html
+
+Hyperbole is described here:
+
+ www.gnu.org/s/hyperbole
+
+For use cases, see:
+
+ www.gnu.org/s/hyperbole/HY-WHY.html
+
+For what users think about Hyperbole, see:
+
+ https://www.gnu.org/s/hyperbole/hyperbole.html#user-quotes
+
+Hyperbole can supplement and extend Org-mode's capabilities. It adds
+many features not found elsewhere in Emacs, including Org mode, see:
+
+ www.emacswiki.org/emacs/Hyperbole
+
+Hyperbole includes its own easy-to-use hypertextual buttons and links
+that can be created without the need for any markup language.
+
+Hyperbole has an interactive demo to introduce you to its features as
+well as a detailed reference manual, as explained here:
+
+ https://www.gnu.org/s/hyperbole/hyperbole.html#invocation-and-doc
+
+========================================================================
+* Quick Reasons to Try Hyperbole
+========================================================================
+
+It contains:
+
+- the most flexible and easy-to-use hyperbuttons available, including
+ implicit buttons automatically recognized by context, e.g. stack
+ trace source line references.
+
+- the only Emacs outliner with full legal item numbering,
+ e.g. 1.4.2.6, and automatic permanent hyperlink anchors for every
+ item
+
+- the only free-form contact manager with full-text search for Emacs
+
+- rapid and precise window, frame and buffer placement on screen
+
+- an extensive menu of typed web searches, e.g. dictionary, wikipedia
+ and stackoverflow, plus convenient, fast file and line finding
+ functions
+
+- immediate execution of a series of key presses just by typing them
+ out. For example, a M-RETURN press on: {C-x C-b C-s scratch RET
+ C-a} will find the first buffer menu item that contains 'scratch';
+ then leave point at the beginning of its line. Build interactive
+ tutorials with this.
+
+
+========================================================================
+* The Magic of Implicit Buttons and the Action Key
+========================================================================
+
+For near instant gratification, try Hyperbole's 'implicit button'
+capabilities (hyper-buttons that Hyperbole gives you for free by
+recognizing all types of references embedded within text such as
+pathnames or error message lines). Below are more complex examples to
+show the power; simpler ones can be found within the Hyperbole DEMO
+file.
+
+Implicit buttons are activated by pressing the Action Key, M-RETURN.
+Once Hyperbole is loaded in your Emacs, pressing M-RETURN on any of
+these examples *in virtually any buffer* will display the associated
+referent in a chosen window or frame, handling all variable
+substitution and full path resolution:
+
+ "find-func.el" Find this file whether gzipped
or not
+ in the Emacs Lisp load-path
+
+ "${hyperb:dir}/HY-NEWS" Resolve variable, show Hyperbole
news
+
+ "${PATH}/umask" Display a script somewhere in
multi-dir PATH
+
+ "${hyperb:dir}/DEMO#Hyperbole Menus" Org mode outline, Markdown, and
HTML # refs
+
+ "(hyperbole)Menus" Texinfo and Info node links
+
+ "c:/Users", "c:\Users", "/C/Users", "/c/Users", and "/mnt/c/Users"
+ On Windows and Windows Subsystem
for Linux,
+ Hyperbole recognizes all of these
as the
+ same path and can translate
between Windows
+ and POSIX path formats in both
directions
+
+Git Links:
+ git#branches List branches in current
repo/project
+ git#commits List and browse commits for
current project
+ git#tags List tags in current project
+
+ git#/hyperbole From any buffer, dired on the top
+ directory of the local hyperbole
+ project
+
+ git#/hyperbole/55a1f0 or From any buffer, display
hyperbole
+ git#hyperbole/55a1f0 local git commit diff
+
+
+Github Links:
+ gh@rswgnu Display user's home page &
projects
+
+ github#rswgnu/hyperbole Display user's project
+ gh#rswgnu/helm/global_mouse Display user project's branch
+ gh#rswgnu/hyperbole/55a1f0 Display user project's commit
diff
+
+Gitlab Links:
+ gitlab@seriyalexandrov Display user's home page
+ gl#gitlab-org/gitlab-ce/activity Summarize user's project activity
+ gl#gitlab-org/gitlab-ce/analytics Display user project's
cycle_analytics
+ gl#gitlab-org/gitlab-ce/boards Display user project's
kanban-type issue boards
+
+Once you set the default user and project variables, you can leave them off
any reference links:
+
+ (setq hibtypes-gitlab-default-user "gitlab-org")
+ (setq hibtypes-gitlab-default-project "gitlab-ce")
+
+ gl#issues or gl#list Display default project's issue
list
+ gl#labels Display default project's issue
categories
+ gl#members Display default project's staff
list
+ gl#contributors Show contributor push frequency
charts
+ gl#merge_requests or gl#pulls Display default project's pull
requests
+ gl#milestones Display default project's
milestones status
+ gl#pages Display default project's web
pages
+ gl#snippets Project snippets, diffs and text
with discussion
+ gl#groups List all available groups of
projects
+ gl#projects List all available projects
+
+ gl#milestone=38 Show a specific project milestone
+ gl#snippet/1689487 Show a specific project snippet
+
+Even useful social media links:
+ tw#travel or twitter#travel Display twitter hashtag matches
+ fb#technology Display facebook hashtag matches
+
+Hyperbole uses simple prefix characters with paths to make them executable:
+ "!/bin/date" Execute as a non-windowed
program within a shell
+ "&/opt/X11/bin/xeyes" Execute as a windowed program;
+ "-find-func.el" Load/execute this Emacs Lisp
library
+
+ File "/usr/lib/python3.7/ast.py", line 37, in parse
+ Jump to error/stack trace source
+
+ "/ftp:address@hidden:" Tramp remote paths
+
+
+========================================================================
+* Try It - Installs or Uninstalls in a Minute
+========================================================================
+
+Hyperbole lets you concentrate more on your work. Then as you grow
+with it across time, it helps speed your work across weeks and months.
+It installs in about a minute and can be uninstalled even faster if
+ever need be. Give it a try.
+
+Hyperbole can boost your day-to-day productivity with Emacs and
+your ability to manage information stored across many different
+machines on the internet.
+
+Hyperbole can be installed like any other package with the Emacs
+package manager:
+
+ {M-x list-packages RET C-s hyperbole RET i x y}
+
+Then to invoke its menu:
+
+ {C-h h} or {M-x hyperbole RET}
+
+The best way to get a feel for many of its capabilities is to
+invoke the interactive DEMO and explore sections of interest:
+
+ {C-h h d d}
+
+Enjoy,
+
+The Hyperbole Team
+
+
+----------------------------------------------------------------------
7.0.2 Announcement
----------------------------------------------------------------------
From: Bob Weiner <address@hidden>
diff --git a/HY-NEWS b/HY-NEWS
index 61e138c..0429549 100644
--- a/HY-NEWS
+++ b/HY-NEWS
@@ -887,7 +887,7 @@ are new in 2016 and you should look through them all.
Implicit-Button menu.
- On the Hyperbole Customize/Change-Key-Bindings menubar menu, renamed
- these entries and added Mark-Think-Key. Similar updates done to the
+ these entries and added Mark-Thing-Key. Similar updates done to the
minibuffer menu.
MOUSE AND SMART KEY SUPPORT
@@ -906,7 +906,7 @@ are new in 2016 and you should look through them all.
help mode so you can page through it with SPC and DEL keys and then quit
from it with {q}.
- - A click of the Action Mouse Key within an inactive minibuffer menu
+ - A click of the Action Mouse Key within an inactive minibuffer window
displays the Hyperbole minibuffer menu, allowing you to invoke menu
entries with the mouse. A click of the Assist Key in the same place
displays the buffer, window and frame jump menu just as does a click
@@ -1008,13 +1008,13 @@ are new in 2016 and you should look through them all.
- Added missing {C-c C-i}/{C-c TAB} binding mentioned in the EXAMPLE.kotl
file; sets cell attributes.
- - {C=t} Transpose characters - Added error checks at the beginning of cells
+ - {C-t} Transpose characters - Added error checks at the beginning of cells
and end of lines for times when there are not 2 chars to transpose.
ROLO
- Improved {M-s} interactive string searching for rolo match buffer
strings.
- Made {C-u M-s} to a regexp search for rolo match buffer strings.
+ Made {C-u M-s} do a regexp search for rolo match buffer strings.
- Documented the {l} hyrolo-locate command in the Hyperbole manual.
@@ -1211,8 +1211,8 @@ are new in 2016 and you should look through them all.
INSTALLATION
- - Installation is greatly simplified. A single emacs initialization line
- of the form:
+ - Hyperbole initialization is greatly simplified. A single "~/.emacs"
+ line of the form:
(require 'hyperbole (expand-file-name "hyperbole" "<HYPERBOLE-DIR>/")
@@ -1266,7 +1266,7 @@ are new in 2016 and you should look through them all.
now begin with 'K'. Some used to start with 'O'. To edit the example
Koutline, use {C-h h k e}.
- - {C-c C-a} - Show-all, expand all cells nihe current view.
+ - {C-c C-a} - Show-all, expand all cells in the current view.
{C-c C-o} - Overview, show only first line of outline cells.
{C-c C-t} - Top-level, hide all cells below level 1 and show
only the first line of each level 1 cell.
diff --git a/hactypes.el b/hactypes.el
index bfe03fc..d227faa 100644
--- a/hactypes.el
+++ b/hactypes.el
@@ -29,8 +29,8 @@
(key-regexp (concat "^[*]*[ \t]*\\\[" (ebut:key-to-label key) "\\\]"))
citation)
(if (save-excursion
- (goto-char (point-min))
- (setq citation (re-search-forward key-regexp nil t)))
+ (goto-char (point-max))
+ (setq citation (re-search-backward key-regexp nil t)))
(progn (hpath:display-buffer (current-buffer))
(goto-char citation)
(beginning-of-line))
@@ -272,11 +272,12 @@ Use `link-to-file' instead for a permanent link."
nil nil nil 'ebut)))
(beep))
(ebut:label-to-key but-lbl)))))
- (or (called-interactively-p 'interactive)
- (setq key-file (hpath:validate (hpath:substitute-value key-file))))
+ (unless (called-interactively-p 'interactive)
+ (setq key-file (hpath:validate (hpath:substitute-value key-file))))
(let ((but (ebut:get key (find-file-noselect key-file))))
(if but (hbut:act but)
- (hypb:error "(link-to-ebut): No button `%s' in `%s'." (ebut:key-to-label
key)
+ (hypb:error "(link-to-ebut): No button `%s' in `%s'."
+ (ebut:key-to-label key)
key-file))))
(defact link-to-elisp-doc (symbol)
@@ -351,6 +352,24 @@ the window."
(hpath:find-line path line-num))
(move-to-column column-num)))
+(defact link-to-gbut (key)
+ "Performs action given by an existing global button, specified by KEY."
+ (interactive
+ (let ((gbut-file (hpath:validate (hpath:substitute-value gbut:file)))
+ but-lbl)
+ (if (not (file-readable-p gbut-file))
+ (hypb:error "(link-to-gbut): You cannot read `%s'." gbut-file)
+ (list (progn
+ (find-file-noselect gbut-file)
+ (while (string-equal "" (setq but-lbl
+ (hargs:read-match
+ "Global button to link to: "
+ (mapcar 'list (gbut:label-list))
+ nil t nil 'gbut)))
+ (beep))
+ (hbut:label-to-key but-lbl))))))
+ (gbut:act (hbut:key-to-label key)))
+
(defact link-to-Info-index-item (index-item)
"Displays an Info index INDEX-ITEM cross-reference.
INDEX-ITEM must be a string of the form \"(filename)item-name\". During
@@ -373,6 +392,30 @@ available. Filename may be given without the .info
suffix."
(id-info string)
(hypb:error "(link-to-Info-node): Invalid Info node: `%s'" string)))
+(defact link-to-ibut (key-file key &optional point)
+ "Performs action given by an implicit button, specified by KEY-FILE, KEY and
optional POINT.
+When creating the button, point must be on the implicit button to which to link
+and its buffer must have a file attached."
+ (interactive
+ (let ((ibut-key (ibut:at-p t)))
+ (if (and ibut-key buffer-file-name)
+ (list buffer-file-name ibut-key (point))
+ (list nil nil nil))))
+ (or (called-interactively-p 'interactive)
+ (setq key-file (hpath:validate (hpath:substitute-value key-file))))
+ (let (but)
+ (if (and key-file
+ (save-excursion
+ (save-restriction
+ (find-file-noselect key-file)
+ (widen)
+ (if (integerp point) (goto-char (min point (point-max))))
+ (setq but (ibut:to key)))))
+ (hbut:act but)
+ (hypb:error "(link-to-ibut): No button `%s' in `%s'."
+ (ibut:key-to-label key)
+ key-file))))
+
(defact link-to-kcell (file cell-ref)
"Displays FILE with kcell given by CELL-REF at window top.
See documentation for `kcell:ref-to-id' for valid cell-ref formats.
diff --git a/hargs.el b/hargs.el
index 696cdab..e5ea221 100644
--- a/hargs.el
+++ b/hargs.el
@@ -320,7 +320,10 @@ Handles all of the interactive argument types that
`hargs:iform-read' does."
(t 0)))))
((hargs:completion t))
((eq hargs:reading-p 'ebut) (ebut:label-p 'as-label))
- ((ebut:label-p) nil)
+ ((eq hargs:reading-p 'gbut)
+ (when (eq (current-buffer) (get-file-buffer gbut:file))
+ (hbut:label-p 'as-label)))
+ ((hbut:label-p) nil)
((eq hargs:reading-p 'file)
(cond ((derived-mode-p 'dired-mode)
(let ((file (dired-get-filename nil t)))
@@ -517,7 +520,7 @@ See also documentation for `interactive'."
;; `@' means select window of last mouse event.
;;
;; `^' means activate/deactivate mark depending on
invocation thru shift translation
- ;; See `this-command-keys-shift-translated' for somewhat of
an explanation.
+ ;; See `this-command-keys-shift-translated' for an
explanation.
;;
;; `_' means keep region in same state (active or inactive)
;; after this command. (XEmacs only.)
diff --git a/hbut.el b/hbut.el
index e4104f9..cc71510 100644
--- a/hbut.el
+++ b/hbut.el
@@ -33,8 +33,7 @@ Nil disables saving.")
(defconst ebut:max-len 100
"Maximum length of a hyper-button label.")
-
-(defun ebut:act (label)
+(defun ebut:act (label)
"Activates Hyperbole explicit button with LABEL from the current buffer."
(interactive (list (hargs:read-match "Activate explicit button labeled: "
(ebut:alist)
@@ -46,7 +45,7 @@ Nil disables saving.")
(error "(ebut:act): No explicit button labeled: %s" label))))
(defun ebut:alist (&optional file)
- "Returns alist with each element a list containing a button label.
+ "Returns alist with each element a list containing an explicit button label.
For use as a completion table. Gets labels from optional FILE or current
buffer."
(mapcar 'list (ebut:list file)))
@@ -57,7 +56,8 @@ Assumes point is within first line of button label, if at all.
Optional START-DELIM and END-DELIM are strings that override default
button delimiters."
(let ((key (ebut:label-p nil start-delim end-delim)))
- (and key (ebut:get key))))
+ (when key
+ (ebut:get key))))
(defun ebut:create (&optional but-sym)
"Creates Hyperbole explicit button based on optional BUT-SYM.
@@ -95,60 +95,58 @@ Returns entry deleted (a list of attribute values) or nil."
(defun ebut:get (&optional lbl-key buffer key-src)
"Returns explicit Hyperbole button symbol given by LBL-KEY and BUFFER.
-KEY-SRC is given when retrieving global buttons and is full source pathname.
+KEY-SRC is given when retrieving global buttons and is the full source
pathname.
+
Retrieves button data, converts into a button object and returns a symbol
which references the button.
-All arguments are optional. When none are given, returns symbol for
-button that point is within or nil. BUFFER defaults to the current
+All arguments are optional. When none are given, returns a symbol for
+the button that point is within or nil. BUFFER defaults to the current
buffer."
(hattr:clear 'hbut:current)
(save-excursion
(let ((key-file) (key-dir) (but-data) (actype))
- (or lbl-key (setq lbl-key (ebut:label-p)))
- (if buffer
- (if (bufferp buffer) (set-buffer buffer)
+ (unless lbl-key
+ (setq lbl-key (ebut:label-p)))
+ (when buffer
+ (if (bufferp buffer)
+ (set-buffer buffer)
(error "(ebut:get): Invalid buffer argument: %s" buffer)))
- (if key-src
- nil
- (if (equal lbl-key (ebut:label-p))
- nil
+ (when (not key-src)
+ (when (not (equal lbl-key (ebut:label-p)))
(goto-char (point-min))
(ebut:next-occurrence lbl-key))
- (if (setq key-src (ebut:key-src 'full))
- ;; `ebut:key-src' sets current buffer to key-src buffer.
- (setq buffer (current-buffer)))
- )
- (if (and (stringp lbl-key) key-src)
- (progn
- (if (stringp key-src)
- (setq key-dir (file-name-directory key-src)
- key-file (file-name-nondirectory key-src)))
- (setq but-data (and key-src
- (hbdata:get-entry lbl-key (or key-file key-src)
- key-dir)))
- (if (null but-data)
- nil
- (hattr:set 'hbut:current 'lbl-key lbl-key)
- (hattr:set 'hbut:current 'loc key-src)
- (hattr:set 'hbut:current 'categ 'explicit)
- (hattr:set 'hbut:current 'action nil)
- (hattr:set 'hbut:current 'actype
- (intern (setq actype (hbdata:actype but-data))))
- ;; Hyperbole V1 referent compatibility
- (if (= (length actype) 2)
- (hattr:set 'hbut:current 'referent
- (hbdata:referent but-data)))
- (hattr:set 'hbut:current 'args (hbdata:args but-data))
- (hattr:set 'hbut:current 'creator (hbdata:creator but-data))
- (hattr:set 'hbut:current
- 'create-time (hbdata:create-time but-data))
- (hattr:set 'hbut:current
- 'modifier (hbdata:modifier but-data))
- (hattr:set 'hbut:current
- 'mod-time (hbdata:mod-time but-data))
- 'hbut:current)
- )))))
+ (when (setq key-src (ebut:key-src 'full))
+ ;; `ebut:key-src' sets current buffer to key-src buffer.
+ (setq buffer (current-buffer))))
+ (when (and (stringp lbl-key) key-src)
+ (when (stringp key-src)
+ (setq key-dir (file-name-directory key-src)
+ key-file (file-name-nondirectory key-src)))
+ (setq but-data (and key-src
+ (hbdata:get-entry lbl-key (or key-file key-src)
+ key-dir)))
+ (when but-data
+ (hattr:set 'hbut:current 'lbl-key lbl-key)
+ (hattr:set 'hbut:current 'loc key-src)
+ (hattr:set 'hbut:current 'categ 'explicit)
+ (hattr:set 'hbut:current 'action nil)
+ (hattr:set 'hbut:current 'actype
+ (intern (setq actype (hbdata:actype but-data))))
+ ;; Hyperbole V1 referent compatibility
+ (if (= (length actype) 2)
+
+ (hattr:set 'hbut:current 'referent
+ (hbdata:referent but-data)))
+ (hattr:set 'hbut:current 'args (hbdata:args but-data))
+ (hattr:set 'hbut:current 'creator (hbdata:creator but-data))
+ (hattr:set 'hbut:current
+ 'create-time (hbdata:create-time but-data))
+ (hattr:set 'hbut:current
+ 'modifier (hbdata:modifier but-data))
+ (hattr:set 'hbut:current
+ 'mod-time (hbdata:mod-time but-data))
+ 'hbut:current)))))
(defun ebut:is-p (object)
"Returns non-nil if OBJECT denotes an explicit Hyperbole button."
@@ -174,21 +172,17 @@ With optional FULL when source is a pathname, the full
pathname is returned."
((save-excursion
(and (re-search-backward
"^[a-z]*make[^a-z]+\\(Entering\\|Leaving\\)
directory `\\([^']+\\)'" nil t)
- (string-equal "Entering"
- (buffer-substring (match-beginning 1)
- (match-end 1)))))
+ (string-equal "Entering" (match-string 1))))
(let ((limit (match-end 2))
;; Latest working directory that `make' reported
- (wd (buffer-substring (match-beginning 2)
- (match-end 2)))
+ (wd (match-string 2))
cd)
;; But another cd or pushd command may have been issued.
;; Return the closest directory from the make output.
(if (re-search-backward
"\\<\\(cd\\|pushd\\)\\s
+[\"\']?\\([^;\"\'\n\r\^L\\]+\\)"
limit t)
- (progn (setq cd (buffer-substring (match-beginning 2)
- (match-end 2)))
+ (progn (setq cd (match-string 2))
;; Eliminate any trailing whitespace.
(setq cd (substring
cd 0 (string-match "\\s +\\'" cd)))
@@ -209,18 +203,22 @@ With optional FULL when source is a pathname, the full
pathname is returned."
(= (point) (point-min))))
(hbut:source full)))))
(t (current-buffer)))))
- (cond ((null src) nil)
- ((bufferp src)
- (set-buffer src)
- src)
- ((file-directory-p src)
- (file-name-as-directory src))
- ((file-readable-p src)
- (set-buffer (find-file-noselect src))
- src)
- ((file-readable-p (setq src (hpath:symlink-referent src)))
- (set-buffer (find-file-noselect src))
- src))))
+ (ebut:key-src-set-buffer src)))
+
+(defun ebut:key-src-set-buffer (src)
+ "Set buffer to SRC, a buffer, file, directory or symlink and return SRC or
nil if invalid."
+ (cond ((null src) nil)
+ ((bufferp src)
+ (set-buffer src)
+ src)
+ ((file-directory-p src)
+ (file-name-as-directory src))
+ ((file-readable-p src)
+ (set-buffer (find-file-noselect src))
+ src)
+ ((file-readable-p (setq src (hpath:symlink-referent src)))
+ (set-buffer (find-file-noselect src))
+ src)))
(defun ebut:key-src-fmt ()
"Returns unformatted filename associated with formatted current buffer.
@@ -256,35 +254,34 @@ represent the output of particular document formatters."
lbl)))
(defun ebut:label-p (&optional as-label start-delim end-delim pos-flag
two-lines-flag)
- "Returns key for Hyperbole button label that point is within.
-Returns nil if not within a label. Assumes point is within first line
- of button label, if at all.
-All following arguments are optional. If AS-LABEL is non-nil, label
-is returned rather than the key derived from the label. START-DELIM
-and END-DELIM are strings that override default button delimiters.
-With POS-FLAG non-nil, returns list of label-or-key,
-but-start-position, but-end-position. Positions include delimiters.
-With TWO-LINES-FLAG non-nil, constrains label search to two lines."
+ "Returns key for the Hyperbole explicit button label that point is within,
else nil.
+Assumes point is within the first line of any button label. All
+following arguments are optional. If AS-LABEL is non-nil, label
+is returned rather than the key derived from the label.
+START-DELIM and END-DELIM are strings that override default
+button delimiters. With POS-FLAG non-nil, returns list of
+label-or-key, but-start-position, but-end-position. Positions
+include delimiters. With TWO-LINES-FLAG non-nil, constrains
+label search to two lines."
(let ((opoint (point))
- (npoint)
(quoted "\\(^\\|[^\\{]\\)")
- (start)
(ebut:max-len ebut:max-len)
- lbl-key end but-start but-end)
- (or start-delim (setq start-delim ebut:start))
- (or end-delim (setq end-delim ebut:end))
- (setq npoint (+ opoint (length start-delim)))
- ;; Ensure label is not blank
+ npoint start lbl-key end but-start but-end start-regexp end-regexp)
+ (unless start-delim (setq start-delim ebut:start))
+ (unless end-delim (setq end-delim ebut:end))
+ (setq start-regexp (regexp-quote start-delim)
+ end-regexp (regexp-quote end-delim)
+ npoint (+ opoint (length start-delim)))
+ ;; Ensure label is not blank and point is within matching delimiters
(save-excursion
- (beginning-of-line)
+ (forward-line 0)
(while (and (progn
- (while (re-search-forward
- (concat quoted (regexp-quote start-delim))
- npoint t)
+ (while (and (< (point) npoint)
+ (re-search-forward (concat quoted start-regexp)
npoint t))
(setq start t))
start)
- (re-search-forward (concat "[^\\{]" (regexp-quote end-delim))
- npoint t))
+ (< (point) opoint)
+ (re-search-forward (concat "[^\\{]" end-regexp) opoint t))
(setq start nil))
(when start
(setq start (point)
@@ -302,49 +299,24 @@ With TWO-LINES-FLAG non-nil, constrains label search to
two lines."
(forward-line 2)
(setq ebut:max-len (- (point) start))))
(and (< (point) (+ start ebut:max-len))
- (re-search-forward (concat quoted (regexp-quote end-delim))
- (+ start ebut:max-len) t)
+ (re-search-forward (concat quoted end-regexp) (+ start
ebut:max-len) t)
(setq but-end (point)
end (- (point) (length end-delim))
- lbl-key (ebut:label-to-key (buffer-substring start end)))
+ lbl-key (ebut:label-to-key (buffer-substring-no-properties
start end)))
(cond (pos-flag
(if as-label
(list (ebut:key-to-label lbl-key) but-start but-end)
(list lbl-key but-start but-end)))
(t (if as-label (ebut:key-to-label lbl-key) lbl-key))))))))
-(defun ebut:label-regexp (lbl-key &optional no-delim)
- "Unnormalizes LBL-KEY. Returns regular expr matching delimited but label.
-Optional NO-DELIM leaves off delimiters and leading and trailing space."
- (if lbl-key
- (let* ((pos 0)
- (len (length lbl-key))
- (c)
- (sep0 "[ \t\n\r]*")
- (sep "[ \t\n\r]+")
- (regexp (if no-delim "" (concat (regexp-quote ebut:start) sep0)))
- (case-fold-search))
- (while (< pos len)
- (setq c (aref lbl-key pos)
- regexp (concat regexp
- (if (eq c ?_)
- (if (or (= (1+ pos) len)
- (not (eq (aref lbl-key (1+ pos))
?_)))
- sep
- (setq pos (1+ pos))
- "_")
- (regexp-quote (char-to-string c))))
- pos (1+ pos)))
- (if no-delim regexp
- (setq regexp (concat regexp sep0 (regexp-quote ebut:end)))))))
+(defalias 'ebut:label-regexp 'hbut:label-regexp)
(defun ebut:label-to-key (label)
"Normalizes LABEL for use as a Hyperbole button key and returns key.
Eliminates any fill prefix in the middle of the label, replaces `_' with
`__', removes leading and trailing whitespace and replaces each other
whitespace sequence with `_'."
- (if (null label)
- nil
+ (when label
(setq label (hbut:fill-prefix-remove label)
;; Remove leading and trailing space.
label (hypb:replace-match-string "\\`[ \t\n\r]+\\|[ \t\n\r]+\\'"
@@ -356,31 +328,30 @@ whitespace sequence with `_'."
"Returns list of button labels from given FILE or current buffer.
Removes duplicate labels if optional LOC-P is omitted. With LOC-P, returns
list of elements (label start end) where start and end are the buffer
-positions at which the starting button delimiter begins and ends."
+positions at which the button delimiter begins and ends."
(interactive)
(setq file (if file (and (file-exists-p file) (find-file-noselect file))
(current-buffer)))
- (if file
- (progn
- (set-buffer file)
- (let ((buts (ebut:map (if loc-p
- (lambda (lbl start end)
- ;; Normalize label spacing
- (list (ebut:key-to-label
- (ebut:label-to-key lbl))
- start end))
- (lambda (lbl start end)
- ;; Normalize label spacing
- (ebut:key-to-label
- (ebut:label-to-key lbl)))))))
- (if loc-p buts (if buts (apply #'set:create buts)))))))
-
-(defalias 'map-ebut 'ebut:map)
+ (when file
+ (set-buffer file)
+ (let ((buts (ebut:map (if loc-p
+ (lambda (lbl start end)
+ ;; Normalize label spacing
+ (list (ebut:key-to-label (ebut:label-to-key
lbl))
+ start end))
+ (lambda (lbl start end)
+ ;; Normalize label spacing
+ (ebut:key-to-label (ebut:label-to-key lbl)))))))
+ (if loc-p buts (if buts (apply #'set:create buts))))))
+
+(defalias 'map-ebut 'ebut:map)
(defun ebut:map (but-func &optional start-delim end-delim
regexp-match include-delims)
"Applies BUT-FUNC to buttons delimited by optional START-DELIM and END-DELIM.
+START-DELIM defaults to ebut:start; END-DELIM defaults to ebut:end.
If REGEXP-MATCH is non-nil, only buttons which match this argument are
considered.
+
Maps over portion of buffer visible under any current restriction.
BUT-FUNC must take precisely three arguments: the button label, the
start position of the delimited button label and its end position (positions
@@ -405,12 +376,10 @@ expression which matches an entire button string."
nil t)
(setq start (match-beginning include-delims)
end (match-end include-delims)
- but (buffer-substring (match-beginning 0) (match-end 0))
- lbl (buffer-substring (match-beginning 1) (match-end 1))
+ but (match-string 0)
+ lbl (match-string 1)
;; If within a programming language buffer, ignore matches
outside comments.
- ignore (and (derived-mode-p 'prog-mode)
- ;; Match is outside of a programming language comment
- (not (nth 4 (syntax-ppss)))))
+ ignore (hbut:outside-comment-p))
(save-excursion
(goto-char start)
;; Ignore matches with quoted delimiters.
@@ -638,9 +607,9 @@ Inserts INSTANCE-STR after END, before ending delimiter."
"\\)" match-part (regexp-quote ebut:end)))
(defconst ebut:start "<("
- "String matching the start of a hyper-button.")
+ "String matching the start of a Hyperbole explicit hyper-button.")
(defconst ebut:end ")>"
- "String matching the end of a hyper-button.")
+ "String matching the end of a Hyperbole explicit hyper-button.")
(defconst ebut:instance-sep ":"
"String of one character, separates an ebut label from its instance num.")
@@ -648,25 +617,36 @@ Inserts INSTANCE-STR after END, before ending delimiter."
;;; gbut class - Global Hyperbole buttons - activated by typing label name
;;; ========================================================================
-(defvar gbut:file (expand-file-name hbmap:filename hbmap:dir-user)
+(defvar gbut:file (expand-file-name hbmap:filename hbmap:dir-user)
"File that stores globally accessible Hyperbole buttons, accessed by name.")
-(defun gbut:act (label)
+(defun gbut:act (label)
"Activates Hyperbole global button with LABEL."
(interactive (list (hargs:read-match "Activate global button labeled: "
(mapcar 'list (gbut:label-list))
- nil t nil 'ebut)))
+ nil t nil 'gbut)))
(cond ((null label)
(error "(gbut:act): You have not created any global buttons"))
((equal label "")
(error "(gbut:act): Please try again and type ? for a list of existing
global button names"))
(t (let* ((lbl-key (hbut:label-to-key label))
- (but (ebut:get lbl-key nil gbut:file)))
+ (but (gbut:get lbl-key)))
(if but
(hbut:act but)
(error "(gbut:act): No global button labeled: %s" label))))))
-(defun gbut:help (label)
+(defun gbut:get (&optional lbl-key)
+ "Returns global Hyperbole button symbol given by optional LBL-KEY if found
in gbut:file.
+
+Retrieves any button data, converts into a button object and returns a symbol
+which references the button.
+
+All arguments are optional. When none are given, returns a symbol for
+the button that point is within or nil."
+ (or (ebut:get lbl-key nil gbut:file)
+ (ibut:get lbl-key nil gbut:file)))
+
+(defun gbut:help (label)
"Displays help for Hyperbole global button with LABEL."
(interactive (list (hargs:read-match "Report on global button labeled: "
(mapcar 'list (gbut:label-list))
@@ -677,18 +657,22 @@ Inserts INSTANCE-STR after END, before ending delimiter."
(hbut:report but)
(error "(gbut:help): No global button labeled: %s" label))))
-(defun gbut:label-list ()
+(defun gbut:label-list ()
"Returns list of global button labels."
(mapcar 'hbut:key-to-label (gbut:key-list)))
;;; ------------------------------------------------------------------------
-(defun gbut:key-list ()
+(defun gbut:key-list ()
"Returns list of global button label keys."
+ (nconc (gbut:ebut-key-list) (gbut:ibut-key-list)))
+
+(defun gbut:ebut-key-list ()
+ "Returns a list of explicit button label keys from the global button file."
(save-excursion
(if (hbdata:to-entry-buf gbut:file)
- (let ((gbuts))
+ (let (gbuts)
(save-restriction
- (narrow-to-region (point) (if (search-forward "\^L" nil t)
+ (narrow-to-region (point) (if (search-forward "\f" nil t)
(point) (point-max)))
(goto-char (point-min))
(condition-case ()
@@ -696,6 +680,15 @@ Inserts INSTANCE-STR after END, before ending delimiter."
(error nil))
gbuts)))))
+(defun gbut:ibut-key-list ()
+ "Returns a list of implicit button label keys from the global button file."
+ (when (file-readable-p gbut:file)
+ (save-excursion
+ (set-buffer (find-file-noselect gbut:file))
+ (save-restriction
+ (widen)
+ (ibut:label-map #'(lambda (label start end) (ibut:label-to-key
label)))))))
+
;;; ========================================================================
;;; hattr class
;;; ========================================================================
@@ -807,7 +800,7 @@ Suitable for use as part of `write-file-functions'."
"Sets OBJ-SYMBOL's attribute ATTR-SYMBOL to ATTR-VALUE and returns
ATR-VALUE."
(put obj-symbol attr-symbol attr-value))
-(defalias 'hattr:summarize 'hattr:report)
+(defalias 'hattr:summarize 'hattr:report)
(defvar hattr:filename
(if hyperb:microsoft-os-p "_hypb" ".hypb")
@@ -918,8 +911,9 @@ Ignores email-related buffers."
"Returns non-nil if object denotes a Hyperbole button."
(and (symbolp object) (hattr:get object 'categ)))
-(defalias 'hbut:key-src 'ebut:key-src)
-(defalias 'hbut:key-to-label 'ebut:key-to-label)
+(defalias 'hbut:key-src 'ebut:key-src)
+(defalias 'hbut:key-src-set-buffer 'ebut:key-src-set-buffer)
+(defalias 'hbut:key-to-label 'ebut:key-to-label)
(defun hbut:label (hbut)
"Returns the label for Hyperbole button symbol HBUT."
@@ -928,8 +922,60 @@ Ignores email-related buffers."
(error "(hbut:label): Argument is not a Hyperbole button symbol, `%s'"
hbut)))
-(defalias 'hbut:label-p 'ebut:label-p)
-(defalias 'hbut:label-to-key 'ebut:label-to-key)
+(defun hbut:label-p (&optional as-label start-delim end-delim pos-flag
two-lines-flag)
+ "Returns key for the Hyperbole button label that point is within, else nil.
+Assumes point is within the first line of any button label. All
+following arguments are optional. If AS-LABEL is non-nil, label
+is returned rather than the key derived from the label.
+START-DELIM and END-DELIM are strings that override default
+button delimiters. With POS-FLAG non-nil, returns list of
+label-or-key, but-start-position, but-end-position. Positions
+include delimiters. With TWO-LINES-FLAG non-nil, constrains
+label search to two lines."
+ (if (and start-delim end-delim)
+ (ebut:label-p as-label start-delim end-delim pos-flag two-lines-flag)
+ (or (ebut:label-p as-label start-delim end-delim pos-flag two-lines-flag)
+ (ibut:label-p as-label start-delim end-delim pos-flag two-lines-flag))))
+
+(defun hbut:label-regexp (lbl-key &optional no-delim start-delim end-delim)
+ "Unnormalizes LBL-KEY. Returns regular expr matching delimited button label.
+Optional NO-DELIM leaves off delimiters and leading and trailing space.
+Optional START-DELIM and END-DELIM are added around the returned
+label; these default to `ebut:start' and `ebut:end'."
+ (when lbl-key
+ (let* ((pos 0)
+ (len (length lbl-key))
+ (c)
+ (sep0 "[ \t\n\r]*")
+ (sep "[ \t\n\r]+")
+ (regexp (if no-delim "" (concat (regexp-quote (or start-delim
ebut:start)) sep0)))
+ (case-fold-search))
+ (while (< pos len)
+ (setq c (aref lbl-key pos)
+ regexp (concat regexp
+ (if (eq c ?_)
+ (if (or (= (1+ pos) len)
+ (not (eq (aref lbl-key (1+ pos)) ?_)))
+ sep
+ (setq pos (1+ pos))
+ "_")
+ (regexp-quote (char-to-string c))))
+ pos (1+ pos)))
+ (if no-delim
+ regexp
+ (setq regexp (concat regexp sep0 (regexp-quote (or end-delim
ebut:end))))))))
+
+
+(defalias 'hbut:label-to-key 'ebut:label-to-key)
+
+(defalias 'hbut:map 'ebut:map)
+
+(defun hbut:outside-comment-p ()
+ "Returns t if within a programming language buffer and prior regexp match is
outside a comment, else nil."
+ (when (and (derived-mode-p 'prog-mode)
+ (not (eq major-mode 'lisp-interaction-mode)))
+ ;; Match is outside of a programming language comment
+ (not (nth 4 (syntax-ppss)))))
(defun hbut:report (&optional arg)
"Pretty prints the attributes of a button or buttons.
@@ -1003,17 +1049,17 @@ Returns number of buttons reported on or nil if none."
If a file, always returns a full path if optional FULL is non-nil."
(goto-char (match-end 0))
(cond ((looking-at "#<buffer \"?\\([^\n\"]+\\)\"?>")
- (get-buffer (buffer-substring (match-beginning 1)
- (match-end 1))))
+ (get-buffer (match-string 1)))
((looking-at "\".+\"")
- (let* ((file (buffer-substring (1+ (match-beginning 0))
- (1- (match-end 0))))
+ (let* ((file (buffer-substring-no-properties
+ (1+ (match-beginning 0))
+ (1- (match-end 0))))
(absolute (file-name-absolute-p file)))
(if (and full (not absolute))
(expand-file-name file default-directory)
file)))))
-(defalias 'hbut:summarize 'hbut:report)
+(defalias 'hbut:summarize 'hbut:report)
(defvar hbut:current nil
"The currently selected Hyperbole button. Available to action routines.")
@@ -1023,44 +1069,152 @@ If a file, always returns a full path if optional FULL
is non-nil."
This expression should be followed immediately by a file-name indicating the
source file for the buttons in the menu, if any.")
+(defun hbut:label-list ()
+ "Returns list of current buffer's Hyperbole button labels."
+ (mapcar 'hbut:key-to-label (hbut:key-list)))
+
+;;; ------------------------------------------------------------------------
+
+(defun hbut:key-list ()
+ "Returns list of global button label keys."
+ (nconc (hbut:ebut-key-list) (hbut:ibut-key-list)))
+
+(defun hbut:ebut-key-list (&optional key-src)
+ "Returns a list of explicit button label keys from optional KEY-SRC or the
current buffer."
+ (save-excursion
+ (if (hbdata:to-entry-buf (or key-src (buffer-file-name)))
+ (let (hbuts)
+ (save-restriction
+ (narrow-to-region (point) (if (search-forward "\f" nil t)
+ (point) (point-max)))
+ (goto-char (point-min))
+ (condition-case ()
+ (while (setq hbuts (cons (car (read (current-buffer))) hbuts)))
+ (error nil))
+ hbuts)))))
+
+(defun hbut:ibut-key-list (&optional key-src)
+ "Returns a list of implicit button label keys from optional KEY-SRC or the
current buffer."
+ (save-excursion
+ (when (hbut:key-src-set-buffer (or key-src (current-buffer)))
+ (save-restriction
+ (widen)
+ (ibut:label-map #'(lambda (label start end) (ibut:label-to-key
label)))))))
+
;;; ========================================================================
;;; ibut class - Implicit Hyperbole Buttons
;;; ========================================================================
(defun ibut:at-p (&optional key-only)
"Returns symbol for implicit button at point, else nil.
-With optional KEY-ONLY, returns only the label key for button."
- (let ((types (htype:category 'ibtypes))
- ;; Global var used in (hact) function, don't delete.
- (hrule:action 'actype:identity)
- (itype)
- (args)
- (is-type))
- (or key-only (hattr:clear 'hbut:current))
- (while (and (not is-type) types)
- (setq itype (car types))
- (if (setq args (funcall itype))
- (setq is-type itype)
- (setq types (cdr types))))
- (if is-type
- (if key-only
- (hattr:get 'hbut:current 'lbl-key)
- (hattr:set 'hbut:current 'loc (save-excursion
- (hbut:key-src 'full)))
- (hattr:set 'hbut:current 'categ is-type)
- (or (hattr:get 'hbut:current 'args)
- (not (listp args))
- (progn
- (hattr:set 'hbut:current 'actype
- (or
- ;; Hyperbole action type
- (intern-soft (concat "actypes::"
- (symbol-name (car args))))
- ;; Regular Emacs Lisp function symbol
- (car args)
- ))
- (hattr:set 'hbut:current 'args (cdr args))))
- 'hbut:current))))
+Point may be on the implicit button or its optional preceding label.
+With optional KEY-ONLY, returns only the label key for button.
+
+Any labeled implicit button must contain at least two characters,
+excluding delimiters, not just one."
+ (let* ((opoint (point))
+ (label-key-start-end (ibut:label-p nil nil nil t t))
+ (lbl-key (car label-key-start-end)))
+ (unwind-protect
+ (when (not (hbut:outside-comment-p))
+ ;; Skip past any optional label and separators
+ (when label-key-start-end
+ (goto-char (nth 2 label-key-start-end))
+ (when (looking-at ibut:label-separator)
+ ;; Move past up to 2 possible characters of ibut
+ ;; delimiters; this prevents recognizing labeled,
+ ;; delimited ibuts of a single character but no one
+ ;; should need that.
+ (goto-char (min (+ 2 (match-end 0)) (point-max)))))
+
+ ;; Check for an implicit button at current point, record its
+ ;; attributes and return a button symbol for it.
+ (let ((types (htype:category 'ibtypes))
+ ;; Global var used in (hact) function, don't delete.
+ (hrule:action 'actype:identity)
+ (itype)
+ (args)
+ (is-type))
+ (unless key-only
+ (hattr:clear 'hbut:current))
+ (while (and (not is-type) types)
+ (setq itype (car types))
+ (if (setq args (funcall itype))
+ (setq is-type itype)
+ (setq types (cdr types))))
+ (when is-type
+ (when lbl-key
+ (hattr:set 'hbut:current 'lbl-key lbl-key))
+ (if key-only
+ (hattr:get 'hbut:current 'lbl-key)
+ (hattr:set 'hbut:current 'loc (save-excursion
+ (hbut:key-src 'full)))
+ (hattr:set 'hbut:current 'categ is-type)
+ (or (hattr:get 'hbut:current 'args)
+ (not (listp args))
+ (progn
+ (hattr:set 'hbut:current 'actype
+ (or
+ ;; Hyperbole action type
+ (intern-soft (concat "actypes::"
+ (symbol-name (car
args))))
+ ;; Regular Emacs Lisp function symbol
+ (car args)))
+ (hattr:set 'hbut:current 'args (cdr args))))
+ 'hbut:current))))
+ (goto-char opoint))))
+
+(defun ibut:at-type-p (ibut-type-symbol)
+ "Returns non-nil if point is on a button of type `ibut-type-symbol`.
+Point must be on the button itself and not its label, if any.
+
+The return value is a list of the type's action type symbol and
+associated arguments from the button."
+ (when (and ibut-type-symbol (symbolp ibut-type-symbol))
+ (let ((type-name (symbol-name ibut-type-symbol)))
+ (unless (string-match "::" type-name)
+ (setq ibut-type-symbol (intern-soft (concat "ibtypes::" type-name))))
+ (when ibut-type-symbol
+ (let ((types (htype:category 'ibtypes))
+ ;; Global var used in (hact) function, don't delete.
+ (hrule:action 'actype:identity))
+ (funcall ibut-type-symbol))))))
+
+(defun ibut:get (&optional lbl-key buffer key-src)
+ "Returns implicit Hyperbole button symbol given by LBL-KEY and BUFFER.
+KEY-SRC is given when retrieving global buttons and is the full source
pathname.
+
+Retrieves button data, converts into a button object and returns a symbol
+which references the button.
+
+All arguments are optional. When none are given, returns a
+symbol for the button or button label that point is within or
+nil. BUFFER defaults to the current buffer."
+ (hattr:clear 'hbut:current)
+ (save-excursion
+ (let ((key-file) (key-dir) (but-data) (actype))
+ (unless lbl-key
+ (setq lbl-key (ibut:label-p nil nil nil nil t)))
+ (when buffer
+ (if (bufferp buffer)
+ (set-buffer buffer)
+ (error "(ibut:get): Invalid buffer argument: %s" buffer)))
+ (when (not key-src)
+ (when (not (equal lbl-key (ibut:label-p nil nil nil nil t)))
+ (goto-char (point-min))
+ (ibut:next-occurrence lbl-key))
+ (when (setq key-src (hbut:key-src 'full))
+ ;; `hbut:key-src' sets current buffer to key-src buffer.
+ (setq buffer (current-buffer))))
+ (when (and (stringp lbl-key) key-src)
+ (when (stringp key-src)
+ (setq key-dir (file-name-directory key-src)
+ key-file (file-name-nondirectory key-src)))
+ (set-buffer (find-file-noselect key-src))
+ (goto-char (point-min))
+ (ibut:next-occurrence lbl-key)
+ ;; Build and return button symbol with button properties
+ (ibut:at-p)))))
(defun ibut:is-p (object)
"Returns non-nil if object denotes an implicit Hyperbole button."
@@ -1068,16 +1222,49 @@ With optional KEY-ONLY, returns only the label key for
button."
(let ((categ (hattr:get object 'categ)))
(and categ (string-match "^ibtypes::" (symbol-name categ))))))
-(defun ibut:label-p ()
- "Returns key for Hyperbole implicit button label that point is on or nil."
- (ibut:at-p 'key-only))
+(defun ibut:label-map (but-func &optional start-delim end-delim
+ regexp-match include-delims)
+ "Applies BUT-FUNC to buttons delimited by optional START-DELIM and END-DELIM.
+START-DELIM defaults to ibut:label-start; END-DELIM defaults to ibut:label-end.
+If REGEXP-MATCH is non-nil, only buttons which match this argument are
+considered.
+
+Maps over portion of buffer visible under any current restriction.
+BUT-FUNC must take precisely three arguments: the button label, the
+start position of the delimited button label and its end position (positions
+include delimiters when INCLUDE-DELIMS is non-nil).
+If END-DELIM is a symbol, e.g. t, then START-DELIM is taken as a regular
+expression which matches an entire button string."
+ (hbut:map but-func ibut:label-start ibut:label-end))
+
+(defun ibut:label-p (&optional as-label start-delim end-delim pos-flag
two-lines-flag)
+ "Returns key for the Hyperbole implicit button label that point is within,
else nil.
+This is an optional label that may precede an implicit button.
+Use `ibut:at-p' instead to test if point is on either the
+implicit button itself or the label. Assumes point is within the
+first line of any button label.
+
+All following arguments are optional. If AS-LABEL is non-nil,
+label is returned rather than the key derived from the label.
+START-DELIM and END-DELIM are strings that override default
+button delimiters. With POS-FLAG non-nil, returns list of
+label-or-key, but-label-start-position, but-label-end-position.
+Positions include delimiters. With TWO-LINES-FLAG non-nil,
+constrains label search to two lines."
+ (ebut:label-p as-label (or start-delim ibut:label-start)
+ (or end-delim ibut:label-end) pos-flag two-lines-flag))
+
+(defun ibut:label-regexp (lbl-key &optional no-delim)
+ "Unnormalizes ibutton LBL-KEY. Returns regular expr matching delimited
button label.
+Optional NO-DELIM leaves off delimiters and leading and trailing space."
+ (hbut:label-regexp lbl-key no-delim ibut:label-start ibut:label-end))
(defun ibut:label-set (label &optional start end)
- "Sets current implicit button attributes from LABEL and START, END position.
-Returns label. START and END are optional. When given, they specify the
-region in the buffer to flash when this implicit button is activated or
-queried for its attributes. If LABEL is a list, it is assumed to contain all
-arguments."
+ "Sets current implicit button attributes from LABEL and optional START, END
positions.
+Returns label. When START and END are given, they specify the
+region in the buffer to flash when this implicit button is
+activated or queried for its attributes. If LABEL is a list, it
+is assumed to contain all arguments."
(cond ((stringp label)
(hattr:set 'hbut:current 'lbl-key (hbut:label-to-key label))
(and start (hattr:set 'hbut:current 'lbl-start start))
@@ -1089,12 +1276,63 @@ arguments."
(t (error "(ibut:label-set): Invalid label arg: `%s'" label)))
label)
+(defalias 'ibut:key-src 'hbut:key-src)
+(defalias 'ibut:key-to-label 'hbut:key-to-label)
+(defalias 'ibut:label-to-key 'hbut:label-to-key)
+(defun ibut:next-occurrence (lbl-key &optional buffer)
+ "Moves point to next occurrence of a labeled implicit button with LBL-KEY in
optional BUFFER.
+BUFFER defaults to current buffer. It may be a buffer name.
+Returns non-nil iff occurrence is found.
+
+Remember to use (goto-char (point-min)) before calling this in order to
+move to the first occurrence of the button."
+ (if buffer
+ (if (not (or (bufferp buffer)
+ (and (stringp buffer) (get-buffer buffer))))
+ (error "(ibut:next-occurrence): Invalid buffer arg: %s" buffer)
+ (switch-to-buffer buffer)))
+ (when (re-search-forward (ibut:label-regexp lbl-key) nil t)
+ (goto-char (+ (match-beginning 0) (length ibut:label-start)))))
+
+(defalias 'ibut:summarize 'hbut:report)
+
+(defun ibut:to (lbl-key)
+ "Find an implicit button in the current buffer with LBL-KEY (a label or
lable key), leave point inside it or its label and return the button symbol for
it, else nil."
+ ;; Handle a label given rather than a label key
+ (if (string-match-p "\\s-" lbl-key)
+ (setq lbl-key (ibut:label-to-key lbl-key)))
+ (let ((regexp (hbut:label-regexp lbl-key t))
+ pos
+ found
+ reverse)
+ (save-excursion
+ (forward-line 0)
+ ;; re-search forward
+ (while (and (not found) (re-search-forward regexp nil t))
+ (setq pos (goto-char (match-beginning 0))
+ found (equal (ibut:at-p t) lbl-key)))
+ ;; re-search backward
+ (while (and (not found) (re-search-backward regexp nil t))
+ (setq pos (goto-char (match-beginning 0))
+ found (equal (ibut:at-p t) lbl-key))))
+ (when found
+ (goto-char pos)
+ (ibut:at-p))))
+
+;;; ------------------------------------------------------------------------
+(defconst ibut:label-start "<["
+ "String matching the start of a Hyperbole implicit button label.")
+(defconst ibut:label-end "]>"
+ "String matching the end of a Hyperbole implicit button label.")
+(defvar ibut:label-separator "\\s-*[-:=]*\\s-+"
+ "Regular expression that separates an implicit button label from its
implicit button text.")
+
;;; ========================================================================
;;; ibtype class - Implicit button types
;;; ========================================================================
-(defalias 'defib 'ibtype:create)
-(put 'ibtype:create 'lisp-indent-function 'defun)
+(defalias 'defib 'ibtype:create)
+(put 'ibtype:create 'lisp-indent-function 'defun)
(defmacro ibtype:create (type params doc at-p &optional to-p style)
"Creates Hyperbole implicit button TYPE (unquoted sym) with PARAMS,
described by DOC.
PARAMS are presently ignored.
diff --git a/hib-kbd.el b/hib-kbd.el
index 339930a..8888668 100644
--- a/hib-kbd.el
+++ b/hib-kbd.el
@@ -65,12 +65,13 @@ Any key sequence must be a string of one of the following:
;; these are special quote marks, not the
;; standard ASCII characters.
(hbut:label-p t "‘" "’" t)))
+ ;; This excludes delimiters
(key-sequence (car seq-and-pos))
(start (cadr seq-and-pos))
binding)
;; Match only when start delimiter is preceded by whitespace or
;; is the 1st buffer character, so do not match to things like
${variable}.
- (when (= (char-syntax (or (char-before start) ?\t)) ?\ )
+ (when (memq (char-before start) '(nil ?\ ?\t ?\n ?\j ?\f))
(when (and (stringp key-sequence)
(not (eq key-sequence "")))
(setq key-sequence (kbd-key:normalize key-sequence)
@@ -171,17 +172,7 @@ With optional prefix arg FULL, displays full documentation
for command."
(string-to-number (substring norm-key-seq (match-beginning 2)
(match-end 2)))
norm-key-seq (substring norm-key-seq (match-end 0))))
- (let (arg-val)
- (while (string-match "\\`C-u" norm-key-seq)
- (if (or (not (listp arg))
- (not (integerp (setq arg-val (car arg)))))
- (setq arg '(1)
- arg-val 1))
- (setq arg-val (* arg-val 4)
- arg (cons arg-val nil)
- norm-key-seq (substring norm-key-seq (match-end 0)))))
- (if arg (setq norm-key-seq (concat (format "\025%s" arg) norm-key-seq)))
- ;;
+
;; Quote Control and Meta key names
(setq norm-key-seq (hypb:replace-match-string
"C-\\(.\\)" norm-key-seq
@@ -208,7 +199,7 @@ With optional prefix arg FULL, displays full documentation
for command."
(and (stringp key-sequence) (string-match kbd-key:extended-command-prefix
key-sequence)))
(defun kbd-key:hyperbole-hycontrol-key-p (key-sequence)
- "Returns t if normalized KEY-SEQUENCE is given when in a HyControl mode,
else nil.
+ "Returns t if normalized, non-nil KEY-SEQUENCE is given when in a HyControl
mode, else nil.
Allows for multiple key sequences strung together."
(and key-sequence
(featurep 'hycontrol)
diff --git a/hibtypes.el b/hibtypes.el
index 8aaae63..dd09470 100644
--- a/hibtypes.el
+++ b/hibtypes.el
@@ -64,7 +64,7 @@
(run-hooks 'hibtypes-begin-load-hook)
;;; ========================================================================
-;;; Follows Org mode links by invoking a web browser.
+;;; Follows Org mode links and radio targets and cycles Org heading views
;;; ========================================================================
(require 'hsys-org)
@@ -184,10 +184,9 @@ display options."
;;; ========================================================================
(defconst hibtypes-path-line-and-col-regexp
- (if hyperb:microsoft-os-p
- ;; Allow for 'c:' single letter drive prefixes on MSWindows
- "\\([^ \t\n\r:][^ \t\n\r]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?"
- "\\([^ \t\n\r:]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?"))
+ ;; Allow for 'c:' single letter drive prefixes on MSWindows and
+ ;; Elisp vars with colons in them.
+ "\\([^
\t\n\r\f:][^\t\n\r\f:]+\\(:[^0-9\t\n\r\f]*\\)*\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?$")
(defib pathname-line-and-column ()
"Makes a valid pathname:line-num[:column-num] pattern display the path at
line-num and optional column-num.
@@ -200,10 +199,10 @@ See `hpath:find' function documentation for special file
display options."
(let ((path-line-and-col (hpath:delimited-possible-path)))
(if (and (stringp path-line-and-col)
(string-match hibtypes-path-line-and-col-regexp path-line-and-col))
- (let ((file (expand-file-name (match-string-no-properties 1
path-line-and-col)))
- (line-num (string-to-number (match-string-no-properties 2
path-line-and-col)))
- (col-num (if (match-end 3) (string-to-number
(match-string-no-properties
- 4
path-line-and-col)))))
+ (let ((file (save-match-data (expand-file-name (hpath:substitute-value
(match-string-no-properties 1 path-line-and-col)))))
+ (line-num (string-to-number (match-string-no-properties 3
path-line-and-col)))
+ (col-num (if (match-end 4) (string-to-number
(match-string-no-properties
+ 5
path-line-and-col)))))
(when (save-match-data (setq file (hpath:is-p file)))
(ibut:label-set file (match-beginning 1) (match-end 1))
(if col-num
@@ -628,11 +627,112 @@ Requires the Emacs builtin Tramp library for ftp file
retrievals."
(require 'klink)
;;; ========================================================================
-;;; Jumps to source line associated with grep or compilation error messages.
-;;; Also supports ripgrep (rg command).
+;;; Links to Hyperbole button types
+;;; ========================================================================
+
+
+(defconst elink:start "<elink:"
+ "String matching the start of a link to a Hyperbole explicit button.")
+(defconst elink:end ">"
+ "String matching the end of a link to a Hyperbole explicit button.")
+
+(defib link-to-ebut ()
+ "At point, activates a link to an explicit button.
+The explicit button's action is executed in the context of the current buffer.
+
+Recognizes the format '<elink:' <button label> '>', e.g. <elink:
project-list>."
+ (let* ((label-key-start-end (hbut:label-p nil elink:start elink:end t t))
+ (lbl-key (nth 0 label-key-start-end))
+ (start-pos (nth 1 label-key-start-end))
+ (end-pos (nth 2 label-key-start-end)))
+ (when lbl-key
+ (ibut:label-set (ebut:key-to-label lbl-key) start-pos end-pos)
+ (hact 'link-to-ebut lbl-key))))
+
+(defconst glink:start "<glink:"
+ "String matching the start of a link to a Hyperbole global button.")
+(defconst glink:end ">"
+ "String matching the end of a link to a Hyperbole global button.")
+
+(defib link-to-gbut ()
+ "At point, activates a link to a global button.
+The global button's action is executed in the context of the current buffer.
+
+Recognizes the format '<glink:' <button label> '>', e.g. <glink: open todos>."
+ (let* ((label-key-start-end (hbut:label-p nil glink:start glink:end t t))
+ (lbl-key (nth 0 label-key-start-end))
+ (start-pos (nth 1 label-key-start-end))
+ (end-pos (nth 2 label-key-start-end)))
+ (when lbl-key
+ (ibut:label-set (ebut:key-to-label lbl-key) start-pos end-pos)
+ (hact 'link-to-gbut lbl-key))))
+
+(defconst ilink:start "<ilink:"
+ "String matching the start of a link to a Hyperbole implicit button.")
+(defconst ilink:end ">"
+ "String matching the end of a link to a Hyperbole implicit button.")
+
+(defib link-to-ibut ()
+ "At point, activates a link to an implicit button.
+The implicit button's action is executed in the context of the current buffer.
+
+Recognizes the format '<ilink:' <button label> '>', e.g. <ilink: my sequence
of keys>."
+ (let* ((label-key-start-end (ibut:label-p nil ilink:start ilink:end t t))
+ (lbl-key (nth 0 label-key-start-end))
+ (start-pos (nth 1 label-key-start-end))
+ (end-pos (nth 2 label-key-start-end)))
+ (when lbl-key
+ (ibut:label-set (ibut:key-to-label lbl-key) start-pos end-pos)
+ (hact 'link-to-ibut lbl-key))))
+
+;;; ========================================================================
+;;; Jumps to source line associated with ipython, ripgreb, grep or
;;; With credit to Michael Lipp and Mike Williams for the idea.
;;; ========================================================================
+(defib ipython-stack-frame ()
+ "Jumps to line associated with an ipython stack frame line numbered msg.
+ipython outputs each pathname once followed by all matching lines in that
pathname.
+Messages are recognized in any buffer (other than a helm completion
+buffer)."
+ ;; Locate and parse ipython stack trace messages found in any buffer other
than a
+ ;; helm completion buffer.
+ ;;
+ ;; Sample ipython stack trace command output:
+ ;;
+ ;; ~/Dropbox/py/inview/inview_pr.py in ap(name_filter, value_filter,
print_func)
+ ;; 1389 apc(name_filter, value_filter, print_func, defined_only=True)
+ ;; 1390 print('\n**** Modules/Packages ****')
+ ;; -> 1391 apm(name_filter, value_filter, print_func, defined_only=True)
+ ;; 1392
+ ;; 1393 def apa(name_filter=None, value_filter=None, print_func=pd1,
defined_only=False):
+ (unless (eq major-mode 'helm-major-mode)
+ (save-excursion
+ (beginning-of-line)
+ (let ((line-num-regexp "\\( *\\|-+> \\)?\\([1-9][0-9]*\\) ")
+ line-num
+ file)
+ (when (looking-at line-num-regexp)
+ ;; ipython stack trace matches and context lines (-A<num> option)
+ (setq line-num (match-string-no-properties 2)
+ file nil)
+ (while (and (= (forward-line -1) 0)
+ (looking-at line-num-regexp)))
+ (unless (or (looking-at line-num-regexp)
+ (not (re-search-forward " in " nil (point-at-eol)))
+ (and (setq file (buffer-substring-no-properties
(point-at-bol) (match-beginning 0)))
+ (string-empty-p (string-trim file))))
+ (let* ((but-label (concat file ":" line-num))
+ (source-loc (if (file-name-absolute-p file)
+ nil
+ (hbut:key-src t))))
+ (if (stringp source-loc)
+ (setq file (expand-file-name file (file-name-directory
source-loc))))
+ (when (file-readable-p file)
+ (setq line-num (string-to-number line-num))
+ (ibut:label-set but-label)
+ (hact 'link-to-file-line file line-num)))))))))
+
(defib ripgrep-msg ()
"Jumps to line associated with a ripgrep (rg) line numbered msg.
Ripgrep outputs each pathname once followed by all matching lines in that
pathname.
@@ -688,7 +788,7 @@ in grep and shell buffers."
(beginning-of-line)
(if (or
;; Grep matches, UNIX C compiler and Introl 68HC11 C compiler errors
- (looking-at "\\([^ \t\n\r:]+\\): ?\\([1-9][0-9]*\\)[ :]")
+ (looking-at "\\([^ \t\n\r:]+\\)[:\^@] ?\\([1-9][0-9]*\\)[ :]")
;; HP C compiler errors
(looking-at "[a-zA-Z0-9]+: \"\\([^\t\n\r\",]+\\)\", line
\\([0-9]+\\):")
;; BSO/Tasking 68HC08 C compiler errors
@@ -733,13 +833,13 @@ This works with JavaScript and Python tracebacks, gdb,
dbx, and xdb. Such lines
(save-excursion
(beginning-of-line)
(cond
- ;; Python pdb or traceback
- ((looking-at ".+ File \"\\([^\"\n\r]+\\)\", line \\([0-9]+\\)")
- (let* ((file (match-string-no-properties 1))
- (line-num (match-string-no-properties 2))
+ ;; Python pdb or traceback, pytype error
+ ((looking-at "\\(^\\|.+ \\)File \"\\([^\"\n\r]+\\)\", line \\([0-9]+\\)")
+ (let* ((file (match-string-no-properties 2))
+ (line-num (match-string-no-properties 3))
(but-label (concat file ":" line-num)))
(setq line-num (string-to-number line-num))
- (ibut:label-set but-label (match-beginning 1) (match-end 1))
+ (ibut:label-set but-label (match-beginning 2) (match-end 2))
(hact 'link-to-file-line file line-num)))
;; JavaScript traceback
@@ -1010,8 +1110,11 @@ Activates only if point is within the first line of the
Info-node name."
(hbut:label-p t "``" "''" t t)
;; Regular open and close quotes
(hbut:label-p t "`" "'" t t)))
- (node-ref (hpath:is-p (car node-ref-and-pos) nil t)))
- (and node-ref (string-match "\\`([^\):]+)" node-ref)
+ (ref (car node-ref-and-pos))
+ (node-ref (and (stringp ref)
+ (string-match "\\`([^\):]+)" ref)
+ (hpath:is-p (car node-ref-and-pos) nil t))))
+ (and node-ref
(ibut:label-set node-ref-and-pos)
(hact 'link-to-Info-node node-ref))))
diff --git a/hpath.el b/hpath.el
index 51e1d14..00bd297 100644
--- a/hpath.el
+++ b/hpath.el
@@ -502,7 +502,7 @@ use with string-match.")
(defconst hpath:markup-link-anchor-regexp
(concat "\\`\\(#?[^#]+\\)\\(#\\)\\([^\]\[#^{}<>\"`'\\\n\t\f\r]*\\)")
- "Regexp that matches an markup filename followed by a hash (#) and an
optional in-file anchor name.")
+ "Regexp that matches a markup filename followed by a hash (#) and an
optional in-file anchor name.")
(defconst hpath:outline-section-pattern "^\*+[ \t]+%s\\([ \t[:punct:]]*\\)$"
"Regexp matching an Emacs outline section header and containing a %s for
replacement of a specific section name.")
@@ -518,6 +518,9 @@ These are used to indicate how to display or execute the
pathname.
"\\`/[^/:]+:\\|\\`ftp[:.]\\|\\`www\\.\\|\\`https?:"
"Regexp matching remote pathnames and urls which invoke remote file
handlers.")
+(defconst hpath:texinfo-section-pattern "^@node+[ \t]+%s[ \t]*\\(,\\|$\\)"
+ "Regexp matching a Texinfo section header and containing a %s for
replacement of a specific section name.")
+
;;; ************************************************************************
;;; Public functions
;;; ************************************************************************
@@ -799,7 +802,8 @@ Returns non-nil iff file is displayed within a buffer (not
with an external
program)."
(interactive "FFind file: ")
(let ((case-fold-search t)
- modifier loc dir anchor hash path)
+ (default-directory default-directory)
+ modifier loc anchor hash path)
(if (string-match hpath:prefix-regexp filename)
(setq modifier (aref filename 0)
filename (substring filename (match-end 0))))
@@ -810,19 +814,17 @@ program)."
(substring filename 0 (match-end 1)))
filename))
loc (hattr:get 'hbut:current 'loc)
- dir (file-name-directory
- ;; Loc may be a buffer without a file
- (if (stringp loc) loc default-directory))
- filename (hpath:absolute-to path dir))
+ default-directory (file-name-directory
+ ;; Loc may be a buffer without a file
+ (if (stringp loc) loc default-directory))
+ filename (hpath:absolute-to path default-directory))
(let ((remote-filename (hpath:remote-p path)))
(or modifier remote-filename
- (file-exists-p path)
- (error "(hpath:find): \"%s\" does not exist"
- (file-relative-name filename)))
+ (file-exists-p filename)
+ (error "(hpath:find): \"%s\" does not exist" filename))
(or modifier remote-filename
- (file-readable-p path)
- (error "(hpath:find): \"%s\" is not readable"
- (file-relative-name filename)))
+ (file-readable-p filename)
+ (error "(hpath:find): \"%s\" is not readable" filename))
;; If filename is a remote file (not a directory, we have to copy it to
;; a temporary local file and then display that.
(when (and remote-filename (not (file-directory-p remote-filename)))
@@ -894,9 +896,11 @@ program)."
(anchor-name (subst-char-in-string ?- ?\ anchor)))
(goto-char (point-min))
(if (re-search-forward (format
- (if (string-match
hpath:markdown-suffix-regexp buffer-file-name)
- hpath:markdown-section-pattern
- hpath:outline-section-pattern)
+ (cond ((string-match
hpath:markdown-suffix-regexp buffer-file-name)
+ hpath:markdown-section-pattern)
+ ((eq major-mode 'texinfo-mode)
+ hpath:texinfo-section-pattern)
+ (t
hpath:outline-section-pattern))
(regexp-quote anchor-name)) nil t)
(progn (forward-line 0)
(recenter 0))
@@ -1042,7 +1046,7 @@ nonexistent local paths are allowed."
(not (string-match "[\t\n\r\"`'|{}\\]" path))
(or (not (hpath:www-p path))
(string-match "\\`ftp[:.]" path))
- (let ((remote-path (string-match "@.+:\\|^/.+:\\|..+:/" path)))
+ (let ((remote-path (string-match
"\\(@.+:\\|^/.+:\\|..+:/\\).*[^:0-9/]" path)))
(if (cond (remote-path
(cond ((eq type 'file)
(not (string-equal "/" (substring path -1))))
@@ -1510,15 +1514,15 @@ from path or t."
Return nil if FILENAME is a directory name or an image file that emacs can
display.
See also documentation for the function (hpath:get-external-display-alist) and
the variable
`hpath:internal-display-alist'."
- (cond ((let ((case-fold-search t))
- (hpath:match filename (hpath:get-external-display-alist))))
+ (cond ((and (fboundp 'image-mode)
+ (string-match hpath:native-image-suffixes filename))
+ nil)
((let ((case-fold-search nil))
(hpath:match filename hpath:internal-display-alist)))
+ ((let ((case-fold-search t))
+ (hpath:match filename (hpath:get-external-display-alist))))
((and (stringp filename) (file-directory-p filename))
nil)
- ((and (fboundp 'image-mode)
- (string-match hpath:native-image-suffixes filename))
- nil)
;; 01/21/2019 - RSW commented this next line out since it can
;; trigger external viewers on many file types that Emacs
;; displays natively.
diff --git a/hsys-org.el b/hsys-org.el
index 59a1eb1..2e9c117 100644
--- a/hsys-org.el
+++ b/hsys-org.el
@@ -29,6 +29,16 @@
(require 'hbut)
(require 'org)
+(defvar hsys-org-mode-function #'hsys-org-mode-p
+ "*Boolean function of no arguments that determines whether hsys-org actions
are triggered or not.")
+
+(defun hsys-org-mode-p ()
+ "Returns non-nil if an Org-related major or minor mode is active in the
current buffer."
+ (or (derived-mode-p 'org-mode)
+ (and (boundp 'outshine-mode) outshine-mode)
+ (and (boundp 'poporg-mode) poporg-mode)))
+
+
(defun hsys-org-cycle ()
"Calls org-cycle and forces it to be set as this-command to cycle through
all states."
(setq last-command 'org-cycle
@@ -47,12 +57,22 @@
(defib org-mode ()
"Follows any Org mode link at point or cycles through views of the outline
subtree at point."
- (when (derived-mode-p 'org-mode)
- (cond ((org-link-at-p)
- (hact 'org-link nil))
- ((org-at-heading-p)
- (hact 'hsys-org-cycle))
- (t (hact 'org-meta-return)))))
+ (when (funcall hsys-org-mode-function)
+ (let (start-end)
+ (cond ((setq start-end (org-internal-link-target-at-p))
+ (org-set-ibut-label start-end)
+ (hact 'org-internal-link-target))
+ ((org-radio-target-def-at-p)
+ (hact 'org-radio-target))
+ ((setq start-end (org-link-at-p))
+ (org-set-ibut-label start-end)
+ (hact 'org-link))
+ ((org-at-heading-p)
+ (hact 'hsys-org-cycle))
+ ((org-at-block-start-p)
+ (org-ctrl-c-ctrl-c))
+ (t
+ (hact 'org-meta-return))))))
(defun org-mode:help (&optional _but)
"If on an Org mode heading, cycles through views of the whole buffer outline.
@@ -65,22 +85,187 @@ If on an Org mode link, displays standard Hyperbole help."
(hact 'hsys-org-global-cycle)
t))))
-(defact org-link (link)
- "Follows an Org mode LINK. If LINK is nil, follows the link at point."
+(defact org-link (&optional link)
+ "Follows an optional Org mode LINK to its target.
+If LINK is nil, follows any link at point. Otherwise, triggers an error."
(if (stringp link)
(org-open-link-from-string link) ;; autoloaded
- (org-open-at-point-global))) ;; autoloaded
+ (org-open-at-point))) ;; autoloaded
+
+(defact org-internal-link-target (&optional link-target)
+ "Follows an optional Org mode LINK-TARGET back to its link definition.
+If LINK-TARGET is nil, follows any link target at point. Otherwise, triggers
an error."
+ (let (start-end)
+ (cond ((stringp link-target)
+ (setq start-end t)
+ (org-search-internal-link-p link-target))
+ ((null link-target)
+ (when (setq start-end (org-internal-link-target-at-p))
+ (org-search-internal-link-p (buffer-substring-no-properties
+ (car start-end) (cdr start-end))))))
+ (unless start-end
+ (error "(org-internal-link-target): Point must be on a link target (not
the link itself)"))))
+
+
+(defact org-radio-target (&optional target)
+ "Jumps to the next occurrence of an optional Org mode radio TARGET link.
+If TARGET is nil and point is on a radio target definition or link, it
+uses that one. Otherwise, triggers an error."
+ (let (start-end)
+ (cond ((stringp target)
+ (setq start-end t)
+ (org-to-next-radio-target-link target))
+ ((null target)
+ (when (setq start-end (org-radio-target-at-p))
+ (org-to-next-radio-target-link (buffer-substring-no-properties
+ (car start-end) (cdr
start-end))))))
+ (unless start-end
+ (error "(org-radio-target): Point must be on a radio target definition
or link"))))
;;; ************************************************************************
;;; Public functions
;;; ************************************************************************
-;; Assumes caller has already checked that the current buffer is in org-mode.
+(defun org-region-with-text-property-value (pos property)
+ "Returns (start . end) buffer positions of the region around POS that shares
its non-nil text PROPERTY value, else nil."
+ (if (null pos) (setq pos (point)))
+ (let ((property-value (get-text-property pos property))
+ (start-point pos))
+ (when property-value
+ ;; Can't use previous-single-property-change here because it
+ ;; ignores characters that lack the property, i.e. have nil values.
+ (if (bobp)
+ (setq start-point (point-min))
+ (while (equal (get-text-property (1- start-point) property)
property-value)
+ (setq start-point (1- start-point))))
+ (cons start-point (next-single-property-change start-point property)))))
+
+(defun org-at-block-start-p ()
+ "Returns non-nil if point is on the first line of an Org block definition,
else nil."
+ (save-excursion
+ (forward-line 0)
+ (or (looking-at org-block-regexp)
+ (looking-at org-dblock-start-re))))
+
(defun org-link-at-p ()
- "Returns non-nil iff point is on an Org mode link."
+ "Returns non-nil iff point is on an Org mode link.
+Assumes caller has already checked that the current buffer is in org-mode."
+ (or (org-in-regexp org-any-link-re)
+ (org-face-at-p 'org-link)))
+
+;; Assumes caller has already checked that the current buffer is in org-mode.
+(defun org-target-at-p ()
+ "Returns non-nil iff point is on an Org mode radio target (definition) or
link target (referent).
+Assumes caller has already checked that the current buffer is in org-mode."
+ (org-face-at-p 'org-target))
+
+(defun org-radio-target-link-at-p ()
+ "Returns (target-start . target-end) positions iff point is on an Org mode
radio target link (referent), else nil."
+ (and (get-text-property (point) 'org-linked-text)
+ (org-link-at-p)
+ (org-region-with-text-property-value (point) 'org-linked-text)))
+
+(defun org-radio-target-def-at-p ()
+ "Returns (target-start . target-end) positions iff point is on an Org mode
radio target (definition), including any delimiter characters, else nil."
+ (when (org-target-at-p)
+ (save-excursion
+ (if (not (looking-at "<<<"))
+ (goto-char (or (previous-single-property-change (point) 'face)
(point-min))))
+ (if (looking-at "<<<")
+ (goto-char (match-end 0)))
+ (and (get-text-property (point) 'org-linked-text)
+ (org-region-with-text-property-value (point) 'face)))))
+
+(defun org-radio-target-at-p ()
+ "Returns (target-start . target-end) positions iff point is on an Org mode
<<<radio target definition>>> or radio target link (referent), including any
delimiter characters, else nil."
+ (or (org-radio-target-def-at-p)
+ (org-radio-target-link-at-p)))
+
+(defun org-internal-link-target-at-p ()
+ "Returns (target-start . target-end) positions iff point is on an Org mode
<<link target>>, including any delimiter characters, else nil."
+ (when (org-target-at-p)
+ (save-excursion
+ (if (not (looking-at "<<"))
+ (goto-char (or (previous-single-property-change (point) 'face)
(point-min))))
+ (if (looking-at "<<<?")
+ (goto-char (match-end 0)))
+ (and (not (get-text-property (point) 'org-linked-text))
+ (org-region-with-text-property-value (point) 'face)))))
+
+(defun org-face-at-p (org-face-type)
+ "Returns `org-face-type` iff point is on a character with face
`org-face-type', a symbol, else nil."
(let ((face-prop (get-text-property (point) 'face)))
- (or (eq face-prop 'org-link)
- (and (listp face-prop) (memq 'org-link face-prop)))))
+ (when (or (eq face-prop org-face-type)
+ (and (listp face-prop) (memq org-face-type face-prop)))
+ org-face-type)))
+
+(defun org-search-internal-link-p (target)
+ "Searches from buffer start for an Org internal link definition matching
TARGET.
+White spaces are insignificant. Returns t if a link is found, else nil."
+ (if (string-match "<<.+>>" target)
+ (setq target (substring target 2 -2)))
+ (let ((re (format "%s"
+ (mapconcat #'regexp-quote
+ (split-string target)
+ "[ \t]+\\(?:\n[ \t]*\\)?")))
+ (origin (point)))
+ (goto-char (point-min))
+ (catch :link-match
+ (while (re-search-forward re nil t)
+ (backward-char)
+ (let ((object (org-element-context)))
+ (when (eq (org-element-type object) 'link)
+ (org-show-context 'link-search)
+ (throw :link-match t))))
+ (goto-char origin)
+ nil)))
+
+(defun org-search-radio-target-link-p (target)
+ "Searches from point for a radio target link matching TARGET.
+White spaces are insignificant. Returns t if a target link is found, else
nil."
+ (if (string-match "<<<.+>>>" target)
+ (setq target (substring target 3 -3)))
+ (let ((re (format "%s"
+ (mapconcat #'regexp-quote
+ (split-string target)
+ "[ \t]+\\(?:\n[ \t]*\\)?")))
+ (origin (point)))
+ (catch :radio-match
+ (while (re-search-forward re nil t)
+ (backward-char)
+ (let ((object (org-element-context)))
+ (when (eq (org-element-type object) 'link)
+ (org-show-context 'link-search)
+ (throw :radio-match t))))
+ (goto-char origin)
+ nil)))
+
+(defun org-set-ibut-label (start-end)
+ "Record the label and START-END positions of any implicit button at point."
+ (when (consp start-end)
+ (ibut:label-set (ibut:key-to-label
+ (ibut:label-to-key
+ (buffer-substring-no-properties (car start-end) (cdr
start-end))))
+ (car start-end) (cdr start-end))))
+
+
+(defun org-to-next-radio-target-link (target)
+ "Moves to the start of the next radio TARGET link if found. TARGET must be
a string."
+ (if (string-match "<<<.+>>>" target)
+ (setq target (substring target 3 -3)))
+ (let ((opoint (point))
+ (start-end (org-radio-target-at-p))
+ found)
+ (if start-end
+ ;; Move past any current target link
+ (goto-char (cdr start-end)))
+ (while (and (org-search-radio-target-link-p target)
+ (setq found t)
+ (not (org-radio-target-link-at-p))))
+ (when found
+ (if (org-radio-target-link-at-p)
+ (goto-char (or (previous-single-property-change (point) 'face)
(point-min)))
+ (goto-char opoint)))))
;;; ************************************************************************
;;; Private functions
diff --git a/htz.el b/htz.el
index 3341d6b..6ff6713 100644
--- a/htz.el
+++ b/htz.el
@@ -61,8 +61,8 @@ Optional 2nd argument TIMEZONE specifies a timezone to be
represented in."
(defun htz:date-parse (date &optional parsed-current-date)
"Parse DATE string and return a vector [year month day time timezone].
-19 is prepended to year if necessary. Timezone in DATE is optional, it
-defaults to the value of `htz:local'.
+If a two-digit year, the first two digits of the current year are prepended.
+Timezone in DATE is optional, it defaults to the value of `htz:local'.
Recognizes the following styles:
(1) \"(1 30 1999)\" or \"(1 30 1999)\" `calendar-julian-date' requires
`parsed-current-date' arg
@@ -73,11 +73,8 @@ Recognizes the following styles:
(6) \"Mar 29 14:00\" `ls -l date' requires `parsed-current-date' arg
(7) \"Mar 7 1994\" `ls -l date' requires `parsed-current-date' arg"
(let ((date (or date ""))
- (year nil)
- (month nil)
- (day nil)
- (time nil)
- (zone nil)) ; This may be nil.
+ year month day time
+ zone) ; This may be nil.
(if (listp date)
(setq month (nth 0 date)
day (nth 1 date)
@@ -87,31 +84,34 @@ Recognizes the following styles:
;; Style (1)
(setq year 3 month 1 day 2 time nil zone nil))
((string-match
-
"\\([0-9][0-9][0-9][0-9]\\)\\([0-1][0-9]\\)\\([0-3][0-9]\\):?\\([0-2][0-9]:[0-5][0-9:]+\\)[
]*\\'" date)
- ;; Style (4)
+ ;; Allow for 3 digits in hour to handle prior error in
+ ;; generating hours fixed on 2019-06-10; 3rd digit
+ ;; removed in htz:time-make-string and htz:time-parse.
+
"\\([0-9][0-9][0-9][0-9]\\)\\([0-1][0-9]\\)\\([0-3][0-9]\\):?\\([0-9][0-9][0-9]?:[0-5][0-9:]+\\)[
]*\\'" date)
+ ;; Style (5)
(setq year 1 month 2 day 3 time 4 zone nil))
((string-match
"\\([0-9]+\\) \\([^ ,]+\\) \\([0-9]+\\) \\([0-9]+:[0-9:]+\\)[
]*\\'" date)
- ;; Styles: (1) and (2) without timezone
+ ;; Styles: (2) and (3) without timezone
(setq year 3 month 2 day 1 time 4 zone nil))
((string-match
"\\([0-9]+\\) \\([^ ,]+\\) \\([0-9]+\\) \\([0-9]+:[0-9:]+\\)[
]*\\([-+a-zA-Z0-9]+\\)" date)
- ;; Styles: (1) and (2) with timezone and buggy timezone
+ ;; Styles: (2) and (3) with timezone and buggy timezone
(setq year 3 month 2 day 1 time 4 zone 5))
((string-match
- "\\([^ ,]+\\) +\\([0-9]+\\) \\([0-9]+:[0-9:]+\\) \\([0-9]+\\)"
date)
- ;; Styles: (3) without timezone
- (setq year 4 month 1 day 2 time 3 zone nil))
+ "\\([^ ,]+\\) +\\([0-9]+\\) \\([0-9]+:[0-9:]+\\(:[0-9]+\\)?\\)
\\([0-9]+\\)" date)
+ ;; Styles: (4) without timezone
+ (setq year 5 month 1 day 2 time 3 zone nil))
((string-match
- "\\([^ ,]+\\) +\\([0-9]+\\) \\([0-9]+:[0-9:]+\\)
\\([-+a-zA-Z0-9]+\\) \\([0-9]+\\)" date)
- ;; Styles: (3) with timezone
- (setq year 5 month 1 day 2 time 3 zone 4))
+ "\\([^ ,]+\\) +\\([0-9]+\\) \\([0-9]+:[0-9:]+\\(:[0-9]+\\)?\\)
\\([-+a-zA-Z0-9]+\\) \\([0-9]+\\)" date)
+ ;; Styles: (4) with timezone
+ (setq year 6 month 1 day 2 time 3 zone 5))
((string-match "^\\([^ ,]+\\) +\\([0-9]+\\) +\\([0-9]+:[0-9:]+\\)$"
date)
- ;; Style: (5)
+ ;; Style: (6)
(setq year nil month 1 day 2 time 3 zone nil))
((string-match
"^\\([^ ,]+\\) +\\([0-9]+\\) +\\([0-9][0-9][0-9][0-9]\\)$" date)
- ;; Style: (6)
+ ;; Style: (7)
(setq year 3 month 1 day 2 time nil zone nil))
(t (error "(htz:date-parse): Invalid date format: `%s'" date)))
(if year
@@ -249,7 +249,10 @@ See `htz:date-parse' for a list of acceptable date
formats."
;; Return [hour minute second]
(vector
(if hour
- (substring time (match-beginning hour) (match-end hour)) "0")
+ ;; Remove possible 3rd digit in hour to handle prior error in
+ ;; generating hours fixed on 2019-06-10; 3rd digit
+ ;; removed in htz:time-make-string and here.
+ (format "%02.2s" (substring time (match-beginning hour) (match-end
hour))) "0")
(if minute
(substring time (match-beginning minute) (match-end minute)) "0")
(if second
@@ -322,7 +325,7 @@ Optional argument TIMEZONE specifies a time zone."
;; Partly copied from Calendar program by Edward M. Reingold.
(defun htz:time-make-string (hour minute second)
"Make time string from HOUR, MINUTE, and SECOND."
- (format "%02d:%02d:%02d" hour minute second))
+ (format "%02.2d:%02.2d:%02.2d" hour minute second))
(defun htz:zone-to-hour (timezone)
"Translate TIMEZONE (in zone name or integer) to integer hour."
diff --git a/hui-mouse.el b/hui-mouse.el
index 0878500..d3396b2 100644
--- a/hui-mouse.el
+++ b/hui-mouse.el
@@ -243,9 +243,9 @@ Its default value is #'smart-scroll-down."
;;
;; Python files - ensure this comes before Imenu for more advanced
;; definition lookups
- ((and (or (and (eq major-mode 'python-mode) buffer-file-name)
+ ((and (or (and (derived-mode-p 'python-mode) buffer-file-name)
(let ((case-fold-search))
- (string-match "\\`\\(Pydoc:\\|\\*?Python\\)" (buffer-name))))
+ (string-match "\\`\\([ *]?Pydoc[: ]\\|\\*?Python\\)"
(buffer-name))))
(setq hkey-value (smart-python-at-tag-p))) .
((smart-python hkey-value) . (smart-python hkey-value 'next-tag)))
;;
diff --git a/hui.el b/hui.el
index f0d1d48..325f287 100644
--- a/hui.el
+++ b/hui.el
@@ -66,7 +66,7 @@
(message "{%s} now runs `%s'" new-key-text cmd))))
(defun hui:ebut-create (&optional start end)
- "Creates an explicit but starting from label between optional START and END.
+ "Creates an explicit Hyperbole button starting from label between optional
START and END.
Indicates by delimiting and adding any necessary instance number of the button
label."
(interactive (list (and (marker-position (hypb:mark-marker t))
@@ -722,8 +722,8 @@ All args are optional, the current button and buffer file
are the defaults."
(defun hui:hbut-term-highlight (start end)
"For terminals only: Emphasize a button spanning from START to END."
- (save-restriction
- (save-excursion
+ (save-excursion
+ (save-restriction
(goto-char start)
(narrow-to-region (point-min) start)
(sit-for 0)
@@ -737,8 +737,8 @@ All args are optional, the current button and buffer file
are the defaults."
(defun hui:hbut-term-unhighlight (start end)
"For terminals only: Remove any emphasis from hyper-button at START to END."
- (save-restriction
- (save-excursion
+ (save-excursion
+ (save-restriction
(goto-char start)
(narrow-to-region (point-min) start)
(sit-for 0)
@@ -834,7 +834,7 @@ button's source file name when the button data is stored
externally."
(t but-buf))))
(defun hui:link-create (modify but-window lbl-key but-loc but-dir
type-and-args)
- "Creates or modifies a new Hyperbole link button.
+ "Creates or modifies a new Hyperbole explicit link button.
If MODIFY is non-nil, modifies button at point in BUT-WINDOW,
otherwise, prompts for button label and creates a button.
LBL-KEY is internal form of button label. BUT-LOC is file or buffer
@@ -862,7 +862,9 @@ possible types.
Referent Context Possible Link Type Returned
----------------------------------------------------
+Global Button link-to-gbut
Explicit Button link-to-ebut
+Implicit Button link-to-ibut
Info Index Item link-to-Info-index-item
Info Node link-to-Info-node
Mail Reader Message link-to-mail
@@ -877,8 +879,12 @@ Buffer without File link-to-buffer-tmp"
(let (val)
(delq nil
- (list (if (ebut:at-p)
- (list 'link-to-ebut buffer-file-name (ebut:label-p)))
+ (list (cond ((eq (current-buffer) (get-file-buffer gbut:file))
+ (list 'link-to-gbut buffer-file-name (hbut:label-p)))
+ ((ebut:at-p)
+ (list 'link-to-ebut buffer-file-name (ebut:label-p)))
+ ((setq val (ibut:at-p t))
+ (list 'link-to-ibut buffer-file-name val)))
(cond ((eq major-mode 'Info-mode)
(if (and Info-current-node
(member Info-current-node
diff --git a/hypb.el b/hypb.el
index f156592..f896305 100644
--- a/hypb.el
+++ b/hypb.el
@@ -220,7 +220,10 @@ Global keymap is used unless optional KEYMAP is given."
(defun hypb:error (&rest args)
"Signals an error typically to be caught by `hyperbole'."
- (let ((msg (if (< (length args) 2) (car args) (apply 'format args))))
+ (let ((msg (if (< (length args) 2)
+ (car args)
+ (apply 'format (cons (car args)
+ (mapcar #'hypb:format-quote (cdr args)))))))
(put 'error 'error-message msg)
(error msg)))
@@ -233,14 +236,16 @@ FILE is temporarily read into a buffer to determine the
major mode if necessary.
(unless (or existing-flag (null buf))
(kill-buffer buf)))))
-(defun hypb:format-quote (string)
- "Replace all single % with %% in STRING so a call to `format' or `message'
ignores them."
- (if (stringp string)
+(defun hypb:format-quote (arg)
+ "Replace all single % with %% in any string ARG so that a call to `format'
or `message' ignores them.
+Return either the modified string or the original ARG."
+ (if (stringp arg)
(replace-regexp-in-string
"@@@" "%%" (replace-regexp-in-string
- "%" "%%" (replace-regexp-in-string "%%" "@@@" string nil t)
+ "%" "%%" (replace-regexp-in-string "%%" "@@@" arg nil t)
nil t)
- nil t)))
+ nil t)
+ arg))
(defun hypb:function-copy (func-symbol)
"Copies FUNC-SYMBOL's body for overloading. Returns copy of body."
diff --git a/hyperbole.el b/hyperbole.el
index b8d2340..3a6cda2 100644
--- a/hyperbole.el
+++ b/hyperbole.el
@@ -300,7 +300,7 @@ With third argument NO-ADD non-nil, skip storage of prior
KEY binding
which prevents automatic removal of any local bindings to the same key."
(or (global-key-binding key)
(where-is-internal command)
- (hkey-global-set-key key command)))
+ (hkey-global-set-key key command no-add)))
(defun hkey-set-bindings (key-binding-list)
"Set keys bound by Hyperbole to those in KEY-BINDING-LIST.
diff --git a/hyrolo.el b/hyrolo.el
index 741fdd8..b6058ff 100644
--- a/hyrolo.el
+++ b/hyrolo.el
@@ -183,10 +183,8 @@ entry which begins with the parent string."
parent (substring name 0 end)
name (substring name (min (1+ end) (length name))))
(if (re-search-forward
- (concat "\\(" hyrolo-entry-regexp "\\)[ \t]*"
- (regexp-quote parent)) nil t)
- (setq level (buffer-substring-no-properties (match-beginning 1)
- (match-end 1)))
+ (concat hyrolo-entry-regexp (regexp-quote parent)) nil t)
+ (setq level (match-string-no-properties hyrolo-entry-group-number))
(error "(hyrolo-add): `%s' category not found in \"%s\"."
parent file)))
(narrow-to-region (point)
@@ -204,10 +202,10 @@ entry which begins with the parent string."
;; entry by moving to an entry with the same (or nearest) first character
;; to that of `name'.
(if (and (= level-len 1)
- (equal hyrolo-entry-regexp "^\\*+"))
+ (equal hyrolo-entry-regexp "^\\(\\*+\\)\\([ \t]+\\)"))
(progn (goto-char (point-min))
- (if (re-search-forward (concat "^\\*[ \t]*"
- (char-to-string first-char))
+ (if (re-search-forward (concat hyrolo-entry-regexp
+ (regexp-quote (char-to-string
first-char)))
nil t)
(goto-char (match-beginning 0))
(goto-char (point-max))
@@ -229,17 +227,12 @@ entry which begins with the parent string."
(setq again nil)))))
(goto-char (point-min)))
- (while (and again
- (re-search-forward
- (concat "\\(" hyrolo-entry-regexp "\\)\\([ \t]*\\)")
- nil 'end))
- (setq entry-level (buffer-substring-no-properties (match-beginning 1)
- (match-end 1)))
+ (while (and again (re-search-forward hyrolo-entry-regexp nil 'end))
+ (setq entry-level (match-string-no-properties
hyrolo-entry-group-number))
(if (/= (length entry-level) level-len)
(hyrolo-to-entry-end t entry-level)
(setq entry (buffer-substring-no-properties (point) (+ (point) len))
- entry-spc (buffer-substring-no-properties (match-beginning 2)
- (match-end 2)))
+ entry-spc (match-string-no-properties
hyrolo-entry-trailing-space-group-number))
(cond ((string< entry name)
(hyrolo-to-entry-end t entry-level))
((string< name entry)
@@ -528,7 +521,7 @@ Returns t if entry is killed, nil otherwise."
(defun hyrolo-locate ()
"Interactively search for an entry beginning with a set of search
characters."
(interactive)
- (hyrolo-isearch-for-regexp (concat hyrolo-entry-regexp "[ \t]*")))
+ (hyrolo-isearch-for-regexp hyrolo-entry-regexp))
(defun hyrolo-mail-to ()
"Start composing mail addressed to the first e-mail address at or after
point."
@@ -1270,8 +1263,7 @@ Name is returned as `last, first-and-middle'."
"\\([^\" \t()]+\\)[ \t]*[)\"]\\)?[ \t]*$")
from)
(setq name (hyrolo-format-name from 3 4))
- (or email (setq email (substring from (match-beginning 1)
- (match-end 1)))))
+ (or email (setq email (match-string 1 from))))
;; Match: <email>, name <email>, "name" <email>
((string-match
(concat "^\\(\"?\\([^\"<>()\n]+\\)[ \t]+"
@@ -1279,8 +1271,7 @@ Name is returned as `last, first-and-middle'."
"<\\([^\"<>() \t\n\r\f]+\\)>[ \t]*$")
from)
(setq name (hyrolo-format-name from 2 3))
- (or email (setq email (substring from (match-beginning 4)
- (match-end 4)))))))
+ (or email (setq email (match-string 4 from))))))
(if (or name email)
(list name email))))
@@ -1295,8 +1286,7 @@ Name is returned as `last, first-and-middle'."
(skip-chars-forward " \t")
(if (or (looking-at "[^ \t\n\r]+ ?, ?[^ \t\n\r]+")
(looking-at "\\( ?[^ \t\n\r]+\\)+"))
- (buffer-substring-no-properties (match-beginning 0)
- (match-end 0))))))))
+ (match-string-no-properties 0)))))))
(defun hyrolo-narrowed-p ()
(or (/= (point-min) 1) (/= (1+ (buffer-size)) (point-max))))
@@ -1387,11 +1377,8 @@ Returns point where matching entry begins or nil if not
found."
(while (and (not level) (search-forward parent nil t))
(save-excursion
(beginning-of-line)
- (if (looking-at
- (concat "\\(" hyrolo-entry-regexp "\\)[ \t]*"
- (regexp-quote parent)))
- (setq level (buffer-substring-no-properties
(match-beginning 1)
-
(match-end 1))))))
+ (if (looking-at (concat hyrolo-entry-regexp
(regexp-quote parent)))
+ (setq level (match-string-no-properties
hyrolo-entry-group-number)))))
level))
((equal name real-name)) ;; Try next file.
(t ;; Found parent but not child
@@ -1409,9 +1396,7 @@ Returns point where matching entry begins or nil if not
found."
(beginning-of-line)
(setq found
(if (looking-at
- (concat "\\(" hyrolo-entry-regexp
- "\\)[ \t]*"
- (regexp-quote name)))
+ (concat hyrolo-entry-regexp (regexp-quote
name)))
(point))))))))
(or found (hyrolo-kill-buffer))) ;; conditionally kill
(widen)
@@ -1462,10 +1447,18 @@ Calls the functions given by `hyrolo-mode-hook'.
"Buffer used to display set of last matching rolo entries.")
(define-obsolete-variable-alias 'rolo-display-buffer 'hyrolo-display-buffer
"06.00")
-(defvar hyrolo-entry-regexp "^\\*+"
+(defvar hyrolo-entry-group-number 1
+ "Group number within `hyrolo-entry-regexp' whose length represents the level
of any entry matched.")
+
+(defvar hyrolo-entry-trailing-space-group-number 2
+ "Group number within `hyrolo-entry-regexp; containing trailing space.")
+
+(defvar hyrolo-entry-regexp "^\\(\\*+\\)\\([ \t]+\\)"
"Regular expression to match the beginning of a rolo entry.
-This pattern must match the beginning of the line. Entries may be nested
-through the use of increasingly longer beginning patterns.")
+This pattern must match the beginning of the line. Use
+`hyrolo-entry-group-number' to compute the entry's level in the
+hierarchy. Use `hyrolo-entry-trailing-space-group-number' to capture
+the whitespace following the entry hierarchy level.")
(define-obsolete-variable-alias 'rolo-entry-regexp 'hyrolo-entry-regexp
"06.00")
(defconst hyrolo-hdr-format
diff --git a/kotl/kfill.el b/kotl/kfill.el
index d1be8ea..a3e0c28 100644
--- a/kotl/kfill.el
+++ b/kotl/kfill.el
@@ -18,12 +18,6 @@
;;; Public variables
;;; ************************************************************************
-(defvar kfill:function-table
- (if (boundp 'filladapt-function-table)
- filladapt-function-table
- (list (cons 'fill-paragraph (symbol-function 'fill-paragraph))))
- "Table containing the old function definitions that kfill overrides.")
-
(defvar kfill:prefix-table
'(
;; Lists with hanging indents, e.g.
@@ -106,44 +100,44 @@ number of lines that could not be moved, otherwise 0."
;; Need this or Emacs ignores fill-prefix when inside a
;; comment.
(comment-multi-line t)
+ (fill-paragraph-handle-comment t)
fill-prefix)
(kfill:adapt nil)
(do-auto-fill))
(do-auto-fill))))
-;;; Redefine this built-in function.
-
-(defun fill-paragraph (arg &optional skip-prefix-remove)
- "Fill paragraph at or after point. Prefix ARG means justify as well."
- (interactive "*P")
- (if (not (eq major-mode 'kotl-mode))
- (kfill:funcall 'fill-paragraph arg)
- ;; This may be called from `fill-region-as-paragraph' in "filladapt.el"
- ;; which narrows the region to the current paragraph. A side-effect is
- ;; that the cell identifier and indent information needed by this function
- ;; when in kotl-mode is no longer visible. So we temporarily rewiden the
- ;; buffer here. Don't rewiden past the paragraph of interest or any
- ;; following blank line may be removed by the filling routines.
- (save-restriction
- (if (eq major-mode 'kotl-mode)
- (narrow-to-region 1 (point-max)))
- ;; Emacs expects a specific symbol here.
- (if (and arg (not (symbolp arg))) (setq arg 'full))
- (or skip-prefix-remove (kfill:remove-paragraph-prefix))
- (catch 'done
- (if (null fill-prefix)
- (let ((paragraph-ignore-fill-prefix nil)
- ;; Need this or Emacs ignores fill-prefix when
- ;; inside a comment.
- (comment-multi-line t)
- (paragraph-start paragraph-start)
- (paragraph-separate paragraph-separate)
- fill-prefix)
- (if (kfill:adapt t)
- (throw 'done (kfill:funcall 'fill-paragraph arg)))))
- ;; Kfill:adapt failed or fill-prefix is set, so do a basic
- ;; paragraph fill as adapted from par-align.el.
- (kfill:fallback-fill-paragraph arg skip-prefix-remove)))))
+(defun kfill:fill-paragraph (&optional arg skip-prefix-remove)
+ "Fill paragraph at or after point when in kotl-mode. Prefix ARG means
justify as well."
+ (interactive (progn
+ (barf-if-buffer-read-only)
+ (list (if current-prefix-arg 'full) nil)))
+ ;; This may be called from `fill-region-as-paragraph' in "filladapt.el"
+ ;; which narrows the region to the current paragraph. A side-effect is
+ ;; that the cell identifier and indent information needed by this function
+ ;; when in kotl-mode is no longer visible. So we temporarily rewiden the
+ ;; buffer here. Don't rewiden past the paragraph of interest or any
+ ;; following blank line may be removed by the filling routines.
+ (save-restriction
+ (if (eq major-mode 'kotl-mode)
+ (narrow-to-region 1 (point-max)))
+ ;; Emacs expects a specific symbol here.
+ (if (and arg (not (symbolp arg))) (setq arg 'full))
+ (or skip-prefix-remove (kfill:remove-paragraph-prefix))
+ (catch 'done
+ (if (null fill-prefix)
+ (let ((paragraph-ignore-fill-prefix nil)
+ ;; Need this or Emacs ignores fill-prefix when
+ ;; inside a comment.
+ (comment-multi-line t)
+ (fill-paragraph-handle-comment t)
+ (paragraph-start paragraph-start)
+ (paragraph-separate paragraph-separate)
+ fill-prefix)
+ (if (kfill:adapt t)
+ (throw 'done (fill-paragraph arg)))))
+ ;; Kfill:adapt failed or fill-prefix is set, so do a basic
+ ;; paragraph fill as adapted from par-align.el.
+ (kfill:fallback-fill-paragraph arg skip-prefix-remove))))
;;;
;;; Redefine this built-in function so that it sets `prior-fill-prefix' also.
@@ -154,16 +148,17 @@ Also sets `prior-fill-prefix' to the previous value of
`fill-prefix'.
Filling removes any prior fill prefix, adjusts line lengths and then adds the
fill prefix at the beginning of each line."
(interactive)
- (setq prior-fill-prefix fill-prefix
- fill-prefix (if turn-off
- nil
- (buffer-substring
- (save-excursion (beginning-of-line) (point))
- (point))))
- (if (equal prior-fill-prefix "")
- (setq prior-fill-prefix nil))
- (if (equal fill-prefix "")
- (setq fill-prefix nil))
+ (setq prior-fill-prefix fill-prefix)
+ (let ((left-margin-pos (save-excursion (move-to-left-margin) (point))))
+ (if (> (point) left-margin-pos)
+ (setq fill-prefix (if turn-off
+ nil
+ (buffer-substring left-margin-pos (point))))
+ (setq fill-prefix nil)))
+ (when (equal prior-fill-prefix "")
+ (setq prior-fill-prefix nil))
+ (when (equal fill-prefix "")
+ (setq fill-prefix nil))
(cond (fill-prefix
(message "fill-prefix: \"%s\"; prior-fill-prefix: \"%s\""
fill-prefix (or prior-fill-prefix "")))
@@ -226,10 +221,6 @@ fill prefix at the beginning of each line."
(funcall function justify-flag)))
(fill-region-as-paragraph from (point) justify-flag)))))
-(defun kfill:funcall (function &rest args)
- "Call the original FUNCTION with rest of ARGS that kfill overloaded."
- (apply (cdr (assq function kfill:function-table)) args))
-
(defun kfill:hanging-list (paragraph)
(let (prefix match beg end)
(setq prefix (make-string (- (match-end 0) (match-beginning 0)) ?\ ))
diff --git a/kotl/kotl-mode.el b/kotl/kotl-mode.el
index 427d76d..eb14fed 100644
--- a/kotl/kotl-mode.el
+++ b/kotl/kotl-mode.el
@@ -79,6 +79,7 @@ It provides the following keys:
;; Some package such as filladapt has overwritten the primitives
;; defined in kfill.el, so reload it.
(load "kfill"))
+ (setq fill-paragraph-function #'kfill:fill-paragraph)
;; Ensure that outline structure data is saved when save-buffer is called
;; from save-some-buffers, {C-x s}.
(add-hook 'local-write-file-hooks #'kotl-mode:update-buffer)
@@ -153,7 +154,7 @@ It provides the following keys:
(kvspec:activate))))
;; We have been converting a buffer from a foreign format to a koutline.
;; Now that it is converted, ensure that `kotl-previous-mode' is set to
- ;; koutline now.
+ ;; koutline.
(setq kotl-previous-mode 'kotl-mode)
(run-hooks 'kotl-mode-hook)
(add-hook 'change-major-mode-hook #'kotl-mode:show-all nil t))
@@ -672,15 +673,17 @@ too long."
With arg N, insert N newlines."
(interactive "*p")
(let* ((bolp (and (kotl-mode:bolp) (not (kotl-mode:bocp))))
- (indent (kcell-view:indent)))
+ (indent (kcell-view:indent))
+ (add-prefix (and (stringp fill-prefix)
+ (not (string-empty-p fill-prefix)))))
(while (> arg 0)
(save-excursion
(insert ?\n)
- (if (and (not bolp) fill-prefix)
+ (if (and (not bolp) add-prefix)
(insert fill-prefix)
(insert-char ?\ indent)))
(setq arg (1- arg)))
- (if (and bolp fill-prefix)
+ (if (and bolp add-prefix)
(progn (delete-horizontal-space)
(insert fill-prefix)))))
@@ -2537,7 +2540,8 @@ With optional prefix ARG, toggle display of blank lines
between cells."
(kview:set-attr kview 'lines-to-show 0)
(outline-flag-region (point-min) (point-max) nil)
(if arg (kvspec:toggle-blank-lines))
- (kvspec:update t))))
+ (if (called-interactively-p 'interactive)
+ (kvspec:update t)))))
;;;###autoload
(defun kotl-mode:top-cells (&optional arg)
diff --git a/kotl/kvspec.el b/kotl/kvspec.el
index b68cb7c..9e0ee89 100644
--- a/kotl/kvspec.el
+++ b/kotl/kvspec.el
@@ -114,15 +114,14 @@ display all levels of cells."
(kview:set-attr kview 'levels-to-show levels-to-keep))
(defun kvspec:show-lines-per-cell (num)
- "Show NUM lines per cell."
+ "Show NUM lines per visible cell; 0 means show all lines in each visible
cell."
(if (or (not (integerp num)) (< num 0))
(error "(kvspec:show-lines-per-cell): Invalid lines per cell, `%d'" num))
(kview:set-attr kview 'lines-to-show num)
- (if (not (zerop num))
- ;; Now show NUM lines in cells.
- (kview:map-tree (lambda (kview)
- (kcell-view:expand (point))
- (kvspec:show-lines-this-cell num)) kview t t)))
+ ;; Now show NUM lines in cells.
+ (kview:map-tree (lambda (kview)
+ (kcell-view:expand (point))
+ (kvspec:show-lines-this-cell num)) kview t t))
(defun kvspec:toggle-blank-lines ()
"Toggle blank lines between cells on or off."
@@ -224,32 +223,25 @@ view specs."
;; "l" means use value of kview:default-levels-to-show.
;; "l0" means show all levels.
(let (levels)
- (if (not (string-match "l\\([0-9]+\\)?" kvspec:current))
- ;; Don't change the view if no view spec is given but note that
- ;; all levels should be shown in the future.
- (kview:set-attr kview 'levels-to-show 0)
- (if (match-beginning 1)
- (setq levels (string-to-number (match-string 1 kvspec:current)))
- (setq levels kview:default-levels-to-show))
- (kvspec:levels-to-show levels))))
+ (if (and (string-match "l\\([0-9]+\\)?" kvspec:current)
+ (match-beginning 1))
+ (setq levels (string-to-number (match-string 1 kvspec:current)))
+ (setq levels kview:default-levels-to-show))
+ (kvspec:levels-to-show levels)))
(defun kvspec:lines-to-show ()
"Show a set number of lines per cell according to `kvspec:current'."
- ;; "c" means use value of kview:default-lines-to-show.
+ ;; "c" or no "c" means use value of kview:default-lines-to-show.
;; "c0" means show all lines.
- (cond ((not (string-match "c\\([0-9]+\\)?" kvspec:current))
- ;; Don't change the view if no view spec is given but note that all
- ;; lines should be shown in the future.
- (kview:set-attr kview 'lines-to-show 0))
- ((match-beginning 1)
- (kvspec:show-lines-per-cell
- (string-to-number (match-string 1 kvspec:current))))
- (t (kvspec:show-lines-per-cell kview:default-lines-to-show))))
+ (if (and (string-match "c\\([0-9]+\\)?" kvspec:current)
+ (match-beginning 1))
+ (kvspec:show-lines-per-cell
+ (string-to-number (match-string 1 kvspec:current)))
+ (kvspec:show-lines-per-cell kview:default-lines-to-show)))
(defun kvspec:numbering ()
"Set the type of numbering (label) display according to `kvspec:current'."
- (if (not (string-match "n\\([.*~0-2]\\)?" kvspec:current))
- nil
+ (when (string-match "n\\([.*~0-2]\\)?" kvspec:current)
;; "n" means use value of kview:default-label-type.
;; "n0" means display idstamps.
;; "n1" means display alpha labels.
@@ -259,22 +251,21 @@ view specs."
;; "n~" means no labels.
(let (spec type)
(if (match-beginning 1)
- (setq spec (string-to-char
- (substring kvspec:current
- (match-beginning 1) (match-end 1)))
+ (setq spec (string-to-char (match-string 1 kvspec:current))
type (cdr (assq spec kvspec:label-type-alist)))
(setq type kview:default-label-type))
(kview:set-label-type kview type))))
(defun kvspec:show-lines-this-cell (num)
"Assume the current cell is fully expanded and collapse to show NUM lines
within it.
-If NUM is greater than the number of lines available, the cell remains fully
expanded."
+If NUM is less than 1 or greater than the number of lines available, the cell
remains fully expanded."
;; Use free variable label-sep-len bound in kview:map-* for speed.
- (let ((start (goto-char (kcell-view:start (point) label-sep-len)))
- (end (kcell-view:end-contents)))
- ;; Hide all but num lines of the cell.
- (and (> num 0) (search-forward "\n" end t num)
- (outline-flag-region (1- (point)) end t))))
+ (unless (< num 1)
+ (let ((start (goto-char (kcell-view:start (point) label-sep-len)))
+ (end (kcell-view:end-contents)))
+ ;; Hide all but num lines of the cell.
+ (and (search-forward "\n" end t num)
+ (outline-flag-region (1- (point)) end t)))))
(defun kvspec:update-modeline ()
"Setup or update display of the current kview spec in the modeline."
diff --git a/man/hyperbole.texi b/man/hyperbole.texi
index 4b3c352..f57abee 100644
--- a/man/hyperbole.texi
+++ b/man/hyperbole.texi
@@ -2679,7 +2679,9 @@ upon the referent context in which the Action Key is
released.
@example
Referent Context Link Type
----------------------------------------------------
+Global Button link-to-gbut
Explicit Button link-to-ebut
+Implicit Button link-to-ibut
Info Index Item link-to-Info-index-item
Info Node link-to-Info-node
Mail Reader Message link-to-mail
@@ -6494,58 +6496,29 @@ be of interest to users.
@cindex referent display
@cindex link display
@cindex display where
+@cindex display outside Emacs
@cindex where to display
+@cindex image display
+@cindex internal display
+@cindex external display
Hyperbole lets you control where link referents are displayed and even
what Emacs function or external program is used to display them.
-There are three categories of referents, each with its own display
-setting:
+There are four categories of referents, each with its own display
+setting, listed in decreasing order of priority.
+
@example
Referent Category Variable Setting
========================================================================
-Internal Standard Display hpath:display-where
+Internal Image Display hpath:native-image-suffixes
Internal Custom Display hpath:internal-display-alist
External Display hpath:external-display-alist
+Internal Standard Display hpath:display-where
@end example
-@cindex menu, Cust/Referents
-@kindex C-h h c r
-Regular file links are displayed in an Emacs window specified by the
-@code{hpath:display-where} setting which may be changed with the Cust/Referents
-@bkbd{C-h h c r} menu.
-
@noindent
-Available options are:
-
-@table @emph
-@item @bullet{} Any-Frame
-Display in the selected window of another existing frame
-@item @bullet{} Current-Win
-Display in the selected (current) window
-@item @bullet{} Diff-Frame-One-Win
-Display in the selected window of another existing frame, deleting its other
windows
-@item @bullet{} New-Frame
-Display in a new single window frame
-@item @bullet{} Other-Win
-Display in another, possibly new window of the selected frame (this is
-the default)
-@item @bullet{} Single-Win
-Display in a window of the selected frame and delete its other windows
-@end table
-
-@page
-@noindent
-Alternatively, you can use the Hyperbole menubar menu as shown here:
-
-@float Image,image:Menu-Display-Referents
-@caption{Display Referents Menu}
-@image{im/menu-display-referents,6in,,Display Referents Menu}
-@end float
-@sp 1
-
-@noindent
-Continue reading the next sections for information on custom Internal
-and External Viewers for link referencts.
+Continue reading the next sections for information on how referents
+are displayed internally and externally.
@node Internal Viewers, External Viewers, Referent Display, Customization
@subsection Internal Viewers
@@ -6554,6 +6527,13 @@ and External Viewers for link referencts.
@cindex display function
@cindex internal viewer
@cindex link, display function
+
+@cindex internal image display
+@vindex hpath:native-image-suffixes
+@cindex internal custom display
+@vindex hpath:internal-display-alist
+@cindex internal standard display
+@vindex hpath:display-where
When given a file name, Hyperbole will by default display the file for
editing within an Emacs buffer. The @code{hpath:internal-display-alist}
variable can be used to specify file name patterns, such as matching
@@ -6579,6 +6559,42 @@ Files with an @file{.rdb} suffix are displayed as
relational databases using the
available with InfoDock.
@end table
+@cindex menu, Cust/Referents
+@kindex C-h h c r
+Links to standard files, those which don't match any special referent
+category, are displayed in an Emacs window specified by the
+@code{hpath:display-where} setting. It may be changed with the Cust/Referents
+@bkbd{C-h h c r} menu.
+
+@noindent
+Available options are:
+
+@table @emph
+@item @bullet{} Any-Frame
+Display in the selected window of another existing frame
+@item @bullet{} Current-Win
+Display in the selected (current) window
+@item @bullet{} Diff-Frame-One-Win
+Display in the selected window of another existing frame, deleting its other
windows
+@item @bullet{} New-Frame
+Display in a new single window frame
+@item @bullet{} Other-Win
+Display in another, possibly new window of the selected frame (this is
+the default)
+@item @bullet{} Single-Win
+Display in a window of the selected frame and delete its other windows
+@end table
+
+@page
+@noindent
+Alternatively, you can use the Hyperbole menubar menu as shown here:
+
+@float Image,image:Menu-Display-Referents
+@caption{Display Referents Menu}
+@image{im/menu-display-referents,6in,,Display Referents Menu}
+@end float
+@sp 1
+
@xref{External Viewers}, for instructions on associating file names with
external, window-system specific viewers.
@@ -6592,6 +6608,9 @@ external, window-system specific viewers.
@cindex external program
@cindex external viewer
@cindex link, viewer program
+
+@cindex external display
+@vindex hpath:external-display-alist
If you will be using Hyperbole under a window system,
the @code{hpath:get-external-display-alist} function
in @file{hpath.el} supports hyperlinks that open files using external,
non-Emacs
@@ -6750,9 +6769,11 @@ through invisible/hidden text, making the text
temporarily visible
until point moves past that hidden part. When a search match is
selected, the surrounding text remains visible.
-This command toggles that setting (turns it off if a prefix
-argument less than or equal to 0 is given) and makes searches look at
-only visible text.
+You can temporarily disable searching of hidden text by typing {M-s i}
+while in an incremental search. This key sequence toggles that
+setting and makes searches look at only visible text (or the reverse
+when invoked again). The setting lasts only through the current
+interactive search.
@node Button Colors, , Invisible Text Searches, Customization
@subsection Configuring Button Colors
- [elpa] scratch/hyperbole-lexbind a65ee22 03/20: Small coding improvements, (continued)
- [elpa] scratch/hyperbole-lexbind a65ee22 03/20: Small coding improvements, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind 91e8a73 02/20: Add texinfo pathname section references; improve internal image links, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind e1a95cc 04/20: Improve paragraph filling to match newer Emacs versions, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind 60d51ad 12/20: Remove last references to XEmscs and xterm used under Emacs 18, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind af55195 05/20: Make Action Key handle bi-directional jumping for Org mode radio target and internal links, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind 36e4724 01/20: 7.0.3a bug fixes; add link-to-ibut, link-to-gbut, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind e647502 18/20: BSD zgrep support for Hyperbole grep command, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind 0829631 13/20: Fix small logic errors in new e/g/ilink functions, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind b128464 06/20: Update Changes and add 7.0.3 release message to HY-ANNOUNCE, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind 332ef33 19/20: V7.0.3b test release: Basic DEMO updates, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind c547ad4 10/20: Merge branch '7.0.3a' into prepare-pr-for-merging,
Stefan Monnier <=
- [elpa] scratch/hyperbole-lexbind 131295e 07/20: Remove conditionals on xemacs, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind ff0f602 11/20: Merge pull request #11 from matsl/prepare-pr-for-merging, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind da8f3fa 09/20: Add labeled implicit buttons, in-buffer links to g/e/ibuts, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind 9ad2bf0 08/20: Remove all featurep checks on xemacs and emacs, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind 21c7432 15/20: Most changes for 7.0.3a release, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind f38ee21 14/20: 7.0.3a changes for creating and modifying ibut labels, small fixes, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind 6e555e7 20/20: Merge remote-tracking branch 'hyperbole/master' into externals/hyperbole, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind d56c8c0 16/20: Most changes for 7.0.3a release, Stefan Monnier, 2019/08/14
- [elpa] scratch/hyperbole-lexbind 64c3563 17/20: Expanded Org mode doc; introduce 'key series' term in Glossary, Stefan Monnier, 2019/08/14