branch: externals/hyperbole
commit bc3fbcf750d65e86d7783b45351921282a0a624d
Author: Bob Weiner <r...@gnu.org>
Commit: Bob Weiner <r...@gnu.org>

    Add hyperbole-run-test-definition ibtype to run an ERT test from def
    
    Fix kimport.el and update tests for star, aug-post and text imports.
    Fix Shift-TAB within an Org table to go to previous field.
---
 ChangeLog             |  27 ++++-
 HY-NEWS               | 329 +++++++++++++++++++++++++++-----------------------
 hibtypes.el           |   7 +-
 hypb-ert.el           |  50 +++++++-
 kotl/EXAMPLE.kotl     |  35 +++---
 kotl/kimport.el       | 229 +++++++++++++++++++++--------------
 kotl/kotl-mode.el     |  11 +-
 man/hkey-help.txt     |   1 +
 man/hyperbole.texi    | 134 +++++++++++---------
 test/kimport-tests.el |  69 ++++++++---
 10 files changed, 545 insertions(+), 347 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index d3c27fc31e..9b6b019470 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
+2023-05-07  Bob Weiner  <r...@gnu.org>
+
+* test/kimport-tests.el: Improve all these tests and add
+    `kimport--aug-post-outline'.
+
+* hypb-ert.el (hyperbole-run-test-definition): Add ibtype that when on the
+    first line of an `ert-deftest' and not at eol nor on a grouping symbol,
+    evaluates the current version of the test and then runs it.  Assist Key
+    press in the same spot steps through the test with edebug.
+              (hyperbole-run-test-definition:help, hypb-ert-def-at-p,
+               hypb-ert-run-test-at-definition):
+    Support functions.
+
 2023-05-06  Bob Weiner  <r...@gnu.org>
 
+* kotl/kimport.el (kimport:aug-post-outline, kimport:text):
+    Update to match `kimport:star-outline'.
+                  (kimport:aug-post-statements):
+    Update to match `kimport:star-entries'.
+
+* kotl/EXAMPLE.kotl:
+  kotl/kotl-mode.el (kotl-mode):
+  man/hyperbole.texi (Promoting and Demoting): Update so {Shift-TAB} within
+    an Org table in a Koutline moves to the previous field to complement
+    the behavior of {TAB}.  This leaves {M-TAB} as the only consistent way
+    to promote trees.
+
 * man/im/action-key-animation.gif: Update this animated gif.
 
 2023-04-30  Mats Lidell  <ma...@gnu.org>
@@ -9,7 +34,7 @@
     (hui--ebut-rename-nonumbered-label, hui--ebut-rename-numbered-label)
     (hui--ebut-rename-all-copies)
   test/hbut-tests.el (hypb:program-create-ebut-in-buffer-with-same-label):
-    Tests for ebut label rename.
+    Test for ebut label rename.
 
 2023-04-30  Bob Weiner  <r...@gnu.org>
 
diff --git a/HY-NEWS b/HY-NEWS
index 59bd9069e9..3bcf70955f 100644
--- a/HY-NEWS
+++ b/HY-NEWS
@@ -8,8 +8,8 @@
 ** ACTION TYPES
 
   *** display-boolean, display-value, display-variable: Made all of these
-      interactive, so can be used as button actypes.
-
+      interactive, so can be used as button actypes.  See "(hyperbole)
+      actypes display-boolean".
 
 ** DOCUMENTATION
 
@@ -39,108 +39,115 @@
   *** Ibut Menu: Documented in the manual, notably the new Ibut/Create
       menu item.  See "(hyperbole)menu, Ibut/Create".
 
+  *** Manual Glossary: Added Ace Window, Consult, Org Mode, and Org Roam
+      entries.  See "(hyperbole)Glossary".
+
   *** Smart Key - Org Mode: Expanded with doc for more extensive behavior.
       See "(hyperbole)Smart Key - Org Mode".
 
-  *** Manual Glossary: Added Ace Window, Consult, Org Mode, and Org Roam 
entries.
-      See "(hyperbole)Glossary".
-
 
 ** HYCONTROL  (See "(hyperbole)HyControl").
 
-  *** I/J/K/M Key Bindings: In Window Control mode, move directionally (based
-      on QUERTY keyboard layout) among windows in the selected frame.  In Frame
-      Control mode, move directionally among active frames.  These keys utilize
-      and prompt to install the windmove and framemove packages if not 
installed.
-      See "(hyperbole)I/J/K/M".
+  *** I/J/K/M Key Bindings: In Window Control mode, move directionally
+      (based on QUERTY keyboard layout) among windows in the selected frame.
+      In Frame Control mode, move directionally among active frames.  These
+      keys utilize and prompt to install the windmove and framemove packages
+      if not installed.  See "(hyperbole)I/J/K/M".
 
-** HYPERBOLE SYSTEM  (See "(hyperbole)").
 
-  *** Native Compilation: Hyperbole now may be natively compiled (.eln files).
-      It works around an Emacs bug where async native comp of a package being
-      installed does not load "hyperbole-autoloads.el".  When building 
Hyperbole
-      without a package manager, 'make eln' now builds it natively.
+** HYPERBOLE SYSTEM  (See "(hyperbole)").
 
-  *** Natively Compiled Functions as Action Types: Now may be used as Hyperbole
-      button action types.  See "(hyperbole)Action Types".
+  *** Any Colorized Display: Face display and colorization of Hyperbole
+      buttons now works on any display capable of displaying colors.  See
+      "(hyperbole)Button Colors".
 
-  *** Reduced Warnings: Large number of byte-compiler warnings eliminated when
-      building the Hyperbole package.  None of these warnings should affect use
-      of Hyperbole.  Most open Hyperbole issues have also been resolved.
+  *** Create Buttons in Current Buffer: Stopped prompting for a source
+      buffer when creating a Hyperbole button.  Always use the current
+      buffer and point.  See "(hyperbole)Creation".
 
   *** Improved Button Help: {C-h A} now says whether a button is explicit or
       implicit.  For implicit buttons, it displays the doc from both its
       implicit button type and its associated action type.
 
-      {C-h A} now also works on Emacs push-buttons, displaying their attributes
-      and associated action.  See "(hyperbole)Smart Key help".
-
-  *** Improved Smart Key Debugging: {C-h h c d} enables Hyperbole Smart Key
-      Action debugging.  If an explicit button has an action that overrides its
-      default action type action, then the debug messages will now show that
-      action.  Debug messages now also show all of the attributes of the 
current
-      button.  See "(hyperbole)Smart Key Debugging".
+      {C-h A} now also works on Emacs push-buttons and text property
+      buttons, displaying their attributes and associated action.  See
+      "(hyperbole)Smart Key help".
 
-  *** Any Colorized Display: Face display and colorization of Hyperbole 
buttons now
-      works on any display capable of displaying colors.  See 
"(hyperbole)Button
-      Colors".
-
-  *** Create Buttons in Current Buffer: Stopped prompting for a source buffer
-      when creating a Hyperbole button.  Always use the current buffer and 
point.
-      See "(hyperbole)Creation".
-
-  *** Interactive Org-Roam DB Consult Grep: {M-x hsys-org-roam-consult-grep 
RET}
-      Interactively greps org-roam files with live in-buffer display as you 
move
-      through matching lines.  It uses the automatically installed 
consult-org-roam
-      package when invoked.  See "(hyperbole)hsys-org-roam-consult-grep".
+  *** Interactive Org-Roam DB Consult Grep: {M-x hsys-org-roam-consult-grep
+      RET} Interactively greps org-roam files with live in-buffer display as
+      you move through matching lines.  It uses the automatically installed
+      consult-org-roam package when invoked.  See
+      "(hyperbole)hsys-org-roam-consult-grep".
 
   *** mhtml-mode Markup Selection: Hyperbole's matching markup pair selection,
       copying and movement now works with Emacs' builtin mhtml-mode.  See
       "(hyperbole)HTML tag pair".
 
+  *** Native Compilation: Hyperbole now may be natively compiled (.eln files).
+      It works around an Emacs bug where async native comp of a package being
+      installed does not load "hyperbole-autoloads.el".  When building
+      Hyperbole without a package manager, 'make eln' now builds it natively.
+
+  *** Natively Compiled Functions as Action Types: Now may be used as
+      Hyperbole button action types.  See "(hyperbole)Action Types".
+
+  *** Reduced Warnings: Large number of byte-compiler warnings eliminated when
+      building the Hyperbole package.  None of these warnings should affect
+      use of Hyperbole.  Most open Hyperbole issues have also been resolved.
+
   *** XEmacs: Removed old XEmacs-compatibility code.
 
 
 ** HYROLO  (See "(hyperbole)HyRolo").
 
-  *** Koutline and Markdown File Support: The `hyrolo-file-list' can now 
contain
-      Koutline or Markdown files and will search their outline entries just 
like
-      it does for Org and Emacs outline files.  See "(hyperbole)HyRolo 
Concepts".
+  *** HyRolo Match Buffer Key Bindings: Improved movement keys:
+
+        - {b} Move backward at the same outline level
+        - {f} Move forward at the same outline level
+        - {n} Move to the next visible outline heading
+        - {p} Move to the previous visible outline heading
+       - {u} Move up a heading level
+        - {,} Move to the beginning of the current entry
+        - {.} Move to the end of the current entry
 
-  *** Koutline Fast Search: Koutlines may now be included in `hyrolo-file-list'
-      and individual cells extracted properly with any HyRolo query.  Then the
-      interactive commands to show the top-level matches, an outline of matches
-      or to show, hide or move to matches, all work in the match display buffer
-      as well.
+      See "(hyperbole)Hyrolo Keys".
 
-  *** Match Buffer Name Change: Changed match buffer name from "*Hyperbole 
Rolo*"
-      to "*HyRolo*".
+  *** Koutline Fast Search: Koutlines may now be included in
+      `hyrolo-file-list' and individual cells extracted properly with any
+      HyRolo query.  Then the interactive commands:
 
-  *** New HyRolo menu items ConsultFind and HelmFind:  These appear when you
-      independently load consult or helm.  These menu items then use the
-      related interactive search functions to search over the HyRolo file list.
-      See "(hyperbole)Consult" and "(hyperbole)Helm".
+        {t} show the top-level matches
+        {o} show an outline of matches
+        {s} show/expand current match
+        {h} hide current match
+       {f/b/n/p} move to another match
 
-      ConsultFind utilizes `consult-grep' or `consult-ripgrep'.
-      HelmFind uses the helm-org-rifle package and searches over .org and
-      .otl files exclusively.
+      all work on Koutline cells displayed in the match buffer.  See
+      "(hyperbole) HyRolo Concepts".
 
-  *** HyRolo Match Buffer Key Bindings: Improved movement keys:
+  *** Koutline and Markdown File Support: The `hyrolo-file-list' can now
+      contain Koutline or Markdown files and will search their outline entries
+      just like it does for Org and Emacs outline files.  See
+      "(hyperbole)HyRolo Concepts".
+
+  *** Match Buffer Name Change: Changed match buffer name from "*Hyperbole
+      Rolo*" to "*HyRolo*".
 
-        - {b} Moves backward at the same outline level
-        - {f} Moves forward at the same outline level
-        - {n} Moves to the next visible outline heading
-        - {p} Moves to the previous visible outline heading
-       - {u} Moves up a heading level
-        - {.} Moves to the end of the current entry
-        - {,} Moves to the beginning of the current entry
+  *** New HyRolo menu items ConsultFind and HelmFind: These appear when you
+      independently load the @file{consult} or @file{helm-org-rifle} package.
+      These menu items then use the related interactive search functions to
+      search over the HyRolo file list.
+
+      ConsultFind utilizes `consult-ripgrep' or `consult-grep'.  HelmFind uses
+      the helm-org-rifle package and searches over .org and .otl files
+      exclusively.  See "(hyperbole)ConsultFind".
 
 
 ** IMPLICIT BUTTONS
 
-  *** Action Button Result Display: Action buttons now display in the 
minibuffer
-      the result of evaluating any type of action expression, using Lisp
-      readable values.
+  *** Action Button Result Display: Action buttons now display in the
+      minibuffer the result of evaluating any type of action expression,
+      using Lisp readable values.
 
   *** Compilation and Grep Error Lines: Error lines in the Emacs Regression
       Test buffer, *ert*, are now supported, as well as the 'Compiling
@@ -155,13 +162,29 @@
       Added jumping to the referenced location from Ruby traceback stack
       messages.
 
+  *** Emacs Regression Test Runs: New 'hyperbole-run-test-definition' implicit
+      button type defined in "hypb-ert.el".  An Action Key press on the first
+      line of an ert test def and not on a grouping symbol (like a parenthesis)
+      nor at the end of a line, evaluates the definition and runs the test;
+      this ensures that the latest version is always run.  An Assist Key press
+      does likewise but runs the test with edebug, stepping through it.
+
+  *** Highlighting of Ibut Names: New `property:ibut-face' used to highlight
+      any <[name]> prefixing an implicit button.  All hproperty functions now
+      support this face as well as the `hproperty:but-face' used for explicit
+      buttons.
+
+  *** Jump to Lisp Identifier Definition in More Buffers: Lisp identifiers are
+      now recognized as programming etags in the *Warnings* byte-compilation
+      buffer and in Flymake log and diagnostics buffers.
+
   *** Info Nodes: Better handle embedded double quotes and add support for
       HTML &quot; quoting.
 
   *** Improved # and Embedded Space Path Handling: If a path exists, don't
-      treat its # hash marks as section markers, notably for #autosave#
-      files.  Allow for unquoted filenames with spaces in them in ls
-      listings in shell buffers (assume files are tab-delimited).
+      treat its # hash marks as section markers, notably for #autosave# files.
+      Allow for unquoted filenames with spaces in them in ls listings in shell
+      buffers (assume files are tab-delimited).
 
   *** Ibut/Create Menu Item: Creates a named/labeled implicit button of any
       type.  Separates the name and the implicit button with " - ".
@@ -169,15 +192,6 @@
   *** Relative Info Paths: Info files with relative pathnames outside of the
       `Info-directory-list' now resolve properly, e.g. "man/hyperbole.info".
 
-  *** Highlighting of Ibut Names: New `property:ibut-face' used to highlight
-      any <[name]> prefixing an implicit button.  All hproperty functions
-      now support this face as well as the `hproperty:but-face' used for
-      explicit buttons.
-
-  *** Jump to Lisp Identifier Definition in More Buffers: Lisp identifiers
-      are now recognized as programming etags in the *Warnings*
-      byte-compilation buffer and in Flymake log and diagnostics buffers.
-
   *** Path Implicit Buttons: Much improved relative path handling, including
       expanding into executable paths when pathname is prefixed by ! or &,
       handling info paths outside `Info-directory-list', like
@@ -197,31 +211,35 @@
 
 ** KOUTLINER  (See "(hyperbole)Koutliner").
 
-  *** M-S-left and M-S-Right: Org compatibility - Add tree promote and demote
-      commands to these keys (same as existing M-left and M-right keys).
+  *** {M-S-<left>} and {M-S-<right>}: Org compatibility - Add tree promote and
+      demote commands to these keys (same as existing {M-<left>} and
+      {M-<right>} keys).  See "(hyperbole)Promoting and Demoting".
 
   *** Star Outline Import Indented Headings: Added support for Emacs/Org
       star-based headings whose stars do not start at the beginning of a line,
-      i.e. are indented.
+      i.e. are indented.  See "(hyperbole)Inserting and Importing".
 
 
 ** MENUS  (See "(hyperbole)Menus").
 
   *** Minibuffer Menu Changes:
-        - Multi-line Menus:  When a menu line is too long for the screen,
-          it is automatically split into multiple lines and aligned by column
-         for ease of access.
+
+        - Multi-line Menus: When a menu line is too long for the screen, it is
+          automatically split into multiple lines and aligned by column for
+          ease of access.
 
   *** Move Prefix Arg Number of Items: {M-b} and {M-f} move backward and
-      forward by the number of items specified in any prefix argument given.
+      forward by the number of items specified by any given prefix argument,
+      as do {TAB} and {Shift-TAB}.  See "(hyperbole)minibuffer menu".
 
 
-** HYPERBOLE PROGRAMMING INTERFACE CHANGES
+** PROGRAMMING INTERFACE CHANGES
 
   *** (hypb:devdocs-lookup): Install and load devdocs package and then
       call its `devdocs-lookup' function.
 
-  *** (hpath:resolve): Add to resolve path variables without doing a path 
expand.
+  *** (hpath:resolve): Add to resolve path variables without doing a path
+      expand.
 
   *** (hsys-org-meta-return): Centralize sharing of {M-RET} key with Org mode.
 
@@ -251,10 +269,9 @@
       (hyrolo-helm-org-rifle-directory): Behaves similarly but searches
       over `org-directory'.
 
-  *** hsys-org-roam.el: This library supports interactively grepping
-      over org-roam files with live in-buffer display.  It uses the
-      automatically installed consult package when `hsys-org-roam-consult-grep'
-      is invoked.
+  *** hsys-org-roam.el: This library supports interactively grepping over
+      org-roam files with live in-buffer display.  It uses the automatically
+      installed consult package when `hsys-org-roam-consult-grep' is invoked.
 
   *** (hattr:list): Now also returns the attributes of an Emacs push-button
        using `hattr:emacs-button-attributes', as recognized by
@@ -262,8 +279,8 @@
 
   *** (hui:ibut-create, ibut:create, ibut:delimit, ibut:edit, ibut:operate):
       Add interactive, named/labeled implicit button creation.  For
-      `ibut:create', improve doc and add but-sym arg which can supply
-      all other arguments in its properties.
+      `ibut:create', improve doc and add but-sym arg which can supply all
+      other arguments in its properties.
 
   *** (ibut:label-key-match): Return filtered list of ibut labels.
 
@@ -281,11 +298,11 @@
 
       (set:replace): Now replaces a non-keyed old-value with a new value.
 
-      (set:replace-member): Added this new function to replace an existing
-      set member or to add a new one if no matching existing member.
+      (set:replace-member): Added this new function to replace an existing set
+      member or to add a new one if no matching existing member.
 
-      (set:members): Now keeps members in stable order; previously
-      returned in reverse order.
+      (set:members): Now keeps members in stable order; previously returned in
+      reverse order.
 
   *** (hycontrol-framemove-*): Add hycontrol-framemove-direction,
       hycontrol-framemove-up, hycontrol-framemove-left,
@@ -306,24 +323,24 @@
 
   *** (hui:menu-choose): Renamed from `hui:menu-select'.
 
-  *** (hyperbole-web-search): Added optional `return-search-expr-flag'
-      to return search expression rather than doing the search, to build up
-      more involved search commands.
+  *** (hyperbole-web-search): Added optional `return-search-expr-flag' to
+      return search expression rather than doing the search, to build up more
+      involved search commands.
 
   *** (hypb:replace-match-string): Removed this unused function.
 
   *** (hyrolo-verify, hyrolo-isearch, hyrolo-next-match,
-       hyrolo-previous-match, hyrolo-isearch-for-regexp):
-      Added support for use in main HyRolo file, not just the match buffer.
+       hyrolo-previous-match, hyrolo-isearch-for-regexp): Added support for
+       use in main HyRolo file, not just the match buffer.
 
-  *** (ibut:at-p): Fixed to return nil if name and lbl-key are both nil.
-      Also added support for <> and {} ibut delimiters.
+  *** (ibut:at-p): Fixed to return nil if name and lbl-key are both nil.  Also
+      added support for <> and {} ibut delimiters.
 
-  *** (hyrolo-find-file-noselect-function): Added so can customize
-      low-level function used to read in each file searched by HyRolo.
+  *** (hyrolo-find-file-noselect-function): Added so can customize low-level
+      function used to read in each file searched by HyRolo.
 
-  *** (hyrolo-previous-match): Changed so this can be used in a
-      predicate when a match is found.
+  *** (hyrolo-previous-match): Changed so this can be used in a predicate when
+      a match is found.
 
   *** (hyrolo-grep): Added support for `outline-regexp' and `outline-level'
       variables from multiple file types.
@@ -331,28 +348,31 @@
       (hyrolo-mode-outline-level): Added and used in `hyrolo-mode'.
 
       (hyrolo-mode): Set the local value of `outline-level' to
-      `hyrolo-mode-outline-level' and define that function to support
-      star outlines and Koutlines.  Also, made `hyrolo-entry-regexp'
-      local and set it to its default value, after which it may be
-      modified.
+      `hyrolo-mode-outline-level' and define that function to support star
+      outlines and Koutlines.  Also, made `hyrolo-entry-regexp' local and set
+      it to its default value, after which it may be modified.
 
   *** (hyrolo-fgrep-file, hyrolo-grep-file, hyrolo-fgrep, hyrolo-grep,
-      hyrolo-word): Added optional `headline-only' argument to limit
-      searches to headlines.
+      hyrolo-word): Added optional `headline-only' argument to limit searches
+      to headlines.
+
+  *** (hyrolo-next-regexp-match, hyrolo-next-match-function): Added to allow
+      for different hyrolo entry matching functions.
 
-  *** (hyrolo-next-regexp-match, hyrolo-next-match-function): Added to
-      allow for different hyrolo  entry matching functions.
+  *** (smart-push-button): Added and referenced in `hkey-help' to trigger
+      push-button-specific help output.
 
 
 ** ORG MODE INTEGRATION (See "(hyperbole)Smart Key - Org Mode").
 
   *** Org and Org Roam IDs: New `org-id' implicit button type and
-      `link-to-org-id-marker' action type that jump to the referent of an
-      Org ID or Org Roam ID at point.  If a marker does not yet exist,
-      there is the `link-to-org-id' action type.  An Action Key drag across
-      windows ending at an Org ID will create a link button with this last
-      action type, which will jump to the ID's definition regardless of
-      whether the link was to the definition or a reference.
+      `link-to-org-id-marker' action type that jump to the referent of an Org
+      ID or Org Roam ID at point.  If a marker does not yet exist, there is
+      the `link-to-org-id' action type.  An Action Key drag across windows
+      ending at an Org ID will create a link button with this last action
+      type, which will jump to the ID's definition regardless of whether the
+      link was to the definition or a reference.  See "(hyperbole) ibtypes
+      org-id".
 
   *** Org Code Blocks: On a header :dir directory, the Action Key displays
       that directory in dired.  The Assist Key anywhere in the header removes
@@ -362,27 +382,22 @@
       targets now work just as they do on radio button targets.
 
   *** Todo Cycling: An Action Key press on an Org mode todo state keyword,
-      cycles to the next state.  An Assist Key press in the same place 
-      cycles to the next set of states, if any.
+      cycles to the next state.  An Assist Key press in the same place cycles
+      to the next set of states, if any.
 
-  *** {C-c /}: Hyperbole {C-c /} web search binding defers to org-mode
-      binding, `org-show-todo-tree' but uses the improved Hyperbole version,
-      `hsys-org-todo-occur' which allows filtering to specific todo states.
+  *** {C-c /}: The Hyperbole {C-c /} web search binding defers to the org-mode
+      binding, `org-show-todo-tree', when in Org mode, but uses the improved
+      Hyperbole command version, `hsys-org-todo-occur', which allows filtering
+      to specific todo states.
 
 
 ** SMART (ACTION AND ASSIST) KEYS  (See "(hyperbole)Smart Keys").
 
-  *** Smart Dired: Action Key subdirectory selection at point now works on
-      any dired header line, not just the first one.  Use {i} to insert
-      multiple subdirectories in Dired mode.  Smart Key end-of-line behavior
-      is no longer specified in Dired mode but handled globally for consistency
-      across modes.
-
   *** Hyperbole Symbol Tags: Hyperbole now includes a pre-built TAGS file so
-      that an Action Key press on any Hyperbole symbol jumps to its
-      definition without the need for any additional support.  This also
-      works on Hyperbole type names (which have a hidden prefix) in a help
-      buffer where an Action Key press displays the type definition.
+      that an Action Key press on any Hyperbole symbol jumps to its definition
+      without the need for any additional support.  This also works on
+      Hyperbole type names (which have a hidden prefix) in a help buffer where
+      an Action Key press displays the type definition.
 
   *** Lisp Load, Autoload and Require Expressions: Action Key press on any
       named target in such expressions displays the associated library.
@@ -392,29 +407,41 @@
       functions run with a press of the Assist Key on such buttons.  See
       "(hyperbole)Action Buttons".
 
+  *** Smart Dired: Action Key subdirectory selection at point now works on any
+      dired header line, not just the first one.  Use {i} to insert multiple
+      subdirectories in Dired mode.  Smart Key end-of-line behavior is no
+      longer specified in Dired mode but handled globally for consistency
+      across modes.  See "(hyperbole)Smart Key - Dired Mode".
+
 
 ** TEST CASES
 
-  *** Hyperbole Automated Testing: Automated test cases increased to over
-      285.  Simply run 'make test-all' or 'make test' from the command-line
-      when in the Hyperbole source directory and you should see all tests
-      pass.  If any fail, you can press the Action Key to see the source of
-      the failure.  Full testing is supported under POSIX systems only.  See
-      "Makefile" and "test/MANIFEST".
+  *** Hyperbole Automated Testing: Automated test cases increased to over 285.
+      Simply run 'make test-all' or 'make test' from the command-line when in
+      the Hyperbole source directory and you should see all tests pass.  If
+      any fail, you can press the Action Key to see the source of the failure.
+      Full testing is supported under POSIX systems only.  See "Makefile" and
+      "test/MANIFEST".
 
   *** The Hyperbole team's CI/CD process automatically runs all test cases
       against Emacs major versions 27, 28 and 29 whenever a code change is
       checked in against git.
 
+  *** QA: Many quality improvements across Hyperbole and integration with
+      Emacs updates with backward compatibility from Emacs 27 through Emacs 29
+      releases.
+
+
+** WINDOW GRIDS (See "(hyperbole)grid of windows").
 
-** WINDOWS GRIDS (See "(hyperbole)grid of windows").
+  *** Grid by File Pattern: Fixed so prompt for a string pattern rather than a
+      file name and forced use of full pathnames to avoid improper relative
+      path resolution.
 
-  *** Grid by File Pattern: Fixed so prompt for a string pattern rather than
-      a file name and forced use of full pathnames to avoid improper relative
-      path resolution.  See 
"(hyperbole)hycontrol-windows-grid-by-file-pattern".
+      Updated to use prefix arg as grid size or to autosize when not given or
+      given an invalid value.
 
-      Updated to use prefix arg as grid size or to autosize when not given
-      or given an invalid value.
+      See "(hyperbole)hycontrol-windows-grid-by-file-pattern".
 
 
 ===========================================================================
diff --git a/hibtypes.el b/hibtypes.el
index b0e723261a..1c49ca0005 100644
--- a/hibtypes.el
+++ b/hibtypes.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    19-Sep-91 at 20:45:31
-;; Last-Mod:     23-Apr-23 at 20:04:58 by Mats Lidell
+;; Last-Mod:      7-May-23 at 13:23:19 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
@@ -120,7 +120,8 @@ line and check for a source reference line again."
       (hib-python-traceback))))
 
 ;;; ========================================================================
-;;; Runs Hyperbole tests
+;;; Action Button Types that run Hyperbole tests;
+;;; ert-deftest ibtype executes current ert test when on first line of def.
 ;;; ========================================================================
 
 (load "hypb-ert")
@@ -132,7 +133,7 @@ line and check for a source reference line again."
 (load "hib-social")
 
 ;;; ========================================================================
-;;; Displays Org Roam and Org IDs
+;;; Displays Org Roam and Org IDs.
 ;;; ========================================================================
 
 (defib org-id ()
diff --git a/hypb-ert.el b/hypb-ert.el
index aafc59ab63..159384a039 100644
--- a/hypb-ert.el
+++ b/hypb-ert.el
@@ -3,7 +3,7 @@
 ;; Author:       Mats Lidell <ma...@gnu.org> and Bob Weiner <r...@gnu.org>
 ;;
 ;; Orig-Date:    31-Mar-21 at 21:11:00
-;; Last-Mod:     11-May-22 at 00:00:42 by Bob Weiner
+;; Last-Mod:      7-May-23 at 20:23:27 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
@@ -29,6 +29,7 @@
 
 ;;; Code:
 
+(require 'lisp-mode)
 (require 'hload-path)
 (require 'ert)
 (require 'hbut)
@@ -65,5 +66,52 @@
   (hypb-ert-require-libraries)
   (ert t))
 
+;; The following expression is true only when an ert-deftest has been
+;; instrumented by edebug:
+;; (memq 'edebug-enter (flatten-tree (ert-test-body (ert-get-test test-sym))))
+
+(defun hypb-ert-def-at-p ()
+  "Return test name if on the name in the first line of an ert test def."
+  (unless (or (eolp)
+             (memq (char-after (point))
+                   '(?\( ?\) ?\[ ?\] ?{ ?} ?< ?>)))
+    (save-excursion
+      (forward-line 0)
+      (when (looking-at (concat "(ert-deftest[ \t]+\\("
+                               lisp-mode-symbol-regexp
+                               "\\)[ \t]+("))
+       (match-string-no-properties 1)))))
+
+(defun hypb-ert-run-test-at-definition (test-name &optional debug-it)
+  "Assume on the name in the first line of an ert test def, eval and run the 
test.
+With optional DEBUG-IT non-nil (when the assist-key is pressed), edebug the
+test when it is run."
+  (let (test-sym)
+    (setq test-sym (intern-soft test-name))
+    ;; Ensure run the latest version of the test, either with the
+    ;; edebugger if already instrumented for it; otherwise, with the
+    ;; normal evaluator.
+    (if (and test-sym debug-it)
+       (edebug-defun)
+      (eval-defun nil))
+    (setq test-sym (intern-soft test-name))
+    (when (and test-sym (ert-test-boundp test-sym))
+      (when (and buffer-file-name (string-prefix-p hyperb:dir 
buffer-file-name))
+       (hypb-ert-require-libraries))
+      (ert test-sym))))
+
+(defib hyperbole-run-test-definition ()
+  "If on the name in the first line of an ert test def, eval and run the test.
+With an Assist Key press instead, edebug the test and step through it."
+  (let ((test-name (hypb-ert-def-at-p)))
+    (when test-name
+      (hact 'hypb-ert-run-test-at-definition test-name))))
+
+(defun hyperbole-run-test-definition:help (_hbut)
+  "If on the name in the first line of an ert test def, edebug the test."
+  (let ((test-name (hypb-ert-def-at-p)))
+    (when test-name
+      (hypb-ert-run-test-at-definition test-name t))))
+
 (provide 'hypb-ert)
 ;;; hypb-ert.el ends here
diff --git a/kotl/EXAMPLE.kotl b/kotl/EXAMPLE.kotl
index 4404177a04..8fee7f1554 100644
--- a/kotl/EXAMPLE.kotl
+++ b/kotl/EXAMPLE.kotl
@@ -49,11 +49,9 @@
            then yank the contents into another cell with {C-y}.
 
       3b5. Tree Demotion and Promotion: Trees may be demoted pressing {TAB}
-           or promoted by pressing {M-TAB} or {SHIFT-TAB}, as in most
-           outliners today. Sub-levels move with their parents.  {M-0 TAB}
-           and {M-0 M-TAB} will demote and promote trees and will
-           additionally refill each cell that has not been specially marked
-           to prevent refilling.
+           or promoted by pressing {M-TAB}.  {M-0 TAB} and {M-0 M-TAB} will
+           demote and promote trees and will additionally refill each cell
+           that has not been specially marked to prevent refilling.
            
            {M-1 TAB} behaves specially.  It toggles the function of {TAB} and
            {M-TAB} so that they insert a tab character and remove the
@@ -102,8 +100,8 @@
            Copying and moving only work within a single outline right now, so
            don't try to move or copy trees to another Koutline file.
            
-            {[M-down]}    - Move current tree past prefix arg same level trees.
-            {[M-up]}      - Move current tree back prefix arg same level trees.
+            {M-<down>}    - Move current tree past prefix arg same level trees.
+            {M-<up>}      - Move current tree back prefix arg same level trees.
            
             {C-c c}       - Copy <tree> to follow as sibling of <cell>.
             {C-u C-c c}   - Copy <tree> to follow as first child of <cell>.
@@ -372,29 +370,30 @@
 
       3d2. Here are two table examples:
            
-           |--------------------------------+---------------------------|
-           | Promotion Inside Org Table     | Demotion Inside Org Table |
-           |--------------------------------+---------------------------|
-           | {M-0 Shift-TAB} or {M-0 M-TAB} | {M-0 TAB}                 |
-           | {C-c C-,}                      | {C-c C-.}                 |
-           | {C-c C-<}                      | {C-c C->}                 |
-           |--------------------------------+---------------------------|
+           |----------------------------+---------------------------|
+           | Promotion Inside Org Table | Demotion Inside Org Table |
+           |----------------------------+---------------------------|
+           | {M-0 M-TAB}                | {M-0 TAB}                 |
+           | {C-c C-,}                  | {C-c C-.}                 |
+           | {C-c C-<}                  | {C-c C->}                 |
+           |----------------------------+---------------------------|
                       
            |-----------------------------+----------------------------|
            | Promotion Outside Org Table | Demotion Outside Org Table |
            |-----------------------------+----------------------------|
-           | {Shift-TAB} or {M-TAB}      | {TAB}                      |
-           | {M-left}                    | {M-right}                  |
+           | {M-TAB} or {Shift-TAB}      | {TAB}                      |
+           | {M-<left>}                  | {M-<right>}                |
            | {C-c C-,}                   | {C-c C-.}                  |
            | {C-c C-<}                   | {C-c C->}                  |
            |-----------------------------+----------------------------|
            
-           
            To toggle table editing mode on or off, press the Action
            Key on any of the table | symbols and then edit as you
            would any Org table.  Note how the above tables show how
            TAB and Shift-TAB behave differently in and outside of
-           tables.  See "(Org)Tables" for help on utilizing tables.
+           tables; use M-TAB rather than Shift-TAB for tree promotion
+           consistency anywhere.  See "(Org)Tables" for help on utilizing
+           tables.
 
     3e. The Koutliner code runs on any system that supports Emacs,
         whether under a window system or from a dumb terminal display.
diff --git a/kotl/kimport.el b/kotl/kimport.el
index 4747d9122d..c4ab4d8e76 100644
--- a/kotl/kimport.el
+++ b/kotl/kimport.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    15-Nov-93 at 11:57:05
-;; Last-Mod:      9-Apr-23 at 18:42:50 by Bob Weiner
+;; Last-Mod:      7-May-23 at 16:11:58 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
@@ -103,6 +103,9 @@ information on specific importation formats."
                             (match-string 0 import-buf-name))))
        (setq function (or (cdr (assoc import-suffix kimport:suffix-alist))
                           (cdr (assq t kimport:mode-alist))))))
+    (when hkey-debug
+      (message "(kimport:file): Buffer: %s; Import-Function: %s"
+              import-buf-name function))
     (funcall function import-from output-to children-flag)))
 
 (defun kimport:insert-buffer (buffer)
@@ -183,8 +186,8 @@ Each statement to be imported is delimited by an Augment 
relative id at the
 end of the statement.  \"1\" = level 1, \"1a\" = level 2 in outline and so
 on."
   (interactive "FImport from Augment post-numbered buffer/file: \nFBuffer/file 
to insert cells into: \nP")
-  (let ((output-level 1) (klabel "1")
-       initially-empty-output no-renumber orig-point count total)
+  (let ((output-level 1) (klabel "1") (count 0)
+       max-pos-and-count initially-empty-output no-renumber orig-point total)
     ;; Don't change the order of import-from and output-to inits here.
     (setq import-from (kimport:copy-and-set-buffer import-from)
          output-to (kimport:initialize output-to t)
@@ -207,21 +210,28 @@ on."
       (unless initially-empty-output
        ;; Insert first cell as sibling of current cell.
        (set-buffer output-to)
-       (if children-flag
-           ;; Insert as children.
-           (progn (setq klabel (klabel:child (kcell-view:label))
-                        output-level (klabel:level klabel))
-                  ;; Move to end of this cell since cell insertion will
-                  ;; occur at point.
-                  (goto-char (kcell-view:end)))
-         ;; Insert as successors.
-         (setq klabel (klabel:increment (kcell-view:label))
-               output-level (klabel:level klabel))
-         ;; Move to start of line of next tree since cell insertion will occur
-         ;; at point.
-         (goto-char (kotl-mode:tree-end))))
-      (setq count (kimport:aug-post-statements
-                  import-from output-to klabel output-level 1 0 total)))
+       (cond (children-flag
+              ;; Insert as children.
+              (setq klabel (klabel:child (kcell-view:label))
+                    output-level (klabel:level klabel))
+              ;; Move to end of this cell since cell insertion will
+              ;; occur at point.
+              (goto-char (kcell-view:end)))
+             ((string-empty-p (kcell-view:contents))
+              ;; This is an unused cell, fill in from here.
+              (setq klabel (kcell-view:label)
+                    output-level (klabel:level klabel))
+              (goto-char (kcell-view:start)))
+             (t ;; Insert as successors.
+              (setq klabel (klabel:increment (kcell-view:label))
+                    output-level (klabel:level klabel))
+              ;; Move to start of line of next tree since cell insertion
+              ;; will occur at point.
+              (goto-char (kotl-mode:tree-end)))))
+      (setq max-pos-and-count (kimport:aug-post-statements
+                              import-from output-to klabel
+                              output-level 1 count total 0)
+           count (cdr max-pos-and-count)))
     (pop-to-buffer output-to)
     (kfile:narrow-to-kcells)
     (unless no-renumber
@@ -249,8 +259,8 @@ placed.
     (setq import-from buffer-file-name))
   (when (and buffer-file-name (directory-name-p output-to))
     (setq output-to (concat (file-name-sans-extension buffer-file-name) 
".kotl")))
-  (let ((output-level 1) (klabel "1")
-       max-pos-and-count initially-empty-output no-renumber orig-point count 
total)
+  (let ((output-level 1) (klabel "1") (count 0)
+       max-pos-and-count initially-empty-output no-renumber orig-point total)
     ;; Don't change the order of import-from and output-to inits here.
     (setq import-from (kimport:copy-and-set-buffer import-from)
          ;; Set current buffer to output-to
@@ -294,11 +304,11 @@ placed.
              (t ;; Insert as successors.
               (setq klabel (klabel:increment (kcell-view:label))
                     output-level (klabel:level klabel))
-              ;; Move to start of line of next tree since cell insertion will 
occur
-              ;; at point.
+              ;; Move to start of line of next tree since cell insertion
+              ;; will occur at point.
               (goto-char (kotl-mode:tree-end)))))
       (setq max-pos-and-count (kimport:star-entries
-                              import-from output-to klabel output-level 1 0 
total 0)
+                              import-from output-to klabel output-level 1 
count total 0)
            count (cdr max-pos-and-count)))
     (pop-to-buffer output-to)
     (kfile:narrow-to-kcells)
@@ -325,10 +335,15 @@ Import Koutlines with their structure intact.  Import text
 paragraphs as a sequence of same level cells.  The variable,
 `paragraph-start,' is used to determine paragraphs."
   (interactive "FImport from text/koutline buffer/file: \nFInsert cells into 
koutline buffer/file: \nP")
-  (let ((klabel "1") (output-level 1) (count 0) initially-empty-output
-       no-renumber orig-point total)
+  (when (and buffer-file-name (directory-name-p import-from))
+    (setq import-from buffer-file-name))
+  (when (and buffer-file-name (directory-name-p output-to))
+    (setq output-to (concat (file-name-sans-extension buffer-file-name) 
".kotl")))
+  (let ((output-level 1) (klabel "1") (count 0)
+        initially-empty-output no-renumber orig-point total)
     ;; Don't change the order of import-from and output-to inits here.
     (setq import-from (kimport:copy-and-set-buffer import-from)
+         ;; Set current buffer to output-to
          output-to (kimport:initialize output-to t)
          orig-point (point)
          initially-empty-output (zerop (- (point-max) (point-min)))
@@ -341,55 +356,57 @@ paragraphs as a sequence of same level cells.  The 
variable,
       (error "(kimport:text): Import and output buffers may not be the same."))
 
     (set-buffer import-from)
-    (let ((kotl-import (eq major-mode 'kotl-mode))
+    (let ((kotl-import (derived-mode-p 'kotl-mode))
          visible-cells)
       (save-excursion
-       (if initially-empty-output
-           nil
+       (goto-char (point-min))
+       (unless initially-empty-output
          ;; Insert first cell as sibling of current cell.
          (set-buffer output-to)
-         (if children-flag
-             ;; Insert as children.
-             (progn (setq klabel (klabel:child (kcell-view:label))
-                          output-level (klabel:level klabel))
-                    ;; Move to end of this cell since cell insertion will
-                    ;; occur at point.
-                    (goto-char (kcell-view:end)))
-           ;; Insert as successors.
-           (setq klabel (klabel:increment (kcell-view:label))
-                 output-level (klabel:level klabel))
-           ;; Move to start of line of next tree since cell insertion will 
occur
-           ;; at point.
-           (goto-char (kotl-mode:tree-end)))
-         (set-buffer import-from))
-
-       (if kotl-import
-           ;; Importing from a koutline, so handle specially.
-           (progn (kotl-mode:beginning-of-buffer)
-                  ;; Total number of cells.
-                  (setq total (count-matches "[\n\r][\n\r]")
-                        visible-cells (count-matches "\n\n")
-                        count (save-excursion
-                                ;; Incredible non-local exit to ensure that
-                                ;; recursion ends at the right time.
-                                (catch 'end
-                                  (kimport:kcells import-from output-to klabel
-                                                  output-level 1
-                                                  count total)))))
-
-         (outline-show-all)
-         (goto-char (point-min))
-         ;; Total number of paragraphs.
-         (setq total (kimport:count-paragraphs)
-               count (kimport:text-paragraphs import-from output-to klabel
-                                              output-level count total))))
+         (cond (children-flag
+                ;; Insert as children.
+                (setq klabel (klabel:child (kcell-view:label))
+                      output-level (klabel:level klabel))
+                ;; Move to end of this cell since cell insertion will
+                ;; occur at point.
+                (goto-char (kcell-view:end)))
+               ((string-empty-p (kcell-view:contents))
+                ;; This is an unused cell, fill in from here.
+                (setq klabel (kcell-view:label)
+                      output-level (klabel:level klabel))
+                (goto-char (kcell-view:start)))
+               (t ;; Insert as successors.
+                (setq klabel (klabel:increment (kcell-view:label))
+                      output-level (klabel:level klabel))
+                ;; Move to start of line of next tree since cell insertion
+                ;; will occur at point.
+                (goto-char (kotl-mode:tree-end))))))
+
+      (if kotl-import
+         ;; Importing from a koutline, so handle specially.
+         (progn (kotl-mode:beginning-of-buffer)
+                ;; Total number of cells.
+                (setq total (count-matches "[\n\r][\n\r]")
+                      visible-cells (count-matches "\n\n")
+                      count (save-excursion
+                              ;; Incredible non-local exit to ensure that
+                              ;; recursion ends at the right time.
+                              (catch 'end
+                                (kimport:kcells import-from output-to klabel
+                                                output-level 1
+                                                count total)))))
+       (outline-show-all)
+       (goto-char (point-min))
+       ;; Total number of paragraphs.
+       (setq total (kimport:count-paragraphs)
+             count (kimport:text-paragraphs import-from output-to klabel
+                                            output-level count total)))
       (pop-to-buffer output-to)
       (kfile:narrow-to-kcells)
       (unless no-renumber
        (klabel-type:update-labels klabel))
       (goto-char orig-point)
-      (if (kotl-mode:buffer-empty-p)
-         nil
+      (unless (kotl-mode:buffer-empty-p)
        (kotl-mode:to-valid-position))
       (if kotl-import
          (message "Imported %d of %d visible cells from a %d cell outline."
@@ -433,20 +450,27 @@ paragraphs as a sequence of same level cells.  The 
variable,
          (t nil))))
 
 (defun kimport:aug-post-statements (import-from output-to klabel output-level
-                                   import-level count total)
+                                   import-level count total max-pos)
   "Insert post-numbered Augment statements (contents only) from IMPORT-FROM.
 Is inserted in existing OUTPUT-TO.
 
 KLABEL is the label to use for the first imported statement.
 OUTPUT-LEVEL is the level at which to insert the first statement.
-IMPORT-LEVEL is the depth of the current statement in the import file,
-\(initially 1).
+IMPORT-LEVEL is the depth of the current statement in the import
+file, \(initially 1).
 
-COUNT of inserted cells starts at 0.  TOTAL is the total number of statements
-in IMPORT-FROM, used to show a running tally of the imported statements."
+COUNT of inserted cells starts at 0.  TOTAL is the total number
+of statements in IMPORT-FROM, used to show a running tally of the
+imported statements.  MAX-POS is the furthest position searched
+in IMPORT-FROM so far (initially 0).
+
+Return a cons of MAX-POS and COUNT."
   (set-buffer import-from)
-  (let ((cell-end-regexp " +\\([0-9][0-9a-z]*\\)\n\\(\n+\\|\\'\\)")
-       contents start subtree-p end end-contents statement-level
+  (let ((start (point))
+       (cell-end-regexp " +\\([0-9][0-9a-z]*\\)\n\\(\n+\\|\\'\\)")
+       (case-fold-search)
+       max-pos-and-count
+       contents subtree-p end end-contents statement-level
        child-label)
     ;; While find cells at import-level or deeper ...
     (while (and (setq start (point))
@@ -465,23 +489,31 @@ in IMPORT-FROM, used to show a running tally of the 
imported statements."
                            (< statement-level
                               (klabel:level-alpha (match-string 1))))))
       (with-current-buffer output-to
-       ;; Add the cell starting at point.
-       (kview:add-cell klabel output-level contents nil t)
+       (if (and (zerop count) (string-empty-p (kcell-view:contents)))
+           ;; Reuse this initial empty cell in koutline
+           (progn (kview:insert-contents (kcell-view:cell) contents 'no-fill
+                                         (make-string (kcell-view:indent) ?\ ))
+                  (goto-char (kcell-view:end)))
+         ;; Add the cell starting at point.
+         (kview:add-cell klabel output-level contents nil t))
        (if subtree-p (setq child-label (klabel:child klabel)))
        (message "%d of %d statements converted..."
-                (setq count (1+ count)) total)
+                (if (= statement-level 1) (setq count (1+ count)) count)
+                total)
        (setq klabel (klabel:increment klabel)))
       ;;
       ;; Current buffer returns to `import-from' here.
       ;; Handle each sub-level through recursion.
       (when subtree-p
        ;; Subtree exists so insert its cells.
-       (setq count
+       (setq max-pos-and-count
              (kimport:aug-post-statements
               import-from output-to child-label (1+ output-level)
-              (1+ import-level) count total))))
-    (goto-char start))
-  count)
+              (1+ import-level) count total max-pos)
+             max-pos (car max-pos-and-count)
+             count (cdr max-pos-and-count))))
+    (goto-char (setq max-pos (max end max-pos))))
+  (cons max-pos count))
 
 ;;;###autoload
 (defun kimport:copy-and-set-buffer (source)
@@ -592,7 +624,9 @@ IMPORT-LEVEL is the depth of the current cell in the import 
file,
 \(initially 1).
 
 COUNT of inserted cells starts at 0.  TOTAL is the total number of cells
-in IMPORT-FROM, used to show a running tally of the imported cells."
+in IMPORT-FROM, used to show a running tally of the imported cells.
+
+Return COUNT."
   (set-buffer import-from)
   (goto-char (kcell-view:start))
   (let ((again t) contents subtree-p child-label)
@@ -630,8 +664,10 @@ OUTPUT-LEVEL is the level at which to insert the first 
entry.
 IMPORT-LEVEL is the depth of the current entry in the import file,
 \(initially 1).
 
-COUNT of inserted entries starts at 0.  TOTAL is the total number of entries
-in IMPORT-FROM, used to show a running tally of the imported entries.
+COUNT of inserted entries starts at 0.  TOTAL is the total number
+of entries in IMPORT-FROM, used to show a running tally of the
+imported entries.  MAX-POS is the furthest position searched in
+IMPORT-FROM so far (initially 0).
 
 Return a cons of MAX-POS and COUNT."
   (set-buffer import-from)
@@ -655,7 +691,7 @@ Return a cons of MAX-POS and COUNT."
       (setq contents (kimport:unindent-region start (point)))
       (with-current-buffer output-to
        (if (and (zerop count) (string-empty-p (kcell-view:contents)))
-           ;; Reuse this initial empty cell in outline
+           ;; Reuse this initial empty cell in koutline
            (progn (kview:insert-contents (kcell-view:cell) contents 'no-fill
                                          (make-string (kcell-view:indent) ?\ ))
                   (goto-char (kcell-view:end)))
@@ -684,16 +720,18 @@ Return a cons of MAX-POS and COUNT."
   (cons max-pos count))
 
 (defun kimport:text-paragraphs (import-from output-to klabel
-                               output-level _count total)
+                               output-level count total)
   "Insert text paragraphs from IMPORT-FROM into existing OUTPUT-TO.
 First cell is inserted with KLABEL at OUTPUT-LEVEL, as the sibling of the
 previous cell, with the COUNT of inserted paragraphs starting at 0.  TOTAL is
 the total number of paragraphs in IMPORT-FROM, used to show a running tally
 of the imported paragraphs.
 
-The variable, `paragraph-start' is used to determine paragraphs."
+The variable, `paragraph-start' is used to determine paragraphs.
+
+Return COUNT."
   (set-buffer import-from)
-  (let* ((count 0) start end contents)
+  (let* (start end contents)
     ;; Next line is needed when importing into an existing kview.
     (goto-char (point-min))
     ;; Move past blank lines at point.
@@ -707,13 +745,18 @@ The variable, `paragraph-start' is used to determine 
paragraphs."
                    (setq end (goto-char (match-end 0))))
                (/= start end))
       (setq contents (kimport:unindent-region start end))
-      (set-buffer output-to)
-      ;; Add the cell starting at point.
-      (kview:add-cell klabel output-level contents nil t)
-      (setq count (1+ count))
-      (message "%d of %d paragraphs converted..."
-              count total)
-      (setq klabel (klabel:increment klabel))
+      (with-current-buffer output-to
+       (if (and (zerop count) (string-empty-p (kcell-view:contents)))
+           ;; Reuse this initial empty cell in koutline
+           (progn (kview:insert-contents (kcell-view:cell) contents 'no-fill
+                                         (make-string (kcell-view:indent) ?\ ))
+                  (goto-char (kcell-view:end)))
+         ;; Add the cell starting at point.
+         (kview:add-cell klabel output-level contents nil t))
+       (setq count (1+ count))
+       (message "%d of %d paragraphs converted..."
+                count total)
+       (setq klabel (klabel:increment klabel)))
       (set-buffer import-from)
       (goto-char end)
       ;; Move past blank lines separating paragraphs.
diff --git a/kotl/kotl-mode.el b/kotl/kotl-mode.el
index e82d58e618..c7c04b387f 100644
--- a/kotl/kotl-mode.el
+++ b/kotl/kotl-mode.el
@@ -3,7 +3,7 @@
 ;; Author:       Bob Weiner
 ;;
 ;; Orig-Date:    6/30/93
-;; Last-Mod:     16-Oct-22 at 19:29:20 by Mats Lidell
+;; Last-Mod:      6-May-23 at 12:39:55 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
@@ -204,11 +204,10 @@ It provides the following keys:
               (orgtbl-make-binding 'orgtbl-meta-return 106
                                   [(meta return)] "\M-\C-m"))
   (org-defkey orgtbl-mode-map "\C-d"
-              (orgtbl-make-binding 'kotl-mode:delete-char 201
-                                  "\C-d"))
-  (org-defkey orgtbl-mode-map [(shift iso-lefttab)]
-              (orgtbl-make-binding 'org-shifttab 202
-                                  [(shift iso-lefttab)] [backtab] [(shift 
tab)]))
+              (orgtbl-make-binding 'kotl-mode:delete-char 201 "\C-d"))
+  (org-defkey orgtbl-mode-map [S-iso-lefttab]
+              (orgtbl-make-binding 'org-shifttab 107
+                                  [S-iso-lefttab] [backtab] [(shift tab)]))
   (run-hooks 'kotl-mode-hook)
   (add-hook 'change-major-mode-hook #'kotl-mode:show-all nil t))
 
diff --git a/man/hkey-help.txt b/man/hkey-help.txt
index c0adcd11ee..60a6ddd309 100644
--- a/man/hkey-help.txt
+++ b/man/hkey-help.txt
@@ -82,6 +82,7 @@ Hyperbole Key Press/Click in Special Modes
   Treemacs                      Displays item              Displays item
   Dired Sidebar                 Displays item              Displays item
   Emacs Push Button             Activates button           Button help
+  Emacs Regression Test Def     Eval and run test          Edebug and run test
   Thing Begin or End            Mark thing region          Mark & kill thing 
region
   Page Directory Listing        Jumps to page              <- same
   Imenu Programming Identifier  Jumps to in-buffer def     Prompts for id to 
jump to
diff --git a/man/hyperbole.texi b/man/hyperbole.texi
index 4d6b814b29..19275747c9 100644
--- a/man/hyperbole.texi
+++ b/man/hyperbole.texi
@@ -7,7 +7,7 @@
 @c Author:       Bob Weiner
 @c
 @c Orig-Date:     6-Nov-91 at 11:18:03
-@c Last-Mod:     29-Apr-23 at 17:20:22 by Bob Weiner
+@c Last-Mod:      7-May-23 at 18:53:57 by Bob Weiner
 
 @c %**start of header (This is for running Texinfo on a region.)
 @setfilename hyperbole.info
@@ -2125,11 +2125,13 @@ by any number of :, - or = separator characters, 
including none.
 
 @cindex ibtypes, list of
 @cindex implicit button types
-Below is a list of standard implicit button types in the order in which
-Hyperbole tries to match to the types when looking for an implicit
-button; @bkbd{C-h h i t @key{RET}} provides similar information.  See
-the Hyperbole file, @file{hibtypes.el}, for examples of how to define
-implicit button types (they are listed in increasing order of priority).
+Below is a list of standard implicit button types in the order in
+which Hyperbole tries to match to the types when looking for an
+implicit button (decreasing priority order).  @bkbd{C-h h i t
+@key{RET}} provides similar information.  See the Hyperbole file,
+@file{hibtypes.el}, for examples of how to define implicit button
+types (in the file, they are listed in reverse order, increasing in
+priority).
 
 @table @code
 
@@ -2720,12 +2722,19 @@ PATH-style variable, the path at point is displayed; 
empty paths,
 e.g. @file{::} represent the current directory, @file{.}.  Must have at
 least four paths within the variable value for this to work.
 
-
-@findex ibtypes hyperbole-run-tests
+@findex ibtypes hyperbole-run-test-definition
+@cindex edebug a test
+@cindex debugging tests
 @cindex running tests
 @cindex testing
 @cindex ert
 @cindex Emacs Regression Test framework
+@item hyperbole-run-test-definition
+With an Action Key press on the name in the first line of an ert test
+def, evaluate and run the ERT test.  With an Assist Key press instead,
+edebug the test and step through it.
+
+@findex ibtypes hyperbole-run-tests
 @item hyperbole-run-tests
 Recognize buttons of the form @code{<hyperbole-run-tests test-selector>}
 which when activated run Hyperbole tests using the ERT framework.  The
@@ -3721,14 +3730,14 @@ Action or Assist Key action to use when no matching 
context is found.
 
 @cindex minibuffer menus
 @cindex menu item key bindings
-The rest of this section discusses only the
-specialized @dfn{minibuffer menus} which appear in the minibuffer
-window and work with all emacs versions on all display devices.  They
-provide similar capabilities to those of the Hyperbole menubar but
-additionally allow for fast menu item selection via the keyboard or
-mouse.  When used with the keyboard, they provide command access
-similar to key bindings.  In fact, any menu item can be bound to a
-global key sequence.  @xref{Binding Minibuffer Menu Items}.
+The rest of this section discusses only the specialized
+@dfn{minibuffer menus} which appear in the minibuffer window and work
+with all emacs versions on all display devices.  They provide similar
+capabilities to those of the Hyperbole menubar but additionally allow
+for fast menu item selection via the keyboard or mouse.  When used
+with the keyboard, they provide command access similar to key
+bindings.  In fact, any menu item can be bound to a global key
+sequence.  @xref{Binding Minibuffer Menu Items}.
 
 @kindex C-h h
 @cindex enable Hyperbole mode
@@ -3761,13 +3770,19 @@ Hy>  Act Butfile/ Cust/ Doc/ Ebut/ Find/ Gbut/ Hist 
Ibut/ Kotl/ Msg/ Rolo/ Scree
 @kindex M-f
 @kindex Shift-@key{TAB}
 @kindex M-b
-All menu items are selected via the first character of their names (letter
-case does not matter), with presses of the Action Key or by using
-@bkbd{@key{TAB}} or @bkbd{M-f} to move forward an item, @bkbd{Shift-@key{TAB}}
-or @bkbd{M-b} to move backward an item and @bkbd{@key{RET}} to select the
-current item.  A press of the Assist Key on an item displays help for the
-item, including the action that it performs.  "/" at the end of an item name
-indicates that it brings up a submenu.
+A menu item can be selected in a number of ways:
+@itemize @bullet
+@item from the keyboard, by typing the first capitalized character of its name,
+@item with a press of @bkbd{@key{RET}} or the Action Key or Action Mouse Key 
on the name,
+@item by pressing @bkbd{@key{TAB}} or @bkbd{M-f} to move forward an item,
+@item or by pressing @bkbd{Shift-@key{TAB}} or @bkbd{M-b} to move backward an 
item.
+@end itemize
+
+@noindent
+A prefix argument given to one of the movement commands, moves by tht
+number of items within the menu.  A press of the Assist Key on an item
+displays help for the item, including the action that it performs.
+"/" at the end of an item name indicates that it brings up a submenu.
 
 @kindex C-h h C-t
 @kindex C-h h Q
@@ -4802,10 +4817,10 @@ substructure) are promoted and demoted, not individual 
cells.
 @kindex koutliner, @key{TAB}
 @kindex koutliner, M-@key{TAB}
 @kindex koutliner, Shift-@key{TAB}
-@kindex koutliner, M-left
-@kindex koutliner, M-right
-@kindex koutliner, M-Shift-left
-@kindex koutliner, M-Shift-right
+@kindex koutliner, M-<left>
+@kindex koutliner, M-<right>
+@kindex koutliner, M-Shift-<left>
+@kindex koutliner, M-Shift-<right>
 @kindex koutliner, C-c C-,
 @kindex koutliner, C-c C-.
 @kindex koutliner, C-c C->
@@ -4816,9 +4831,9 @@ substructure) are promoted and demoted, not individual 
cells.
 |-----------------------------+----------------------------|
 | Promotion Outside Org Table | Demotion Outside Org Table |
 |-----------------------------+----------------------------|
-| Shift-TAB or M-TAB          | TAB                        |
-| M-left                      | M-right                    |
-| M-Shift-left                | M-Shift-right              |
+| M-TAB or Shift-TAB          | TAB                        |
+| M-<left>                    | M-<right>                  |
+| M-Shift-<left>              | M-Shift-<right>            |
 | C-c C-,                     | C-c C-.                    |
 | C-c C-<                     | C-c C->                    |
 |-----------------------------+----------------------------|
@@ -4826,15 +4841,14 @@ substructure) are promoted and demoted, not individual 
cells.
 
 
 Trees may be demoted or promoted by pressing @key{TAB} or
-@bkbd{M-@key{TAB}} (or @bkbd{@key{SHIFT}-@key{TAB}}) respectively, as
-in most outliners today.  @bkbd{M-0 @key{TAB}} and @bkbd{M-0
-M-@key{TAB}} demote and promote trees and additionally refill each
-cell that is not specially marked to prevent refilling.
-@xref{Filling}.  A positive or negative prefix argument to these
-commands promotes or demotes the tree up to a maximum of the number of
-levels given by the argument.  The outline may not support movement of
-the tree by the number of levels requested, however, in which case the
-maximal possible adjustment is made.
+@bkbd{M-@key{TAB}}.  @bkbd{M-0 @key{TAB}} and @bkbd{M-0 M-@key{TAB}}
+demote and promote trees and additionally refill each cell that is not
+specially marked to prevent refilling.  @xref{Filling}.  A positive or
+negative prefix argument to these commands promotes or demotes the
+tree up to a maximum of the number of levels given by the argument.
+The outline may not support movement of the tree by the number of
+levels requested, however, in which case the maximal possible
+adjustment is made.
 
 @kindex koutliner, M-1 @key{TAB}
 @cindex inserting tabs
@@ -4853,10 +4867,11 @@ Use @bkbd{M-1 @key{TAB}} to toggle the @key{TAB} and
 
 
 @cindex Org tables
-The Koutliner also supports Org Table editing, @pxref{Tables,,, org, the Org
-Mode Manual}, via Org table minor mode.  Use @bkbd{M-x orgtbl-mode @key{RET}}
-to toggle this on and off.  A press of the Action Key on a @code{|} symbol,
-also toggles this minor mode on or off.
+The Koutliner also supports Org Table editing, @pxref{Tables,,, org,
+the Org Mode Manual}, via Org table minor mode.  Use @bkbd{M-x
+orgtbl-mode @key{RET}} to toggle this on and off.  A press of the
+Action Key on a @code{|} symbol, also toggles this minor mode on or
+off.
 
 @cindex outline mode
 @kindex M-0 @key{TAB}
@@ -4865,16 +4880,16 @@ Tree demotion and promotion keys match the defaults in 
Org mode and
 Outline mode, plus some easier to type ones.  The tables below
 summarize which keys work whether inside an Org table or outside.
 
-Note that you must use @bkbd{M-0 @key{TAB}} and @bkbd{M-0 M-@key{TAB}} to
-demote/promote Koutline trees when in a table since @key{TAB} by itself
-moves between fields within a table.
+Note that you must use @bkbd{M-0 @key{TAB}} and @bkbd{M-0 M-@key{TAB}}
+to demote/promote Koutline trees when in a table since @key{TAB} and
+@bkdb{M-@key{TAB}} move between fields within a table.
 
 @example
 @noindent
 |----------------------------+-----------------------------|
 | Promotion Inside Org Table | Demotion Inside Org Table   |
 |----------------------------+-----------------------------|
-| M-0 Shift-TAB or M-0 M-TAB | M-0 TAB                     |
+| M-0 M-TAB                  | M-0 TAB                     |
 | C-c C-,                    | C-c C-.                     |
 | C-c C-<                    | C-c C->                     |
 |----------------------------+-----------------------------|
@@ -4888,9 +4903,9 @@ moves between fields within a table.
 @cindex Action Key, cell argument
 @kindex koutliner, Action Key, cell argument
 Like Org mode, you can move the tree rooted at point past trees rooted
-at the same level with @bkbd{M-down} and before trees with @bkbd{M-up}.
-Give a prefix argument to move past that many other trees.  (A 0 valued
-argument is automatically changed to 1).
+at the same level with @bkbd{M-<down>} and before trees with
+@bkbd{M-<up>}.  Give a prefix argument to move past that many other
+trees.  (A 0 valued argument is automatically changed to 1).
 
 For maximum flexibility in rearranging outlines, there are commands
 that move or copy entire trees anywhere within the outline as
@@ -4908,9 +4923,9 @@ arguments changes each command's behavior from insertion 
at the sibling
 level to insertion at the child level.
 
 @table @asis
-@kitem M-down
+@kitem M-<down>
 Move current tree past prefix arg same level trees.
-@kitem M-up
+@kitem M-<up>
 Move current tree back prefix arg same level trees.
 
 @kitem C-c c
@@ -5815,14 +5830,16 @@ set of commands as the menubar and popup menus, with 
more concise labels.
 @bkbd{C-mouse-3} pops up the mode-specific menu in Emacs.  Experiment with
 the menu or read the following sections explaining commands.
 
-The minibuffer Rolo/ menu offers the following commands:
-
 @cindex Rolo commands
 @cindex HyRolo commands
+@cindex ConsultFind
+@cindex HelmFind
 @findex hyrolo-add
+@findex hyrolo-consult-grep
 @findex hyrolo-display-matches
 @findex hyrolo-edit
 @findex hyrolo-find-file
+@findex hyrolo-helm-org-rifle
 @findex hyrolo-kill
 @findex hyrolo-mail-to
 @findex hyrolo-sort
@@ -5830,14 +5847,19 @@ The minibuffer Rolo/ menu offers the following commands:
 @findex hyrolo-fgrep
 @findex hyrolo-word
 @findex hyrolo-yank
+The minibuffer Rolo/ menu offers the following commands (ConsultFind
+and HelmFind appear only when associated packages are loaded):
+
 @example
 @group
 Menu Item       Command                 Description
 =====================================================================
 Add             hyrolo-add              Adds a hyrolo entry
+ConsultFind     hyrolo-consult-grep     Interactively narrow grep matches
 Display         hyrolo-display-matches  Displays last matches again
 Edit            hyrolo-edit             Edits an existing hyrolo entry
 File            hyrolo-find-file        Edits a @code{hyrolo-file-list} file
+HelmFind        hyrolo-helm-org-rifle   Interactively narrow entry matches
 Info            id-info                 Displays a hyrolo manual entry
 Kill            hyrolo-kill             Deletes a hyrolo entry
 Mail            hyrolo-mail             Mails to an address at point
@@ -9571,8 +9593,8 @@ When in an Org mode context and 
@code{hsys-org-enable-smart-keys} is non-nil:
 
 @cindex Org ID
 @cindex Org link, outside Org
-@vindex org-id
-@vindex org-link-outside-org-mode
+@findex ibtypes org-id
+@findex ibtypes org-link-outside-org-mode
 @noindent
 Org links may be used outside of Org mode buffers.  Such links are
 handled by the separate implicit button type, @code{org-link-outside-org-mode}.
diff --git a/test/kimport-tests.el b/test/kimport-tests.el
index 145e1bc75c..98d07e1df6 100644
--- a/test/kimport-tests.el
+++ b/test/kimport-tests.el
@@ -3,7 +3,7 @@
 ;; Author:       Mats Lidell
 ;;
 ;; Orig-Date:     9-Apr-23 at 23:31:48
-;; Last-Mod:     11-Apr-23 at 00:59:17 by Mats Lidell
+;; Last-Mod:      7-May-23 at 17:11:53 by Bob Weiner
 ;;
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 ;;
@@ -20,9 +20,28 @@
 (require 'kimport)
 (require 'ert)
 
+(ert-deftest kimport--aug-post-outline ()
+  "Import .otl star outline as one cell per entry beginning with one or more 
stars."
+  (let ((file (make-temp-file "hypb" nil ".aug"
+                             (concat "entry1  1\n\nentry1a  1a\n\nentry1b  
1b\n\n"
+                                     "entry2  2\n\nentry3  3\n\nentry3a  
3a\n")))
+        (kotl-file (make-temp-file "hypb" nil ".kotl")))
+    (unwind-protect
+        (progn
+          (find-file file)
+          (kimport:file file kotl-file)
+          (find-file kotl-file)
+          (dolist (v '("entry1" "entry1a" "entry1b" "entry2" "entry3" 
"entry3a"))
+            (should (looking-at-p v))
+           (should (string-suffix-p (kcell-view:label) v))
+           (unless (kotl-mode:last-cell-p)
+              (kotl-mode:next-cell 1)))
+         (should (kotl-mode:last-cell-p)))
+      (delete-file file)
+      (delete-file kotl-file))))
+
 (ert-deftest kimport--text-file ()
-  "Import text file as one cell per paragraph."
-  (skip-unless false) ;; Skip until text file import if fixed
+  "Import .txt text file into a Koutline, as one cell per paragraph."
   (let ((file (make-temp-file "hypb" nil ".txt" "1\n\n2\n\n3\n"))
         (kotl-file (make-temp-file "hypb" nil ".kotl")))
     (unwind-protect
@@ -32,43 +51,53 @@
           (find-file kotl-file)
           (dolist (v '(1 2 3))
             (should (looking-at-p (number-to-string v)))
-            (kotl-mode:forward-cell 1)))
+           (unless (kotl-mode:last-cell-p)
+              (kotl-mode:forward-cell 1)))
+         (should (kotl-mode:last-cell-p)))
       (delete-file file)
       (delete-file kotl-file))))
 
 (ert-deftest kimport--text-file-two-lines-per-paragraph ()
-  "Import text file as one cell per paragraph each two lines."
-  (skip-unless false) ;; Skip until text file import if fixed
-  (let ((file (make-temp-file "hypb" nil ".txt" "1\n2\n\n\n3\n4\n\n5\n6\n"))
+  "Import .txt text file into a Koutline, as one cell per paragraph.
+Each paragraph is two lines."
+  (let ((file (make-temp-file "hypb" nil ".txt"
+                             (concat "par1 line1\npar1 line2\n\n\npar2 line3\n 
par2 line4"
+                                     "\n\n par3 *. line5\n par3 *. line6")))
         (kotl-file (make-temp-file "hypb" nil ".kotl")))
     (unwind-protect
         (progn
           (find-file file)
           (kimport:file file kotl-file)
           (find-file kotl-file)
-          (dolist (v '("1\n.*2" "3\n.*4" "5\n.*6"))
+          (dolist (v '("par1 line1\\s-+par1 line2" "par2 line3\\s-+par2 line4"
+                      "par3 \\*\\. line5\\s-+par3 \\*\\. line6"))
             (should (looking-at-p v))
-            (kotl-mode:forward-cell 1)))
+           (unless (kotl-mode:last-cell-p)
+              (kotl-mode:forward-cell 1)))
+         (should (kotl-mode:last-cell-p)))
       (delete-file file)
       (delete-file kotl-file))))
 
 (ert-deftest kimport--star-outline ()
-  "Import star outline as one cell per star."
-  (let ((file (make-temp-file "hypb" nil ".org" "* 1\n* 2\n* 3\n"))
+  "Import .otl star outline as one cell per entry beginning with one or more 
stars."
+  (let ((file (make-temp-file "hypb" nil ".otl" "* 1\n** 1a\n** 1b\n* 2\n* 
3\n** 3a\n"))
         (kotl-file (make-temp-file "hypb" nil ".kotl")))
     (unwind-protect
         (progn
           (find-file file)
           (kimport:file file kotl-file)
           (find-file kotl-file)
-          (dolist (v '(1 2 3))
-            (should (looking-at-p (number-to-string v)))
-            (kotl-mode:forward-cell 1)))
+          (dolist (v '("1" "1a" "1b" "2" "3" "3a"))
+            (should (looking-at-p v))
+           (should (equal (kcell-view:label) v))
+           (unless (kotl-mode:last-cell-p)
+              (kotl-mode:next-cell 1)))
+         (should (kotl-mode:last-cell-p)))
       (delete-file file)
       (delete-file kotl-file))))
 
 (ert-deftest kimport--star-outline-two-lines-per-star-heading ()
-  "Import text file as one cell per paragraph each two lines."
+  "Import .org star outline as one cell per paragraph, each two lines."
   (let ((file (make-temp-file "hypb" nil ".org" "* 1\n2\n* 3\n4\n* 5\n6\n"))
         (kotl-file (make-temp-file "hypb" nil ".kotl")))
     (unwind-protect
@@ -78,12 +107,14 @@
           (find-file kotl-file)
           (dolist (v '("1\n.*2" "3\n.*4" "5\n.*6"))
             (should (looking-at-p v))
-            (kotl-mode:forward-cell 1)))
+           (unless (kotl-mode:last-cell-p)
+              (kotl-mode:forward-cell 1)))
+         (should (kotl-mode:last-cell-p)))
       (delete-file file)
       (delete-file kotl-file))))
 
 (ert-deftest kimport--star-outline-with-siblings ()
-  "Import star outline as one cell per star."
+  "Import .org star outline as one cell per entry beginning with one or more 
stars."
   (let ((file (make-temp-file "hypb" nil ".org" "* 1\n** 2\n*** 3\n"))
         (kotl-file (make-temp-file "hypb" nil ".kotl")))
     (unwind-protect
@@ -93,8 +124,10 @@
           (find-file kotl-file)
           (dolist (v '(1 2))
             (should (looking-at-p (number-to-string v)))
-            (kotl-mode:next-cell 1))
+           (unless (kotl-mode:last-cell-p)
+              (kotl-mode:next-cell 1)))
           (should (looking-at-p (number-to-string 3)))
+         (should (kotl-mode:last-cell-p))
           (kotl-mode:end-of-buffer)
           (should (= (kcell-view:level) 3)))
       (delete-file file)

Reply via email to