0

I am trying to implement the following behavior: when hideshow minor mode is enabled and user start editing file (or alternatively pressed spacebar or enter key): automatically execute hs-show-all or just disable hs-minor-mode, - is there is a way to do that?

Idea is to use hideshow mode as some sort of navigation shortcut: on certain key execute hs-hide-all, then use arrow keys to navigate to desired portion of the document and automatically show all document when editing started. I will be happy to use other packages if similar functionality could be archived by other means. Thanks,

1 Answer 1

1

You could define the following function

(defun hs-show-all-on-editing ()
  (unless (member last-command-event '(up down left right))
    (hs-show-all)
    (remove-hook 'pre-command-hook #'hs-show-all-on-editing)))

and then advise hs-show-all to add this function to the pre-command-hook:

(advice-add 'hs-hide-all :after (lambda () (add-hook 'pre-command-hook #'hs-show-all-on-editing nil t)))

The logic in the function calls hs-show-all only when some other key than an arrow key is pressed, but you could add more 'keys' (that should not trigger hs-show-all) to the list.

Of course, this only works if you use hs-hide-all to hide the blocks (but you can always advise more functions).

If you'd like to use SPC or RET to trigger hs-show-all without inserting, then you could conditionally remove the inserted char using the post-command-hook:

(defun hs-show-delete-backward-char ()
  (when (memq last-command-event '(13 32))
    (delete-backward-char 1)
    (remove-hook 'post-command-hook #'hs-show-all-on-editing)))

(advice-add 'hs-hide-all :after (lambda () (add-hook 'post-command-hook #'hs-show-delete-backward-char nil t)))

Be aware that you should call hs-hide-all via a shortcut, because if you call it via M-x (which requires pressing RET) then this hook function will run directly after running hs-hide-all.

This is the most pragmatic solution. A better solution might be implemented by defining a minor mode, but this would require fully rewriting this answer, and as long as thing work fine, they work fine.

Although this idea does not seem bad at all, personally I am mostly using imenu (with helm/counsel/consult, i.e. SPC j i in Spacemacs) and 'evil marks' for quick navigation.

5
  • Fantastic, this is exactly what i was looking for @dalanicolai ! - I have tried this solution but getting the following error: condition-case: Invalid function: (hs-show-all-on-editing t), - thoughts?
    – WorkPerNap
    Nov 8, 2022 at 19:08
  • Also, thank you for imenu tip, - i was not aware of this functionality, looking it up now...
    – WorkPerNap
    Nov 8, 2022 at 19:09
  • ok, looks like using (advice-add 'hs-hide-all :after '(lambda () (add-hook 'pre-command-hook #'hs-show-all-on-editing))) fix the error. However there is one nuance: pressing space/enter still edit the text. So i tried to insert undo into hs-show-all-on-editing but this does not seems to work...
    – WorkPerNap
    Nov 8, 2022 at 19:26
  • Ah sorry, yeah the advice-add definitely expects a function, don't know why I forgot to make it a lambda (lambda's are self-quoting b.t.w.). I thought using SPC or RET for executing hs-show-all was an 'alternative'. Anyway, I have 'extended' the answer. Nov 9, 2022 at 0:30
  • Awesome - thank you very much @dalanicolai - this was very useful and educational! I have tried to replace (delete-backward-char 1) with (undo) but oddly enough while working this produced message Error in post-command-hook (hs-show-delete-backward-char): (user-error "No further undo information") - any idea why? Thanks,
    – WorkPerNap
    Nov 9, 2022 at 22:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.