Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

hideshow minor-mode

40 views
Skip to first unread message

Shiyuan

unread,
Oct 14, 2012, 9:40:26 PM10/14/12
to help-gn...@gnu.org
Hi, 
   I want to turn-on the hide-show-minor-mode in a user-defined mymode. But it gives me the error: mymode doesn't support hide show minor mode. I have put  (require 'hideshow) at the beginning of mymode.el, and also 
(hs-minor-mode 1) in the body of the definition of the major mode, and after that 
I put (add-to-list 'hs-special-modes-alist '(mymode "{" "}" "/[*/]" nil nil)) in mymode.el. 

What else I should do to utilize the hs-minor-mode in mymode? Thanks. 


Michael Heerdegen

unread,
Oct 15, 2012, 2:04:34 PM10/15/12
to help-gn...@gnu.org
Enabling `hs-minor-mode' tests if `comment-start' and `comment-end' are
bound to something non-nil and fails otherwise. This happens even
before `hs-special-modes-alist' is handled. IMHO this doesn't make much
sense. FWIW, your minor-mode must bind `comment-start' and
`comment-end'.

If your mode doesn't have comments at all, you can bind these to a
regexp that always fails matching - like "\\=[^[:ascii:][:nonascii:]]".

Does that help?


Michael.

Shiyuan

unread,
Oct 15, 2012, 7:30:09 PM10/15/12
to help-gn...@gnu.org
Yes, that solves the problem. Now, I can turn on hs-minor-mode. 
But actually the block in my major mode is defined by tags, not by braces/parentheses, like,  
[begin]
   This is the block.
   This is the block.
[end]

accord to the commentary in the hideshow.el file, we can define the BEGIN and the END of the block by regex, this is what I did, 

 (add-to-list 'hs-special-modes-alist '(mymode "\\[begin]" "\\[end]" "#" nil nil))

However, it doesn't work. Anything else I need to do? or is there other packages allow me to fold the source where the blocks are defined in this way?  Thanks. 

Shiyuan 

On Mon, Oct 15, 2012 at 1:04 PM, Michael Heerdegen <michael_...@web.de> wrote:

Michael Heerdegen

unread,
Oct 15, 2012, 9:03:57 PM10/15/12
to help-gn...@gnu.org
Shiyuan <gshy...@gmail.com> writes:

> Yes, that solves the problem. Now, I can turn on hs-minor-mode.
>
> But actually the block in my major mode is defined by tags, not by
> braces/parentheses, like,
> [begin]
> This is the block.
> This is the block.
> [end]
>
> accord to the commentary in the hideshow.el file, we can define the
> BEGIN and the END of the block by regex, this is what I did,
>
> (add-to-list 'hs-special-modes-alist '(mymode "\\[begin]" "\\[end]"
> "#" nil nil))

Yes, that's not wrong.

> However, it doesn't work. Anything else I need to do?

I'm afraid you'll need to specify a FORWARD-SEXP-FUNC element in your
`hs-special-modes-alist' entry, since the default `forward-sexp'
function won't work for your mode.

This function must accept one argument ARG and implement moving over ARG
balanced blocks.

If you don't have something like that yet - I tried the following:

--8<---------------cut here---------------start------------->8---
(defun mymode-forward-sexp-func (arg)
(dotimes (_ arg)
(let ((counter 0))
(catch 'done
(while t
(search-forward-regexp "\\[begin]\\|\\[end]")
(setq counter (+ counter (if (looking-back "\\[begin]") 1 -1)))
(when (= counter 0) (throw 'done t)))))))
--8<---------------cut here---------------end--------------->8---

It doesn't check for comments, dunno what else I forgot. But,
if I then use

(add-to-list 'hs-special-modes-alist '(mymode "\\[begin]" "\\[end]"
"#" my-mode-forward-sexp-func))

folding worked for me in a test buffer using your syntax.

> or is there other packages allow me to fold the source where the
> blocks are defined in this way?

Fundamentally, hideshow is fine for that. It's just the setup that
isn't trivial. No doubt, there is room for improvement.


Regards,

Michael.


Shiyuan

unread,
Oct 16, 2012, 12:20:56 AM10/16/12
to help-gn...@gnu.org
Michael, 
Thanks for the detailed reply. However, it doesn't work for me. I guess I make a mistake somewhere. Here is mymode.el: 
On Mon, Oct 15, 2012 at 8:03 PM, Michael Heerdegen <michael_...@web.de> wrote:
Shiyuan <gshy...@gmail.com> writes:

> Yes, that solves the problem. Now, I can turn on hs-minor-mode.
>
> But actually the block in my major mode is defined by tags, not by
> braces/parentheses, like,
> [begin]
> This is the block.
> This is the block.
> [end]
>
> accord to the commentary in the hideshow.el file, we can define the
> BEGIN and the END of the block by regex, this is what I did,
>
> (add-to-list 'hs-special-modes-alist '(mymode "\\[begin]" "\\[end]"
> "#" nil nil))

Yes, that's not wrong.
> However, it doesn't work. Anything else I need to do?

I'm afraid you'll need to specify a FORWARD-SEXP-FUNC element in your
`hs-special-modes-alist' entry, since the default `forward-sexp'
function won't work for your mode.

This function must accept one argument ARG and implement moving over ARG
balanced blocks.

If you don't have something like that yet - I tried the following:

--8<---------------cut here---------------start------------->8---
(defun mymode-forward-sexp-func (arg)
  (dotimes (_ arg)
    (let ((counter 0))
      (catch 'done
        (while t
          (search-forward-regexp "\\[begin]\\|\\[end]")
          (setq counter (+ counter (if (looking-back "\\[begin]") 1 -1)))
          (when (= counter 0) (throw 'done t)))))))
--8<---------------cut here---------------end--------------->8---

It doesn't check for comments, dunno what else I forgot.  But,
if I then use
(add-to-list 'hs-special-modes-alist '(mymode "\\[begin]" "\\[end]"
"#" my-mode-forward-sexp-func))

folding worked for me in a test buffer using your syntax.
> or is there other packages allow me to fold the source where the
> blocks are defined in this way?

Michael Heerdegen

unread,
Oct 16, 2012, 1:17:44 AM10/16/12
to help-gn...@gnu.org
Hi again,

> Michael,
> Thanks for the detailed reply. However, it doesn't work for me. I
> guess I make a mistake somewhere. Here is mymode.el:
>
> http://paste.lisp.org/display/132611

Yes, there are two little errors.

First, you register your mode in `hs-special-modes-alist' after you
enable hs-minor-mode. That's too late, because hideshow then has
already initialized its stuff. Also, adding to `hs-special-modes-alist'
has to be done only once, and not every time mymode is enabled.

Second, you quoted mymode-forward-sexp-func in your quoted list:

| '(mymode "\\[begin]" "\\[end]" "#" 'mymode-forward-sexp-func nil))
^

That's not needed, remember, the quote before a list already prevents
evaluation of its members (you want to specify a symbol).

So, this should do the trick:

--8<---------------cut here---------------start------------->8---
(require 'hideshow)

(defun mymode-forward-sexp-func (arg)
"move over ARG balanced blocks; This is needed by hs-minor-mode"
(dotimes (number arg)
(let ((counter 0))
(catch 'done
(while t
(search-forward-regexp "\\[begin]\\|\\[end]")
(setq counter (+ counter (if (looking-back "\\[begin]") 1 -1)))
(when (= counter 0) (throw 'done t)))))))

(add-to-list 'hs-special-modes-alist '(mymode "\\[begin]" "\\[end]" "#" mymode-forward-sexp-func))

(define-derived-mode mymode fundamental-mode
"mymode is a major mode for fun."
(setq mode-name "mymode")
(setq comment-start "#")
(setq comment-end "")
(hs-minor-mode 1))
--8<---------------cut here---------------end--------------->8---

Of course, that's all just for playing. If mymode was a major-mode
really to be used, you would leave it up to the user to call
`hs-minor-mode' e.g. in `mymode-hook', and not call it in the mode
definition.


Michael.

Shiyuan

unread,
Oct 16, 2012, 10:40:40 AM10/16/12
to help-gn...@gnu.org
Michael, 
That works. Thank you very much for guiding me into the world of Lisp.

Shiyuan  

On Tue, Oct 16, 2012 at 12:17 AM, Michael Heerdegen <michael_...@web.de> wrote:
Hi again,


> Michael,
> Thanks for the detailed reply. However, it doesn't work for me. I
> guess I make a mistake somewhere. Here is mymode.el:
>
> http://paste.lisp.org/display/132611

Yes, there are two little errors.

First, you register your mode in `hs-special-modes-alist' after you
enable hs-minor-mode.  That's too late, because hideshow then has
already initialized its stuff.  Also, adding to `hs-special-modes-alist'
has to be done only once, and not every time mymode is enabled.

Second, you quoted mymode-forward-sexp-func in your quoted list:

| '(mymode "\\[begin]" "\\[end]" "#"  'mymode-forward-sexp-func nil))
                                      ^

That's not needed, remember, the quote before a list already prevents
evaluation of its members (you want to specify a symbol).

So, this should do the trick:

--8<---------------cut here---------------start------------->8---
(require 'hideshow)

(defun mymode-forward-sexp-func (arg)
  "move over ARG balanced blocks; This is needed by hs-minor-mode"
  (dotimes (number arg)

    (let ((counter 0))
      (catch 'done
        (while t
          (search-forward-regexp "\\[begin]\\|\\[end]")
          (setq counter (+ counter (if (looking-back "\\[begin]") 1 -1)))
          (when (= counter 0) (throw 'done t)))))))

Michael Heerdegen

unread,
Oct 16, 2012, 2:09:15 PM10/16/12
to help-gn...@gnu.org
Shiyuan <gshy...@gmail.com> writes:

> That works.

Fine.

Maybe also have a look at folding.el, if you don't yet know it:

http://www.emacswiki.org/emacs/FoldingMode

It uses explicit markers, but therefore works out of the box in any
mode.


Regards,

Michael.
0 new messages