Loading ...
Sorry, an error occurred while loading the content.
 

How can I preserve old filetype?

Expand Messages
  • Ron Aaron
    Hi all! I m using ftplugin scripts to get special behavior, scripts, etc. loaded for particular files. Specifically, I have a line like: vim: ft=specialty
    Message 1 of 5 , Apr 3, 2001
      Hi all!

      I'm using ftplugin scripts to get special behavior, scripts, etc. loaded for
      particular files. Specifically, I have a line like:

      vim: ft=specialty ft=c :

      in a C file to load the scripts in 'ftplugin/specialty.vim' when I edit that
      file (specifically).

      The question is, is there a way within my ftplugin script to get the old value
      of '&ft', so I can automatically restore it to its prior value?

      In other words, the ft script is a way to accomplish very specific setup on
      specific files, where Autocommands will not work or would be cumbersome. I
      don't really want to change the filetype of the file, just do something
      special to it.

      Ideas? '&ft' is already set to the new type when my script is loaded :-(

      --
      Ron Aaron Moss Bay Engineering
      425-649-8817 Precision Crafted Software
      http://www.mossbayeng.com/~ron/ronsresume.html

      "If I am not for myself, who will be for me?
      If I am only for myself, who am I?
      And if not now, when?"
      R' Hillel, Avot 1:13
    • Paul Moore
      ... I don t think you can do this. You re abusing the filetype system pretty seriously here, so I think you re on your own... (I didn t even realise that
      Message 2 of 5 , Apr 3, 2001
        On Tue, 3 Apr 2001 10:58:05 -0700, you wrote:

        >Hi all!
        >
        >I'm using ftplugin scripts to get special behavior, scripts, etc. loaded for
        >particular files. Specifically, I have a line like:
        >
        > vim: ft=specialty ft=c :
        >
        >in a C file to load the scripts in 'ftplugin/specialty.vim' when I edit that
        >file (specifically).
        >
        >The question is, is there a way within my ftplugin script to get the old value
        >of '&ft', so I can automatically restore it to its prior value?

        I don't think you can do this. You're abusing the filetype system pretty
        seriously here, so I think you're on your own... (I didn't even realise that
        setting ft twice like this would work).

        As an alternative, how about writing your own "behaviour" function. The
        following seems like the sort of thing. It looks for lines of the form

        [text][space]behaviour:[space]word word ...:

        within 'modelines' of the start or end of the file, and executes any files in
        a "behaviour" subdirectory of $VIMRUNTIME for each of the words in the line
        (it uses the same algorithm as for filetypes - run any or all of
        behaviour/word.vim, behaviour/word_*.vim and behaviour/word/*.vim).

        So your example would become

        vim: set ft=c: behaviour: specialty:

        That was fun to do! For now, it's in my _vimrc, but I'll probably make it into
        a proper plugin.

        Paul


        --- Code attached here to be included in _vimrc, or made into a plugin.

        " Just being clever - check lines within 'modelines' of the
        " end, just like "real" modelines
        function CheckBehaviour(n)
        let i = 1
        let end = line('$')
        while i <= a:n && i <= end
        echo 'doing line' i
        call CheckBehaviourLine(getline(i))
        let i = i + 1
        endwhile
        let i = end
        let finish = end - a:n
        if finish <= 0
        return
        endif
        if finish < a:n
        let finish = a:n
        endif
        while i > finish
        echo 'doing line' i
        call CheckBehaviourLine(getline(i))
        let i = i - 1
        endwhile
        endfunction

        " This function just does a match and splits the result into words.
        " String processing in Vim is hard!!! (Silly, isn't it?)
        function CheckBehaviourLine(line)
        " Look for the required pattern. Note the use of \zs and \ze to pick
        " out the part of the line we are interested in
        let res = matchstr(a:line, '\<behaviour:\s\+\zs.*\ze:')
        if res == ""
        return
        endif
        " Trim whitespace
        let res = substitute(res, '^\s*', '', '')
        let res = substitute(res, '\s*$', '', '')
        " Split off words
        while res != ""
        let word = substitute(res, '\s.*$', '', '')
        let res = substitute(res, '^\S*\s*', '', '')
        " Use the same behaviour as for filetype plugins
        " (see $VIMRUNTIME/ftplugin.vim)
        exec "runtime! behaviour/" . word . ".vim" .
        \ " behaviour/" . word . "_*.vim" .
        \ " behaviour/" . word . "/*.vim"
        endwhile
        endfunction

        au BufReadPost * call CheckBehaviour(&modelines)
      • Ron Aaron
        ... modelines as it appears -- you can set as many options, as many times, as you like. ... Very clever! But this means I have to call that function for every
        Message 3 of 5 , Apr 3, 2001
          Paul Moore <gustav@...> writes:
          >On Tue, 3 Apr 2001 10:58:05 -0700, you wrote:
          >
          >I don't think you can do this. You're abusing the filetype system pretty
          >seriously here

          :-) ... but it works! The reason is that vim just processes each option in
          modelines as it appears -- you can set as many options, as many times, as you
          like.

          >As an alternative, how about writing your own "behaviour" function. The
          >following seems like the sort of thing. It looks for lines of the form

          Very clever! But this means I have to call that function for every file I
          open, when the whole point is that I only want 'special' behaviour for a
          particular file or two.

          Ron
        • Benji Fisher
          Paul Moore wrote: [snip] ... Wouldn t it be easier to use :global? let n = (a:n
          Message 4 of 5 , Apr 3, 2001
            Paul Moore wrote:
            [snip]

            > As an alternative, how about writing your own "behaviour" function. The
            > following seems like the sort of thing. It looks for lines of the form
            >
            > [text][space]behaviour:[space]word word ...:
            >
            > within 'modelines' of the start or end of the file, and executes any files in
            > a "behaviour" subdirectory of $VIMRUNTIME for each of the words in the line
            > (it uses the same algorithm as for filetypes - run any or all of
            > behaviour/word.vim, behaviour/word_*.vim and behaviour/word/*.vim).
            >
            > So your example would become
            >
            > vim: set ft=c: behaviour: specialty
            >

            > That was fun to do! For now, it's in my _vimrc, but I'll probably make it into
            > a proper plugin.
            >
            > Paul
            >
            >
            > --- Code attached here to be included in _vimrc, or made into a plugin.
            >
            > " Just being clever - check lines within 'modelines' of the
            > " end, just like "real" modelines
            > function CheckBehaviour(n)
            > let i = 1
            > let end = line('$')
            > while i <= a:n && i <= end
            > echo 'doing line' i
            > call CheckBehaviourLine(getline(i))
            > let i = i + 1
            > endwhile
            > let i = end
            > let finish = end - a:n
            > if finish <= 0
            > return
            > endif
            > if finish < a:n
            > let finish = a:n
            > endif
            > while i > finish
            > echo 'doing line' i
            > call CheckBehaviourLine(getline(i))
            > let i = i - 1
            > endwhile
            > endfunction

            Wouldn't it be easier to use :global?

            let n = (a:n < line("$") ? a:n : line("$"))
            execute "1," . n . "g/^/call CheckBehaviorLine(getline('.'))"
            execute (line("$")-n+1) . ",$g/^/call CheckBehaviorLine(getline('.'))"

            (untested) You could probably speed things up by using a more interesting
            pattern after "g/". I think my version and yours both have the problem
            that a modeline can be executed twice (in a short file) if it is near both
            the beginning and the end.

            > " This function just does a match and splits the result into words.
            > " String processing in Vim is hard!!! (Silly, isn't it?)
            > function CheckBehaviourLine(line)
            > " Look for the required pattern. Note the use of \zs and \ze to pick
            > " out the part of the line we are interested in
            > let res = matchstr(a:line, '\<behaviour:\s\+\zs.*\ze:')
            > if res == ""
            > return
            > endif

            You do not really need this test.

            > " Trim whitespace
            > let res = substitute(res, '^\s*', '', '')
            > let res = substitute(res, '\s*$', '', '')
            > " Split off words
            > while res != ""
            > let word = substitute(res, '\s.*$', '', '')
            > let res = substitute(res, '^\S*\s*', '', '')
            > " Use the same behaviour as for filetype plugins
            > " (see $VIMRUNTIME/ftplugin.vim)
            > exec "runtime! behaviour/" . word . ".vim" .
            > \ " behaviour/" . word . "_*.vim" .
            > \ " behaviour/" . word . "/*.vim"
            > endwhile
            > endfunction
            >
            > au BufReadPost * call CheckBehaviour(&modelines)

            --Benji Fisher
          • Moore, Paul
            From: Benji Fisher [mailto:benji@e-math.AMS.org] ... That s a good idea. And yes, by including the string we re looking for in the g// command will speed it
            Message 5 of 5 , Apr 4, 2001
              From: Benji Fisher [mailto:benji@...]
              > Wouldn't it be easier to use :global?
              >
              > let n = (a:n < line("$") ? a:n : line("$"))
              > execute "1," . n . "g/^/call CheckBehaviorLine(getline('.'))"
              > execute (line("$")-n+1) . ",$g/^/call CheckBehaviorLine(getline('.'))"
              >
              > (untested) You could probably speed things up by using a
              > more interesting pattern after "g/". I think my version and
              > yours both have the problem that a modeline can be executed
              > twice (in a short file) if it is near both the beginning and
              > the end.

              That's a good idea. And yes, by including the string we're looking for in
              the g// command will speed it up. But while your version (as it stands -
              it's not difficult to fix) does run the line twice in short files, mine
              doesn't. I know it doesn't, because it did, and then I fixed it :-)

              > > if res == ""
              > > return
              > > endif
              >
              > You do not really need this test.

              True. It was there before I thought of substitute() for the word splitting.
              My previous code needed it...

              Paul.
            Your message has been successfully submitted and would be delivered to recipients shortly.