help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Strings as opening/closing delimiters in the syntax table?


From: Tim X
Subject: Re: Strings as opening/closing delimiters in the syntax table?
Date: Wed, 08 Dec 2010 15:33:43 -0000
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux)

Philip <phil.ganchev@gmail.com> writes:

> On Oct 27, 2:38 am, Tim X <t...@nospam.dev.null> wrote:
>> Philip <phil.ganc...@gmail.com> writes:
>> > I want to make emacs match "if" to "then" in sh mode like it does "("
>> > and ")" in other modes. I read the wiki page about syntax tables
>> > (http://www.emacswiki.org/emacs/EmacsSyntaxTable) but it only talks
>> > about opening and closing delimiter *characters*. Have I
>> > misunderstood, or have I found something that emacs cannot do? [ghasp!]
>>
>> There is nothing emacs cannot do!
>
> Glad to know.
>
>> However, I'm not clear exactly what you want. When you say you want
>> emacs to match if to then in sh mode, do you mean work like match-paren
>> does i.e. show the match and maybe highlight if you have a then without
>> a matching then etc or do you mean you want more 'electric' behavior so
>> that when you type if, emacs automatically puts in 'then' and leaves you
>> at a pint where you can enter the condition or are you talking about
>> some sort of indentation which lines up if and then statements or ....?
>
> OK, I understand now that those are implemented separately, which is
> unfortunate. For a start, I want highlighting of matching if-then,
> then I want go-to-match-construct similar to what I have for goto-
> match-paren, and eventually I was going to consider auto-inserting he
> matching construct. The function goto-match-paren that I have uses the
> syntax table (I did not write it myself):
>
> (defun goto-match-paren (arg)
>   (interactive "p")
>   (cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1))
>         ((looking-at "\\s\)") (forward-char 1) (backward-list 1))
>         ;(t (self-insert-command (or arg 1)))
>         (t)))
>
>

OK, I think I understand a bit better. 

What you want is certainly possible, but it is a fair it of work and I'm
not sure if the effort will be worth the rewards (this is probably why
it has not been done). 

Paren matching is valuable because it is common to nest bracketed
statements and it can be hard to ensure ending brackets are really
matching the opening bracket you intended. While 'if' blocks can be
nested, you don't tend to get the level of nesting depth that makes
paren matching useful. 

I suspect what you really want is matching of 'if' and 'fi' (assuming
bash/sh scripts - maybe endif or similar for another shell dialect). The
reason I say this is that matching of 'if' and 'then' is not going to be
very beneficial because its not marking the beginning/end of a block. There
is always a 'then' following an 'if' and you cannot nest them, but you
can have nested if/fi blocks. 

Doing this will be a little more complex than paren matching because the
paren matching code can take advatnage of existing sexp navigation.
However, it is still possible. 

One way to do it would be to simple search backwards after you enter a
'fi'. However, you need to track nesting - its not as simple as just
looking back for the previous 'if' as this could belong to a nested
block that alaready has a 'fi'. A stack could be useful for this, though
management can become complex when you consider what needs to be done
when you edit your code. I'd be tempted to take a totally different
approach.

Assuming the main concern is ensure you have correct block format i.e.
paired 'if' and 'fi'. I'd be tempted to use something similar to other
modes, like cperl or C etc. Have a template expansion (possibly using
tempo or skeleton), which is attached to an abbrev for if. When you type
if, the abbrev would expand into a basic if....fi block. Essentially,
you would make 'if' an 'electric' operation. While not exactly what you
want, it would likely achieve most of what you want with a lot less
effort or performance impact. Have a look at a mode like cperl to see
how this can be done. 

I'd start with a simple template and bind that to a key so that you can
easily insert an if/fi template. Then, once you have that working how
you want, look into abbrev mode and use that template aa an expansion
for 'if'. 

HTH

Tim


-- 
tcross (at) rapttech dot com dot au


reply via email to

[Prev in Thread] Current Thread [Next in Thread]