Setting shiftwidth in html (with embedded javascript) pages

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Setting shiftwidth in html (with embedded javascript) pages

David Fishburn

Vim 6.3.75  WinXP

I was wondering if it was possible to dynamically change the shiftwidth
while editing an HTML documement.

While I am editing HTML tags, I want the default of 2.

But if I am in the middle of a <script> ... </script> section, I want the
shiftwidth = 4.

I am not sure what to check for in this case, to trigger it.

TIA,
Dave

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Setting shiftwidth in html (with embedded javascript) pages

Eric Arnold
I didn't find a simple way to do this.

You could remap shift width related commands, i.e. >> <<  ^t ^d <tab>
to first call a function that checks the surrounding context, but I
think the right way is probably to fiddle with "indentkeys" and
"indentexpr", and you might want to create a version of the
"indent/html.vim to feed to "indentexpr"



--- David Fishburn <[hidden email]> wrote:

>
> Vim 6.3.75  WinXP
>
> I was wondering if it was possible to dynamically change the shiftwidth
> while editing an HTML documement.
>
> While I am editing HTML tags, I want the default of 2.
>
> But if I am in the middle of a <script> ... </script> section, I want the
> shiftwidth = 4.
>
> I am not sure what to check for in this case, to trigger it.
>
> TIA,
> Dave
>
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Setting shiftwidth in html (with embedded javascript) pages

Gary Johnson
In reply to this post by David Fishburn
On 2005-06-03, David Fishburn <[hidden email]> wrote:

> Vim 6.3.75  WinXP
>
> I was wondering if it was possible to dynamically change the shiftwidth
> while editing an HTML documement.
>
> While I am editing HTML tags, I want the default of 2.
>
> But if I am in the middle of a <script> ... </script> section, I want the
> shiftwidth = 4.
>
> I am not sure what to check for in this case, to trigger it.

You could use a CursorHold autocommand to check the current cursor
context and set shiftwidth accordingly.  One way to determine the
context would be to search backwards for <script> and </script> and
verify that the first match, if any, is <script>.  Another way might  
be to use a syntax command to transparently "highlight" the
<script>/</script> region and then test the highlighting in effect
at the cursor location.  I can help you with the former, but I don't
know enough about syntax highlighting even to know whether the
latter is possible.

HTH,
Gary

--
Gary Johnson                 | Agilent Technologies
[hidden email]     | Wireless Division
                             | Spokane, Washington, USA
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Setting shiftwidth in html (with embedded javascript) pages

Eric Arnold

It is possible to check the highlighting at a cursor position, see the help
entries for

    hlID()
    synIDattr()
    synIDtrans()
    searchpair()

there are some examples which get you pretty close.

Given the effort, though, it's probably better spent attacking the
problem at the source:  the   indentexpr   and   indent/xxx.vim
process.

I think this is close to what you want.  Make a copy of
        vim[your-release-num]/indent/html.vim

change these lines in function   HtmlIndentGet(v:lnum)   which is
what "indentexpr" is set to by default for ".html" file types.

    " [-- special handling for <javascript>: use cindent --]
    let js = '<script.*type\s*=\s*.*java'
    if   0 < searchpair(js, '', '</script>', 'nWb')
    \ || 0 < searchpair(js, '', '</script>', 'nW')
        " we're inside javascript
        if getline(lnum) !~ js && getline(a:lnum) != '</script>'
                let s:save_sw=&sw
                set sw=4
                let l:ret = cindent(a:lnum)
                let &sw=s:save_sw
            return  l:ret
        endif
    endif

When I tried this, it didn't act exactly as I expected, but the "=" command
indented by 4, and adding {} braces worked correctly, but I think the above
code might be matching more than it should when looking for <script> pairs,
so you might have to adjust it some if it starts changing shiftwidth for
other areas you didn't want.


Put the new version of "html.vim" in you ~/.vim/indent or ~/vimfiles/indent
or where ever your personal Vim directory is.  It seemed to pick it
up automatically for me, though I'm wondering if "b:did_indent" could
be a problem between the original "html.vim" script and the new one.
I'm always getting bitten by the question of whether these files are
executed as with "runtime"  or  "runtime!"  (take the first instance
found, or the last).

Alternatively, you could just make your own   HtmlIndentGet(v:lnum)
function, and override the original by sourcing it explicitly.  Or
make a   My_HtmlIndentGet(v:lnum)   which calls   HtmlIndentGet(v:lnum)
and returns it's own value when it detects a <script> pair.
This is probably a better solution which would allow you to use
future versions of "indent/html.vim".






--- Gary Johnson <[hidden email]> wrote:

> On 2005-06-03, David Fishburn <[hidden email]> wrote:
> > Vim 6.3.75  WinXP
> >
> > I was wondering if it was possible to dynamically change the shiftwidth
> > while editing an HTML documement.
> >
> > While I am editing HTML tags, I want the default of 2.
> >
> > But if I am in the middle of a <script> ... </script> section, I want the
> > shiftwidth = 4.
> >
> > I am not sure what to check for in this case, to trigger it.
>
> You could use a CursorHold autocommand to check the current cursor
> context and set shiftwidth accordingly.  One way to determine the
> context would be to search backwards for <script> and </script> and
> verify that the first match, if any, is <script>.  Another way might  
> be to use a syntax command to transparently "highlight" the
> <script>/</script> region and then test the highlighting in effect
> at the cursor location.  I can help you with the former, but I don't
> know enough about syntax highlighting even to know whether the
> latter is possible.
>
> HTH,
> Gary
>
> --
> Gary Johnson                 | Agilent Technologies
> [hidden email]     | Wireless Division
>                              | Spokane, Washington, USA
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Setting shiftwidth in html (with embedded javascript) pages

A.J.Mechelynck
Eric Arnold wrote:
[...]
> Put the new version of "html.vim" in you ~/.vim/indent or ~/vimfiles/indent
> or where ever your personal Vim directory is.  It seemed to pick it
> up automatically for me, though I'm wondering if "b:did_indent" could
> be a problem between the original "html.vim" script and the new one.
> I'm always getting bitten by the question of whether these files are
> executed as with "runtime"  or  "runtime!"  (take the first instance
> found, or the last).
[...]

IIUC, they are executed as with ":runtime!". That's where b:did_indent
comes into play. Both your modified plugin and the standard one should
begin with something akin to

if exists("b:did_indent") && b:did_intent
        finish
endif
let b:did_indent = 1

With such code, only the first of them (the one in ~/.vim/indent/ or in
~/vimfiles/indent) gets to run more than its two first lines.

Alternatively, you could extract just the function and define a new
version of it it with

function! HtmlIndentGet()
...
endfunction

in a script named ~/.vim/after/indent/html.vim or
~/vimfiles/after/indent/html.vim, which would not test for b:did_indent
and would not duplicate whatever it doesn't need to change from the
standard plugin. In that case the default plugin
($VIMRUNTIME/indent/html.vim) would be run, and
~/.vim/after/indent/html.vim would be run immediately afterwards,
modifying the definition of the function.


In a nutshell, here's in which order the directories in 'vimruntime' are
searched, and what they are for:

$HOME/.vim/ or $HOME/vimfiles/
user-specific full-fledged scripts which either replace a script of the
same name in one of the two following directory trees, or provide a
capability which is missing (e.g., a new filetype, a new language, ...)

$VIM/vimfiles/
system-wide full-fledged scripts which either replace bodily a script of
the same name under $VIMRUNTIME, or provide a capability for which there
is no script under $VIMRUNTIME

$VIMRUNTIME/
scripts which come with the distribution (and may be silently
overwritten by the next upgrade, so don't modify them in place, it's in
your best interest).

$VIM/vimfiles/after/
small system-wide modifications to any of the above

$HOME/.vim/after/ or $HOME/vimfiles/after/
small user-specific modifications to any of the above


Windows uses $HOME/vimfiles (or, in Dos parlance, %HOME%\vimfiles). Unix
uses $HOME/.vim . They both use $VIM/vimfiles (not $VIM/.vim, even under
Unix). For other systems, see ":help 'runtimepath'".


Best regards,
Tony.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Setting shiftwidth in html (with embedded javascript) pages

Eric Arnold

So, if I have:

        $VIM/vim63/indent/html.vim
        $VIM/vimfiles/indent/html.vim
        $HOME/vimfiles/indent/html.vim

they are *all* executed, in the order:

        $HOME/vimfiles/indent/html.vim
        $VIM/vimfiles/indent/html.vim
        $VIM/vim63/indent/html.vim

Is there a preferred way to tweak core file functionality
and maintain those tweaks through releases?  Do people always
provide a full replacement for the file they override, or ...

I was thinking I ought to be able to do something like have

        $HOME/vimfiles/indent/html.vim

consist only of a single function,

         function! My_HtmlIndentGet(lnum)
                 ...test if in <script> pair block
                 ... if so, change sw to 4
                 call HtmlIndentGet( a:lnum )
                 ... reset sw
                 return value from HtmlIndentGet( a:lnum )
         endfunction

and notably, no   b:did_indent   at the top so it will fall through
to the core file.

This avoids having to rewrite my own version of "html.vim" for each
new release.  However, it also means I have a problem with
indentexpr   which will be set to    HtmlIndentGet()   instead
of   My_HtmlIndentGet()   when the core file executes after my version.

I guess I could do my own search through   runtimepath   and execute
all the other versions, and then set    indentexpr   in my version,
and then set   b:did_indent   so that the value for   indentexpr   sticks.

Anyway, working through this scenario made me wonder if I was missing
an intended methodology.



--- "A. J. Mechelynck" <[hidden email]> wrote:

> Eric Arnold wrote:
> [...]
> > Put the new version of "html.vim" in you ~/.vim/indent or ~/vimfiles/indent
> > or where ever your personal Vim directory is.  It seemed to pick it
> > up automatically for me, though I'm wondering if "b:did_indent" could
> > be a problem between the original "html.vim" script and the new one.
> > I'm always getting bitten by the question of whether these files are
> > executed as with "runtime"  or  "runtime!"  (take the first instance
> > found, or the last).
> [...]
>
> IIUC, they are executed as with ":runtime!". That's where b:did_indent
> comes into play. Both your modified plugin and the standard one should
> begin with something akin to
>
> if exists("b:did_indent") && b:did_intent
> finish
> endif
> let b:did_indent = 1
>
> With such code, only the first of them (the one in ~/.vim/indent/ or in
> ~/vimfiles/indent) gets to run more than its two first lines.
>
> Alternatively, you could extract just the function and define a new
> version of it it with
>
> function! HtmlIndentGet()
> ...
> endfunction
>
> in a script named ~/.vim/after/indent/html.vim or
> ~/vimfiles/after/indent/html.vim, which would not test for b:did_indent
> and would not duplicate whatever it doesn't need to change from the
> standard plugin. In that case the default plugin
> ($VIMRUNTIME/indent/html.vim) would be run, and
> ~/.vim/after/indent/html.vim would be run immediately afterwards,
> modifying the definition of the function.
>
>
> In a nutshell, here's in which order the directories in 'vimruntime' are
> searched, and what they are for:
>
> $HOME/.vim/ or $HOME/vimfiles/
> user-specific full-fledged scripts which either replace a script of the
> same name in one of the two following directory trees, or provide a
> capability which is missing (e.g., a new filetype, a new language, ...)
>
> $VIM/vimfiles/
> system-wide full-fledged scripts which either replace bodily a script of
> the same name under $VIMRUNTIME, or provide a capability for which there
> is no script under $VIMRUNTIME
>
> $VIMRUNTIME/
> scripts which come with the distribution (and may be silently
> overwritten by the next upgrade, so don't modify them in place, it's in
> your best interest).
>
> $VIM/vimfiles/after/
> small system-wide modifications to any of the above
>
> $HOME/.vim/after/ or $HOME/vimfiles/after/
> small user-specific modifications to any of the above
>
>
> Windows uses $HOME/vimfiles (or, in Dos parlance, %HOME%\vimfiles). Unix
> uses $HOME/.vim . They both use $VIM/vimfiles (not $VIM/.vim, even under
> Unix). For other systems, see ":help 'runtimepath'".
>
>
> Best regards,
> Tony.
>
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Setting shiftwidth in html (with embedded javascript) pages

A.J.Mechelynck
Eric Arnold wrote:

> So, if I have:
>
> $VIM/vim63/indent/html.vim
> $VIM/vimfiles/indent/html.vim
> $HOME/vimfiles/indent/html.vim
>
> they are *all* executed, in the order:
>
> $HOME/vimfiles/indent/html.vim
> $VIM/vimfiles/indent/html.vim
> $VIM/vim63/indent/html.vim
>
> Is there a preferred way to tweak core file functionality
> and maintain those tweaks through releases?  Do people always
> provide a full replacement for the file they override, or ...

No they don't; see farther down.

>
> I was thinking I ought to be able to do something like have
>
> $HOME/vimfiles/indent/html.vim
>
> consist only of a single function,
>
> function! My_HtmlIndentGet(lnum)
> ...test if in <script> pair block
> ... if so, change sw to 4
> call HtmlIndentGet( a:lnum )
> ... reset sw
> return value from HtmlIndentGet( a:lnum )
> endfunction
>
> and notably, no   b:did_indent   at the top so it will fall through
> to the core file.

That would work, *except* that you would name that file
$HOME/vimfiles/after/indent/html.vim and not
$HOME/vimfiles/indent/html.vim (see ":help after-directory"). This way,
your small file would be executed after the one in $VIMRUNTIME, and it
would replace the function defined in the default script by another
function.

>
> This avoids having to rewrite my own version of "html.vim" for each
> new release.  However, it also means I have a problem with
> indentexpr   which will be set to    HtmlIndentGet()   instead
> of   My_HtmlIndentGet()   when the core file executes after my version.

Since, by placing it in an "after-directory", your script is executed
after the default one, it can set 'indentexpr' to something else than
the default.

>
> I guess I could do my own search through   runtimepath   and execute
> all the other versions, and then set    indentexpr   in my version,
> and then set   b:did_indent   so that the value for   indentexpr   sticks.

That's not needed, see below.

>
> Anyway, working through this scenario made me wonder if I was missing
> an intended methodology.
[...]

Yes, you did: see ":help after-directory".


Best regards,
Tony.

Loading...