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

67099Re: Does b:undo_ftplugin actually work?

Expand Messages
  • Bram Moolenaar
    Nov 15, 2012
    • 0 Attachment
      Christian Brabandt wrote:

      > On Do, 27 Sep 2012, Gary Johnson wrote:
      >
      > > On 2012-09-27, ZyX wrote:
      > > > пятница, 28 сентября 2012 г., 8:04:05 UTC+4 пользователь Gary Johnson написал:
      > > > > I was working on some code that set b:undo_ftplugin, but it didn't
      > > > > have any effect when I set a new filetype. I copied
      > > > > $VIMRUNTIME/ftplugin.vim to ~/.vim and instrumented the section that
      > > > > is supposed to execute b:undo_ftplugin.
      > > > >
      > > > > func! s:LoadFTPlugin()
      > > > > echo "In s:LoadFTPlugin()" | sleep 2
      > > > > echo "b:undo_ftplugin is" b:undo_ftplugin | sleep 2
      > > > You should've put this line after the next one (or, better, remove
      > > > it as absense of the next message will indicate absence of
      > > > b:undo_ftplugin definition). And use ":echom", not ":echo |
      > > > sleep", then all messages will be seen when you do ":messages"
      > > > > if exists("b:undo_ftplugin")
      > > > > echo "b:undo_ftplugin exists" | sleep 2
      > > > > exe b:undo_ftplugin
      > > > > unlet! b:undo_ftplugin b:did_ftplugin
      > > > > endif
      > > > >
      > > > > Whenever I open a new file for which Vim can detect the filetype, or
      > > > > :edit some file, I always get the following errors.
      > > > b:undo_ftplugin is defined in filetype plugins. What else do you
      > > > expect? When opening new file and doing :edit buffer scope is
      > > > clean and filetype plugins are loaded by s:LoadFTPlugin function
      > > > *after* you test for b:undo_ftplugin. You should have used "set
      > > > filetype=new_filetype" on *existing* buffer to trigger desired
      > > > behavior.
      > > >
      > > > > Error detected while processing function <SNR>5_LoadFTPlugin:
      > > > > line 2:
      > > > > E121: Undefined variable: b:undo_ftplugin
      > > > > E15: Invalid expression: b:undo_ftplugin | sleep 2
      > > > >
      > > > > That is even after I execute
      > > > >
      > > > > :echo b:undo_ftplugin
      > > > >
      > > > > and verify that it is set correctly according to the new filetype.
      > > > Don't use :edit. It wipes the buffer.
      > > >
      > > > > It seems that b:undo_ftplugin does not exist in the environment in
      > > > > which s:LoadFTPlugin() is executed. Does setting b:undo_ftplugin as
      > > > > most current ftplugin scripts do actually do anything?
      > > > They do. Use "set filetype=new_filetype".
      > >
      > > Thanks for the reply, but I see that I didn't explain the problem
      > > very well. Also, some of my experiments created new buffers instead
      > > of replacing the contents of existing buffers with new filetypes, so
      > > I wasn't replicating the actual problem conditions.
      > >
      > > Let me try again.
      > >
      > > The actual problem is that I would like to set 'indentexpr' for
      > > buffers with no 'filetype' so that I get indenting behavior that I
      > > think might be useful when just opening Vim and typing notes. To
      > > that end I put the following in my ~/.vimrc.
      > >
      > > au BufWinEnter * if &ft == "" || &ft == "text"
      > > \ | setlocal indentexpr=indent(prevnonblank(v:lnum-1))
      > > \ | setlocal indentkeys-=o
      > > \ | let b:undo_ftplugin = "setl inde< indk<"
      > > \ | endif
      > >
      > > When I start vim and execute
      > >
      > > :echo b:undo_ftplugin
      > >
      > > I see
      > >
      > > setl inde< indk<
      > >
      > > as expected. Further, ":ls" shows
      > >
      > > 1 %a "[No Name]" line 1
      > >
      > > Now, if I open a C file, I expect to have 'indentexpr' empty, either
      > > because the C file is opened in a new buffer or because the C file
      > > was opened in the same buffer and the b:undo_ftplugin was executed.
      > > However, after executing
      > >
      > > :e foo.c
      > > :set indentexpr?
      > >
      > > I see
      > >
      > > indentexpr=indent(prevnonblank(v:lnum-1))
      > >
      > > and ":ls" shows
      > >
      > > 1 %a "foo.c" line 1
      > >
      > > I did take your advice about using echom and instrumented
      > > ftplugin.vim differently and verified that when it was executed by
      > > the 'filetype' change to "c", b:undo_ftplugin did not exist.
      > >
      > > If ":edit wipes the buffer" as you say, so that b:undo_ftplugin is
      > > deleted, then shouldn't that wiping reset the values of any local
      > > options?
      > >
      > > I'm just looking for a way to reset those local options when I edit
      > > a new file, b:undo_ftplugin seemed to be the way to do it, but it
      > > doesn't seem to do anything useful.
      > >
      > > Not using :edit is not a solution. For example, if I start vim
      > > and use ":MRU" to open a recently-used C file, I wind up with
      > > 'indentexpr' set as above, which wrongly indents C.
      >
      > Hi Gary,
      >
      > Looks like the initial buffer isn't correctly freed.
      > Try this patch: which at least also gets rid of the buffer local
      > options, when loading another buffer:
      > diff --git a/src/buffer.c b/src/buffer.c
      > --- a/src/buffer.c
      > +++ b/src/buffer.c
      > @@ -1702,6 +1702,12 @@
      > #endif
      > /* buf->b_nwindows = 0; why was this here? */
      > free_buffer_stuff(buf, FALSE); /* delete local variables et al. */
      > + /* can't set TRUE in free_buffer_stuff(), this would destroy the wininfo stuff,
      > + * so freeing the buffer options here afterwards manually */
      > + free_buf_options(buf, TRUE);
      > +#ifdef FEAT_SPELL
      > + ga_clear(&buf->b_s.b_langp);
      > +#endif
      > #ifdef FEAT_KEYMAP
      > /* need to reload lmaps and set b:keymap_name */
      > curbuf->b_kmap_state |= KEYMAP_INIT;
      >
      > Although, this doesn't solve the problem, that the b:undo_ftplugin
      > option isn't executed on BufUnload event. Possibly we need a global
      > BufUnLoad event, that takes care of this, e.g. something like this:
      >
      > " Make sure, the b:undo_ftplugin is also executed deleting the buffer
      > BufUnload * if exists("b:undo_ftplugin") | exe b:undo_ftplugin | endif
      >
      > But I am not sure, where to put this script. Perhaps also put this into
      > ftplugin.vim?

      I finally had time to look into this patch. It breaks the tests in a
      nasty way. Thus this is not the right solution. Instead of freeing the
      options they should be initialized to the global values.
      Perhaps setting buf->b_p_initialized to FALSE works?

      --
      The technology involved in making anything invisible is so infinitely
      complex that nine hundred and ninety-nine billion, nine hundred and
      ninety-nine million, nine hundred and ninety-nine thousand, nine hundred
      and ninety-nine times out of a trillion it is much simpler and more
      effective just to take the thing away and do without it.
      -- Douglas Adams, "The Hitchhiker's Guide to the Galaxy"

      /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
      /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
      \\\ an exciting new programming language -- http://www.Zimbu.org ///
      \\\ help me help AIDS victims -- http://ICCF-Holland.org ///

      --
      You received this message from the "vim_dev" maillist.
      Do not top-post! Type your reply below the text you are replying to.
      For more information, visit http://www.vim.org/maillist.php
    • Show all 23 messages in this topic