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

Proposal for defining mappings in plugins and other scripts

Expand Messages
  • Bram Moolenaar
    Here is a proposal for how to deal with mappings in settings and plugin files. Actually, this can be used in any Vim script. The basic problem is that when
    Message 1 of 18 , Oct 2, 2000
    • 0 Attachment
      Here is a proposal for how to deal with mappings in settings and plugin files.
      Actually, this can be used in any Vim script.

      The basic problem is that when using several Vim scripts from different
      sources, the key sequences that trigger functions in each script may conflict.
      In one script ",q" may be mapped to a function that quotes text, in another
      script ",q" may have a totally different meaning.

      It would be possible to have each script define a unique (long) name for each
      function it provides. The user then needs to add mappings for each of them to
      actually use the functions. Example:
      :map ,q \ABCdoit
      :map ,r \XYZdoit
      That works, but requires the user to define mappings before he can start using
      the functionality in the script. That's not very nice for plugin, which
      should work right after dropping it in the plugin directory.

      The solution I propose is to support both mechanisms: Define a mapping in the
      script unless the user defined one already. It could work like this:

      if !hasmapto('\MSQuote') && exists('mapleader')
      :exe "map " . mapleader . "q \MSQuote"
      endif
      :map \MSQuote do-the-stuff

      The trick here is to detect that a mapping _to_ "\MSQuote" already exists. If
      it does exist, the user apparently defined his own choice of keys to use this
      functionality. If it doesn't exist, the script will define its own default,
      starting with "mapleader". For example, if "mapleader" has the value of ",",
      this will result in the following command:

      map ,q \MSQuote

      Using the backslash as the standard character for the start of the long name
      seems like a good idea (it doesn't start a Vim command).

      The start of the long name should be unique. Perhaps we can have some kind of
      registration at VUR (Vim Users' Repository) for this? In the above example I
      used "MS" for Mail Settings, this isn't very unique.

      Previously I used "localmapchar" for mappings in a settings file. I would
      like to rename this to "localmapleader". This makes clear that the value
      isn't necessarely one character. The use of these variables then becomes:

      mapleader in plugins and other scripts that are used for
      all buffers.
      localmapleader in settings files and other scripts that are
      used locally for one buffer.

      The value could be the same for both. I would use ",". By using two
      different values it's less likely to run into conflicts between plugins and
      settings scripts.


      Here is a bigger example. The $VIMRUNTIME/macros/explorer.vim script can be
      used as a plugin. It is mostly triggered from autocommands, when editing a
      directory. That doesn't need to be changed. But there are two mappings:

      nmap ,e :call ExplInitiate(0)<cr> " open explorer in this window
      nmap ,s :call ExplInitiate(1)<cr> " open explorer in new window

      For the above proposed mechanism, this should be changed to:

      if !hasmapto('\ExplExe', "n") && exists('mapleader')
      :exe "nmap " . mapleader . "e \ExplExe"
      endif
      nmap \ExplExe :call ExplInitiate(0)<cr>

      if !hasmapto('\ExplSplit', "n") && exists('mapleader')
      :exe "nmap " . mapleader . "s \ExplSplit"
      endif
      nmap \ExplSplit :call ExplInitiate(1)<cr>

      With the old script you could easily run into the problem that ,e and ,s were
      also defined by another script. You would have to edit explorer.vim to avoid
      this (and repeat that each time you get a new version of the script).

      With the new method you can still get the default ,e and ,s mappings, if your
      "mapleader" is a comma. If you have the problem that these mappings are
      already being used, you can define your own mappings to \ExplExe and
      \ExplSplit, without the need to change explorer.vim. For example, you could
      add this to your .vimrc:

      :nmap ,x \ExplExe
      :nmap ,S \ExplSplit


      Any objections against this method? Is there a better solution?

      One question: Suppose you don't need to use some function that the script
      provides, how to make a script not install a map for that function?


      An alternative would be to set a variable for each mapping that you did
      yourself, or a variable for all mappings. The script would then look like:

      if !exists("skip_Expl_maps")
      if !exists("skip_ExplExe_map") && exists('mapleader')
      :exe "nmap " . mapleader . "e \ExplExe"
      endif
      if !exists("skip_ExplSplit_map") && exists('mapleader')
      :exe "nmap " . mapleader . "s \ExplSplit"
      endif
      endif

      The disadvantage is that the user needs to set those variables, and they
      clutter the list of variables. There could be quite a large number of
      variables you need to set this way.
      The advantage is that no hasmapto() function has to be implemented.

      --
      hundred-and-one symptoms of being an internet addict:
      123. You ask the car dealer to install an extra cigarette lighter
      on your new car to power your notebook.

      /// Bram Moolenaar Bram@... http://www.moolenaar.net \\\
      \\\ Vim: http://www.vim.org ICCF Holland: http://iccf-holland.org ///
    • Johannes Zellner
      ... as already pointed out earlier: I d propose to use the script name as leader for all functions / variables of the script. e.g.: script name: explorer.vim
      Message 2 of 18 , Oct 2, 2000
      • 0 Attachment
        On Mon, Oct 02, 2000 at 02:05:55PM +0200, Bram Moolenaar wrote:

        > The start of the long name should be unique. Perhaps we can have some kind of
        > registration at VUR (Vim Users' Repository) for this? In the above example I
        > used "MS" for Mail Settings, this isn't very unique.

        as already pointed out earlier: I'd propose to use the script
        name as leader for all functions / variables of the script.
        e.g.:
        script name: explorer.vim
        --> functions:
        ExplorerFunction1()
        ExplorerFunction2()
        --> global variables:
        g:explorer_var1
        g:explorer_var2
        --> long mappings
        \explorer_mapping1
        \explorer_mapping2

        in fact, vim could do this itself. Python does something similar
        when loading modules:

        import math

        will result in the following naming of symbols

        math.cos()
        math.sin()
        ...

        --
        Johannes
      • hitched97@hotpop.com
        ... How about a module/endmodule pair? module takes one argument giving the name of the module ( explorer ), and all definitions in between it and the
        Message 3 of 18 , Oct 2, 2000
        • 0 Attachment
          At 06:52 AM 10/2/00, Johannes Zellner wrote:
          >as already pointed out earlier: I'd propose to use the script
          >name as leader for all functions / variables of the script.
          >e.g.:
          >script name: explorer.vim
          > --> functions:
          > ExplorerFunction1()
          > ExplorerFunction2()
          > --> global variables:
          > g:explorer_var1
          > g:explorer_var2
          > --> long mappings
          > \explorer_mapping1
          > \explorer_mapping2
          >
          >in fact, vim could do this itself. Python does something similar
          >when loading modules:
          >
          > import math
          >
          >will result in the following naming of symbols
          >
          > math.cos()
          > math.sin()


          How about a module/endmodule pair? module takes one argument giving
          the name of the module ("explorer"), and all definitions in between it and
          the matching endmodule are prepended with the module name.

          --
          Steve
        • Bram Moolenaar
          ... This has been mentioned before. The main problem is that we will have to define how the module name is used in mappings, function names, etc. This
          Message 4 of 18 , Oct 3, 2000
          • 0 Attachment
            Steve Wall wrote:

            > At 06:52 AM 10/2/00, Johannes Zellner wrote:
            > >as already pointed out earlier: I'd propose to use the script
            > >name as leader for all functions / variables of the script.
            > >e.g.:
            > >script name: explorer.vim
            > > --> functions:
            > > ExplorerFunction1()
            > > ExplorerFunction2()
            > > --> global variables:
            > > g:explorer_var1
            > > g:explorer_var2
            > > --> long mappings
            > > \explorer_mapping1
            > > \explorer_mapping2
            > >
            > >in fact, vim could do this itself. Python does something similar
            > >when loading modules:
            > >
            > > import math
            > >
            > >will result in the following naming of symbols
            > >
            > > math.cos()
            > > math.sin()
            >
            > How about a module/endmodule pair? module takes one argument giving
            > the name of the module ("explorer"), and all definitions in between it and
            > the matching endmodule are prepended with the module name.

            This has been mentioned before. The main problem is that we will have to
            define how the module name is used in mappings, function names, etc. This
            actually makes it more complicated. There will be an extra mechanism you need
            to learn.

            Starting each function, variable, etc. with the name of the file is simple and
            straightforward. And we don't need to implement anything in Vim to make it
            work. And you can still have some variables with another name (e.g., if you
            want to check if some other module was loaded).

            The main advantage of a module kind of thing is when the module would be
            loaded automatically. But we never came up with a simple way to do that. The
            new plugin mechanism should work well for most people. The few power-users
            that don't want to load all functions when starting can use the FuncUndefined
            autocommand event to automatically load their functions. I don't think
            "normal" users need to load functions on demand. I don't do this myself, and
            don't notice much startup delay.

            --
            hundred-and-one symptoms of being an internet addict:
            149. You find your computer sexier than your girlfriend

            /// Bram Moolenaar Bram@... http://www.moolenaar.net \\\
            \\\ Vim: http://www.vim.org ICCF Holland: http://iccf-holland.org ///
          • Zdenek Sekera
            ... [...] ... I agree, I alos like Johannes suggested mechanism, though, inevitably, the name may sometimes get long. I d consider that a minor nit. ... I
            Message 5 of 18 , Oct 3, 2000
            • 0 Attachment
              Bram Moolenaar wrote:
              >
              [...]
              > Starting each function, variable, etc. with the name of the file is simple and
              > straightforward. And we don't need to implement anything in Vim to make it
              > work. And you can still have some variables with another name (e.g., if you
              > want to check if some other module was loaded).
              >

              I agree, I alos like Johannes' suggested mechanism, though, inevitably,
              the
              name may sometimes get long. I'd consider that a minor nit.

              > The main advantage of a module kind of thing is when the module would be
              > loaded automatically. But we never came up with a simple way to do that. The
              > new plugin mechanism should work well for most people. The few power-users
              > that don't want to load all functions when starting can use the FuncUndefined
              > autocommand event to automatically load their functions. I don't think
              > "normal" users need to load functions on demand. I don't do this myself, and
              > don't notice much startup delay.

              I guess that depends on how much startup has to load in. Speaking for
              myself,
              I really like the FuncUndef mechanism and use it a lot. What is missing,
              though,
              IMHO (or rather: what I'd like to have in addition) is FuncFinish which
              would
              delf a function after it had finished execution. I have some functions
              that
              I need but very rarely so I would really like they get deleted when they
              finish,
              they'll be reloaded by FuncUndef next time if needed. I don't much like
              unneeded
              things in the memory, call it 'programmers hygiene', no religious wars
              (like 'mem' is
              big, cheap,...these days), please...:-).
              Maybe you still remember my 'dynamic functions patch' for 5.4 (or
              around) that was
              automatically unloading functions not used within a certain time. Today
              I think this
              is too complicated but the FuncFinish should be useful.

              ---Zdenek
            • raf
              ... i might be alone in this but i don t like mappings that require multiple keystrokes. i prefer to map a single meta/ctrl/function key. so i wouldn t be able
              Message 6 of 18 , Oct 8, 2000
              • 0 Attachment
                Bram Moolenaar wrote:

                > Here is a proposal for how to deal with mappings in settings and plugin files.
                > Actually, this can be used in any Vim script.
                >
                > The basic problem is that when using several Vim scripts from different
                > sources, the key sequences that trigger functions in each script may conflict.
                > In one script ",q" may be mapped to a function that quotes text, in another
                > script ",q" may have a totally different meaning.
                >
                > It would be possible to have each script define a unique (long) name for each
                > function it provides. The user then needs to add mappings for each of them to
                > actually use the functions. Example:
                > :map ,q \ABCdoit
                > :map ,r \XYZdoit
                > That works, but requires the user to define mappings before he can start using
                > the functionality in the script. That's not very nice for plugin, which
                > should work right after dropping it in the plugin directory.
                >
                > [...]
                >
                > An alternative would be to set a variable for each mapping that you did
                > yourself, or a variable for all mappings. The script would then look like:
                >
                > if !exists("skip_Expl_maps")
                > if !exists("skip_ExplExe_map") && exists('mapleader')
                > :exe "nmap " . mapleader . "e \ExplExe"
                > endif
                > if !exists("skip_ExplSplit_map") && exists('mapleader')
                > :exe "nmap " . mapleader . "s \ExplSplit"
                > endif
                > endif
                >
                > The disadvantage is that the user needs to set those variables, and they
                > clutter the list of variables. There could be quite a large number of
                > variables you need to set this way.
                > The advantage is that no hasmapto() function has to be implemented.

                i might be alone in this but i don't like mappings that require multiple
                keystrokes. i prefer to map a single meta/ctrl/function key. so i wouldn't
                be able to use the mapleader option.

                an alternative that i'd prefer is to have maptemplate rather than mapleader
                so i could have: set maptemplate="<Meta-%>" and have the mapping i want
                automatically generated.

                another point: what if a plugin is only intended for use when editing
                a certain filetype? can it automatically create its mappings only when
                the right type of file is loaded and then unmap them when the file is
                unloaded? are there any plans for this sort of behaviour? i suppose the
                plugin just needs its own autocommands.

                raf
              • Bram Moolenaar
                ... That s OK, in the proposed system you will have to add your own set of mappings before loading the plugin. You can then map your single keystroke to the
                Message 7 of 18 , Oct 9, 2000
                • 0 Attachment
                  Raf wrote:

                  > i might be alone in this but i don't like mappings that require multiple
                  > keystrokes. i prefer to map a single meta/ctrl/function key. so i wouldn't
                  > be able to use the mapleader option.

                  That's OK, in the proposed system you will have to add your own set of
                  mappings before loading the plugin. You can then map your single keystroke to
                  the long sequence that triggers the function in the plugin.

                  > an alternative that i'd prefer is to have maptemplate rather than mapleader
                  > so i could have: set maptemplate="<Meta-%>" and have the mapping i want
                  > automatically generated.

                  I don't see how the plugin can automatically generate a key based on a
                  maptemplate like this...

                  > another point: what if a plugin is only intended for use when editing
                  > a certain filetype? can it automatically create its mappings only when
                  > the right type of file is loaded and then unmap them when the file is
                  > unloaded? are there any plans for this sort of behaviour? i suppose the
                  > plugin just needs its own autocommands.

                  Yes, the plugin can use an autocommand that is triggered on a FileType event,
                  and then install buffer-local mappings. If you want your own mappings
                  instead, you will have to do the same (make sure your autocommands are
                  executed before the ones from the plugin).

                  --
                  hundred-and-one symptoms of being an internet addict:
                  211. Your husband leaves you...taking the computer with him and you
                  call him crying, and beg him to bring the computer back.

                  /// Bram Moolenaar Bram@... http://www.moolenaar.net \\\
                  \\\ Vim: http://www.vim.org ICCF Holland: http://iccf-holland.org ///
                • Dr. Charles E. Campbell
                  ... Hello! Decided to drop in my two cents (one cent?). Anyway, here s some comments, in no particular order: 1. Won t there be a problem with ambiguity given
                  Message 8 of 18 , Oct 10, 2000
                  • 0 Attachment
                    Thus saith Bram Moolenaar:
                    > That's OK, in the proposed system you will have to add your own set of
                    > mappings before loading the plugin. You can then map your single keystroke to
                    > the long sequence that triggers the function in the plugin.
                    ---------------------------------------------------------------------

                    Hello!

                    Decided to drop in my two cents (one cent?). Anyway,
                    here's some comments, in no particular order:


                    1. Won't there be a problem with ambiguity given multiple
                    long mapleaders from various plugins? ex. \Abc vs \Ad

                    Potential solution: \Abc\ \Ad\
                    requires change to ambiguity-detector; a mapleader's first
                    character must/automatically-will be duplicated at the end,
                    not used internally, hence s/w can easily pick up the
                    beginning/end of the mapping introducer.

                    Ex. \Abc\ has two maps, ,x and ,y : \Abc\,x \Abc\,y
                    \Ad\ has two maps, ,x and ,y : \Ad\,x \Ad\,y

                    Those who want short maps can map a meta- or alt- character or
                    whatever to the long form.


                    2. As shown in Note 1, two plugins could easily be re-using
                    the same maps (both \Abc\ and \Ad\ have ,x mapped).
                    Thus some priority scheme could be in place, where duplicate
                    short-form map sequences get kept: .vimrc normally
                    gets top priority, plugins/scripts get lowest.k

                    However, while executing something from a specific plugin,
                    that plugin's maps should get priority.


                    3. map <buffer> -- this serves a good purpose, but: normally
                    one would want to make the global interface obvious, and so
                    might exporting be better?

                    ex. map <export> ,x ,y ,z
                    which would do whatever is needed to make long forms of
                    the maps available, as well. It could also change the
                    <Map>s into whatever, too.

                    and, by default, all maps in a plugin are local-only.


                    Flak jacket now donned,
                    Chip Campbell

                    --
                    Charles E Campbell, Jr, PhD _ __ __
                    Goddard Space Flight Center / /_/\_\_/ /
                    cec@... /_/ \/_//_/
                    PGP public key: http://www.erols.com/astronaut/pgp.html/
                  • Bram Moolenaar
                    ... There will always be a problem with the ambiguety of the long version of the mapping. I thought of a way to automatically generate one (e.g., add a number
                    Message 9 of 18 , Oct 10, 2000
                    • 0 Attachment
                      Charles Campbell wrote:

                      > 1. Won't there be a problem with ambiguity given multiple
                      > long mapleaders from various plugins? ex. \Abc vs \Ad

                      There will always be a problem with the ambiguety of the long version of the
                      mapping. I thought of a way to automatically generate one (e.g., add a number
                      to make it unique), but the result will be unpredictable. This makes it
                      impossible to add your own maps to this long name.

                      I'm hoping most people will write a plugin with a good name, e.g.:
                      "goodname.vim". Then using the name in the long mapping: "\Goodname" will
                      make it pretty unique. People can see at the VUR what names already exist and
                      avoid duplications.

                      Anyway, \Abc and \Ad are not ambiguous. \Abd and \Ab are. But when appending
                      the word for the functionality, the ambiguety is gone again: \AbdFunc and
                      \AbFunc.

                      > Potential solution: \Abc\ \Ad\
                      > requires change to ambiguity-detector; a mapleader's first
                      > character must/automatically-will be duplicated at the end,
                      > not used internally, hence s/w can easily pick up the
                      > beginning/end of the mapping introducer.
                      >
                      > Ex. \Abc\ has two maps, ,x and ,y : \Abc\,x \Abc\,y
                      > \Ad\ has two maps, ,x and ,y : \Ad\,x \Ad\,y
                      >
                      > Those who want short maps can map a meta- or alt- character or
                      > whatever to the long form.

                      I'm afraid I don't see what this solves. If two plugins both use <Map>x, then
                      the user will have to define his own mapping for at least one of them. Then
                      he can use the long name, I don't see the need to add <Map>x to the long
                      name...

                      > 2. As shown in Note 1, two plugins could easily be re-using
                      > the same maps (both \Abc\ and \Ad\ have ,x mapped).
                      > Thus some priority scheme could be in place, where duplicate
                      > short-form map sequences get kept: .vimrc normally
                      > gets top priority, plugins/scripts get lowest.k
                      >
                      > However, while executing something from a specific plugin,
                      > that plugin's maps should get priority.

                      If there are two plugins that map the same key sequence, the last one wins. I
                      don't really see much use in trying to fix the ambiguety, it's the user that
                      has to say how he wants this solved. The docs for each plugin will say that
                      ,x will do something, and that won't work (whatever solution we come up with).

                      Perhaps the plugin should first check that the mappings it wants to add are
                      not already taken, and give a clear error message in case they are. E.g.:

                      if mapcheck("<Map>x", "nv") != ""
                      echo "Hey, you have a problem!"
                      finish
                      endif

                      Well, OK, so I said _clear_ error message... :-)

                      > 3. map <buffer> -- this serves a good purpose, but: normally
                      > one would want to make the global interface obvious, and so
                      > might exporting be better?
                      >
                      > ex. map <export> ,x ,y ,z
                      > which would do whatever is needed to make long forms of
                      > the maps available, as well. It could also change the
                      > <Map>s into whatever, too.

                      Sorry, I don't understand what you want ":map <export>" to do and what problem
                      it solves.

                      > and, by default, all maps in a plugin are local-only.

                      Ehm, a plugin is currently always global. It's supposed to define mappings
                      that work in every type of file. A settings file does things local to a
                      file of a certain filetype.

                      A settings-plugin file, or more appropriately: filetype-plugin, would be
                      possible... Hmm, perhaps we could drop the settings files, and use this
                      scheme:

                      pluginft/<filetype>/default.vim

                      Which contains the stuff that is now in settings/<filetype>.vim. These can be
                      distributed with Vim, instead of the settings directory.

                      Then you can add filetype-specific plugin files like this:

                      pluginft/<filetype>/myplugin.vim
                      pluginft/<filetype>/yourplugin.vim

                      This way you can get somone else's plugin that only works for a specific
                      filetype and just drop it in the right directory.

                      One thing that will be difficult with this, is when you want to use the same
                      plugin for five different filetypes (on a system that doesn't support symbolic
                      links! :-).

                      Or is this getting too complicated?

                      --
                      hundred-and-one symptoms of being an internet addict:
                      216. Your pet rock leaves home.

                      /// Bram Moolenaar Bram@... http://www.moolenaar.net \\\
                      \\\ Vim: http://www.vim.org ICCF Holland: http://iccf-holland.org ///
                    • Johannes Zellner
                      ... Solution: Install an operating system. ... hey this is good! Maybe it could be done like this: if a plugin is found in pluginft/ / vim adds
                      Message 10 of 18 , Oct 10, 2000
                      • 0 Attachment
                        On Tue, Oct 10, 2000 at 10:35:32PM +0200, Bram Moolenaar wrote:
                        > A settings-plugin file, or more appropriately: filetype-plugin, would be
                        > possible... Hmm, perhaps we could drop the settings files, and use this
                        > scheme:
                        >
                        > pluginft/<filetype>/default.vim
                        >
                        > Which contains the stuff that is now in settings/<filetype>.vim. These can be
                        > distributed with Vim, instead of the settings directory.
                        >
                        > Then you can add filetype-specific plugin files like this:
                        >
                        > pluginft/<filetype>/myplugin.vim
                        > pluginft/<filetype>/yourplugin.vim
                        >
                        > This way you can get somone else's plugin that only works for a specific
                        > filetype and just drop it in the right directory.
                        >
                        > One thing that will be difficult with this, is when you want to use the same
                        > plugin for five different filetypes (on a system that doesn't support symbolic
                        > links! :-).

                        Solution: Install an operating system.

                        > Or is this getting too complicated?

                        hey this is good! Maybe it could be done like this:
                        if a plugin is found in

                        pluginft/<filetypes>/

                        vim adds automa[tg]ically <buffer> to the mappings and translates
                        all `set's to `setlocal's. This make sense, as everything from the

                        plugin/

                        is only loaded once (and therefore must be global). On the other hand

                        pluginft/<filetypes>/

                        is visited for every file beeing edited, so it makes sense to define
                        everything locally there.

                        Yeah. That's going to get really complicated.
                        Anyway: I believe there exist mostly two extremal cases:

                        1) very filetype specific scripts like indent, syntax, fold scripts.
                        These are shared rarely and if so, then only between a few realated
                        languages (e.g. html / xml / sgml). (drop these scripts in the
                        filetype specific directories).

                        2) scripts which work for all filetypes. (drop them in the plugin dir)

                        I think the intermediate case, that a script is used for some filetypes
                        and for some others not is pretty seldom.


                        --
                        Johannes
                      • Zdenek Sekera
                        ... [...] ... Funny you say that. Just yesterday I ve spent a fair amount of time to reorganize my settings/c.vim, make.vim, asm.vim to source common parts,
                        Message 11 of 18 , Oct 10, 2000
                        • 0 Attachment
                          Johannes Zellner wrote:
                          >
                          [...]
                          > Yeah. That's going to get really complicated.
                          > Anyway: I believe there exist mostly two extremal cases:
                          ????????
                          >
                          > 1) very filetype specific scripts like indent, syntax, fold scripts.
                          > These are shared rarely and if so, then only between a few realated
                          > languages (e.g. html / xml / sgml). (drop these scripts in the
                          > filetype specific directories).
                          >
                          > 2) scripts which work for all filetypes. (drop them in the plugin dir)
                          >
                          > I think the intermediate case, that a script is used for some filetypes
                          > and for some others not is pretty seldom.

                          Funny you say that. Just yesterday I've spent a fair amount of time to
                          reorganize my settings/c.vim, make.vim, asm.vim to source common parts,
                          some
                          3/4 were the same and the whole thing started to become unmanagable.

                          I think there will always be such cases but I also think a user will
                          have
                          to put in his own effort to sort it out. If it can be done....:-(

                          The whole idea seems attractive though a bit on the heavy side IMHO.

                          ---Zdenek
                        • Bram Moolenaar
                          ... I would prefer not to do things automatically here. It s quite easy to use :setlocal and :map in the scripts. When doing things
                          Message 12 of 18 , Oct 11, 2000
                          • 0 Attachment
                            Johannes Zellner wrote:

                            > > Or is this getting too complicated?
                            >
                            > hey this is good! Maybe it could be done like this:
                            > if a plugin is found in
                            >
                            > pluginft/<filetypes>/
                            >
                            > vim adds automa[tg]ically <buffer> to the mappings and translates
                            > all `set's to `setlocal's. This make sense, as everything from the
                            >
                            > plugin/
                            >
                            > is only loaded once (and therefore must be global). On the other hand
                            >
                            > pluginft/<filetypes>/
                            >
                            > is visited for every file beeing edited, so it makes sense to define
                            > everything locally there.

                            I would prefer not to do things automatically here. It's quite easy to use
                            ":setlocal" and ":map <buffer>" in the scripts. When doing things
                            automagically people would need to read the docs to understand how it really
                            works.

                            > Yeah. That's going to get really complicated.
                            > Anyway: I believe there exist mostly two extremal cases:
                            >
                            > 1) very filetype specific scripts like indent, syntax, fold scripts.
                            > These are shared rarely and if so, then only between a few realated
                            > languages (e.g. html / xml / sgml). (drop these scripts in the
                            > filetype specific directories).
                            >
                            > 2) scripts which work for all filetypes. (drop them in the plugin dir)
                            >
                            > I think the intermediate case, that a script is used for some filetypes
                            > and for some others not is pretty seldom.

                            I don't think so. For example, languages like C, C++ and Java are pretty
                            similar. Pascal and Delphi are similar. There must be many more.

                            It's possible to have one plugin contain the real stuff, and a
                            plugin-redirection in other directories. It would contain something like

                            source %:p:h/../sometype/other.vim

                            The complexity comes from when the user has to drop these files in his
                            plugin/filetype directories. And when he deletes the main plugin file he has
                            a source command that no longer works. Oh well.

                            --
                            hundred-and-one symptoms of being an internet addict:
                            225. You sign up for free subscriptions for all the computer magazines

                            /// Bram Moolenaar Bram@... http://www.moolenaar.net \\\
                            \\\ Vim: http://www.vim.org ICCF Holland: http://iccf-holland.org ///
                          • Dr. Charles E. Campbell
                            Hello! One problem that has cropped up (ie. I ve gotten bug reports about , for example) is that maps from elsewhere mess up the normal
                            Message 13 of 18 , Oct 11, 2000
                            • 0 Attachment
                              Hello!

                              One problem that has cropped up (ie. I've gotten bug reports about
                              <diffwin.vim>, for example) is that maps from "elsewhere" mess up the
                              normal operation of a package. Packages of macros/functions seldom
                              are written *expecting* outside maps to change their internal
                              behavior.

                              It seems to me that packages (ie. what goes into plugins) generally
                              should be protected from outside influences. This idea means that
                              maps need to know where they came from (internal to vim).


                              Thus did Bram say:

                              > Sorry, I don't understand what you want ":map <export>" to do and what
                              > problem it solves.

                              The idea is that mappings for plugins would, by default, assume what
                              I think you intend to have "map <buffer>" doing; ie. they would not
                              be operational outside the package. Only those mappings clearly
                              marked for export would have an outside-the-package influence. One
                              could "map <export>" for each such map in a similar vein to "map
                              <buffer>", or one could have <export> operate on a list of maps (map
                              <export> list-of-maps). The latter form makes for it clear as to
                              what maps are exported for external use.

                              Anyway, I'm arguing for a firewall between in-plugin-package and
                              out-of-plugin-package. Plugins' maps/functions should generally
                              *not* affect or be available to other plugins. Such interactions
                              nearly always result in difficult-to-find bugs. Of course, there's
                              bound to be an exception (such as netrw.vim's ftp://abc/def
                              handling), so perhaps a plugin package should also have some import
                              capability. However, in that case, the author of the plugin would
                              have taken that other package into account.

                              > Then you can add filetype-specific plugin files like this:
                              >
                              > pluginft/<filetype>/myplugin.vim
                              > pluginft/<filetype>/yourplugin.vim

                              This is probably a Good Idea, as it would facilitate distribution.
                              As is, I use autocmds in my <.vimrc>.

                              Regards,
                              C. Campbell

                              --
                              Charles E Campbell, Jr, PhD _ __ __
                              Goddard Space Flight Center / /_/\_\_/ /
                              cec@... /_/ \/_//_/
                              PGP public key: http://www.erols.com/astronaut/pgp.html/
                            • Bram Moolenaar
                              ... You mean that the package internally uses some key sequences as mappings, and the user never uses them. Yes, you want to make sure these mappings never
                              Message 14 of 18 , Oct 11, 2000
                              • 0 Attachment
                                Charles Campbell wrote:

                                > One problem that has cropped up (ie. I've gotten bug reports about
                                > <diffwin.vim>, for example) is that maps from "elsewhere" mess up the
                                > normal operation of a package. Packages of macros/functions seldom
                                > are written *expecting* outside maps to change their internal
                                > behavior.
                                >
                                > It seems to me that packages (ie. what goes into plugins) generally
                                > should be protected from outside influences. This idea means that
                                > maps need to know where they came from (internal to vim).

                                You mean that the package internally uses some key sequences as mappings, and
                                the user never uses them. Yes, you want to make sure these mappings never
                                get mixed up with mappings from the user or other scripts.

                                However, I don't see that maps need to know where they came from. They just
                                need to be unique. The same can be said for functions that the package uses
                                internally.

                                > The idea is that mappings for plugins would, by default, assume what
                                > I think you intend to have "map <buffer>" doing; ie. they would not
                                > be operational outside the package. Only those mappings clearly
                                > marked for export would have an outside-the-package influence. One
                                > could "map <export>" for each such map in a similar vein to "map
                                > <buffer>", or one could have <export> operate on a list of maps (map
                                > <export> list-of-maps). The latter form makes for it clear as to
                                > what maps are exported for external use.

                                This is extremely difficult to implement. After the script has run and
                                installed its mappings, Vim doesn't know where the mapping came from. Since
                                it's obviously required that some mappings can be called from another script
                                (the ones that are "exported") it would be very complicated to add some mode
                                for where only the mappings from one script apply. And the mappings from the
                                user would have to be blocked out at the same time. Complicated...

                                > Anyway, I'm arguing for a firewall between in-plugin-package and
                                > out-of-plugin-package. Plugins' maps/functions should generally
                                > *not* affect or be available to other plugins. Such interactions
                                > nearly always result in difficult-to-find bugs. Of course, there's
                                > bound to be an exception (such as netrw.vim's ftp://abc/def
                                > handling), so perhaps a plugin package should also have some import
                                > capability. However, in that case, the author of the plugin would
                                > have taken that other package into account.

                                I don't really like the idea of importing/exporting mappings. It's a new
                                mechanism that the user would have to learn. And I'm not sure how it would
                                work anyway.

                                Instead, why not generate a string that's unique for the script. Then you can
                                prepend that to your mappings (and function names) to make sure no one else
                                will use them. It could work like <Map> is used for "mapleader". Perhaps
                                <SID> (Script ID). Then you could do:

                                :map \FoobarFunc <SID>1<SID>2
                                :map <SID>1 do-something
                                :map <SID>2 do-something-more

                                Here \FoobarFunc is "exported". The <SID>1 and <SID>2 mappings will be
                                "local" to the script. Note that the first :map command has an "exported" key
                                sequence in the lhs, and "local" key sequences in the rhs. Thus it wouldn't
                                be possible to do something like ":map <local>" for this.

                                Now, how to generate a unique <SID>? Perhaps by using a special key code and
                                a number. The special code could start with K_SPECIAL, which can't be typed.
                                The number is then unique for the script, simply incrementing a number for
                                each script loaded would work.

                                Something similar could be used for function names. Perhaps by prepending
                                "s:" for the function name, like it's done for script-local variables? No,
                                that doesn't work when the function is called by a mapping... Perhaps <SID>
                                can be used here too:

                                :map <SID>2 :call <SID>DoIt()<CR>
                                function <SID>DoIt()
                                ...

                                This requires the <SID> in commands that are executed _after_ executing the
                                script, like functions and autocommands. The <SID> would have to be replaced
                                while the script is executed. I'm not 100% sure this will work...

                                Anything else that should be local to the plugin script?

                                --
                                hundred-and-one symptoms of being an internet addict:
                                229. You spend so much time thinking what to add on this list.

                                /// Bram Moolenaar Bram@... http://www.moolenaar.net \\\
                                \\\ Vim: http://www.vim.org ICCF Holland: http://iccf-holland.org ///
                              • Dr. Charles E. Campbell
                                ... Well, not exactly -- the problem which I was referring to was a mapping involving j. Camilo Ramos just came up with a problem involving a mapping of
                                Message 15 of 18 , Oct 12, 2000
                                • 0 Attachment
                                  > Charles Campbell wrote:
                                  > > One problem that has cropped up (ie. I've gotten bug reports about
                                  > > <diffwin.vim>, for example) is that maps from "elsewhere" mess up the
                                  > > normal operation of a package.

                                  Thus saith Bram Moolenaar:
                                  > You mean that the package internally uses some key sequences as mappings

                                  Well, not exactly -- the problem which I was referring to was a
                                  mapping involving <c-w>j. Camilo Ramos just came up with a problem
                                  involving a mapping of <c-v>. So these two problems are examples of
                                  folk's private maps' interference. Noremap blots out all maps;
                                  <diffwin.vim> (and <hdiffwin.vim>) has several maps which use other
                                  maps in the package, and so noremap is too strong.

                                  I like the <SID> idea, although something like <private> might be
                                  better in terms of functionality rather than implementation. Now if
                                  a "noremap" that allows <SID>maps was available (remapsid? remapriv?)
                                  then I could modify <diffwin.vim> to have a public interface but to
                                  internally allow package-only maps to do their thing.

                                  Regards,
                                  Chip Campbell

                                  --
                                  Charles E Campbell, Jr, PhD _ __ __
                                  Goddard Space Flight Center / /_/\_\_/ /
                                  cec@... /_/ \/_//_/
                                  PGP public key: http://www.erols.com/astronaut/pgp.html/
                                • Bram Moolenaar
                                  ... OK, this makes clear what the problem is. ... Would work different from then? Or is it just the name? ... which defines a mapping local
                                  Message 16 of 18 , Oct 12, 2000
                                  • 0 Attachment
                                    Charles Campbell wrote:

                                    > Thus saith Bram Moolenaar:
                                    > > You mean that the package internally uses some key sequences as mappings
                                    >
                                    > Well, not exactly -- the problem which I was referring to was a
                                    > mapping involving <c-w>j. Camilo Ramos just came up with a problem
                                    > involving a mapping of <c-v>. So these two problems are examples of
                                    > folk's private maps' interference. Noremap blots out all maps;
                                    > <diffwin.vim> (and <hdiffwin.vim>) has several maps which use other
                                    > maps in the package, and so noremap is too strong.

                                    OK, this makes clear what the problem is.

                                    > I like the <SID> idea, although something like <private> might be
                                    > better in terms of functionality rather than implementation.

                                    Would <private> work different from <SID> then? Or is it just the name?

                                    > Now if a "noremap" that allows <SID>maps was available (remapsid? remapriv?)
                                    > then I could modify <diffwin.vim> to have a public interface but to
                                    > internally allow package-only maps to do their thing.

                                    How about:

                                    :map <script> lhs rhs

                                    which defines a mapping "local to the script".

                                    This sort of fits next to:

                                    :map <buffer> lhs rhs

                                    which defines a mapping "local to a buffer".

                                    However, the intended meaning of "local" is slightly different. ":map
                                    <buffer>" defines a lhs which is local. ":map <script>" would use a lhs which
                                    is global, but no global mappings are used in the rhs. Hmm, that's hard to
                                    explain.

                                    Perhaps it's better to use:

                                    :noremap <script> lhs rhs

                                    Does this make clear that <script> applies to the no-remapping?

                                    Perhaps I should try writing the "How to write a plugin" chapter to check if
                                    it all looks logical and consistent.

                                    --
                                    Vi is clearly superior to emacs, since "vi" has only two characters
                                    (and two keystrokes), while "emacs" has five. (Randy C. Ford)

                                    /// Bram Moolenaar Bram@... http://www.moolenaar.net \\\
                                    \\\ Vim: http://www.vim.org ICCF Holland: http://iccf-holland.org ///
                                  • Dr. Charles E. Campbell
                                    ... Just the name; private refers to purpose, sid (presumably script identifier) refers to method of implementation. ... Whew, my head was spinning after all
                                    Message 17 of 18 , Oct 13, 2000
                                    • 0 Attachment
                                      Thus saith Bram Moolenaar:
                                      > Would <private> work different from <SID> then? Or is it just the name?
                                      Just the name; private refers to purpose, sid (presumably script identifier)
                                      refers to method of implementation.

                                      > Perhaps I should try writing the "How to write a plugin" chapter to check if
                                      > it all looks logical and consistent.

                                      Whew, my head was spinning after all that (map <buffer> , map <local>, noremap <script>).
                                      What about

                                      map|noremap|etc [<{lhs|rhs}={buffer,script,local,global}[,{lhs|rhs}={buffer,script,local,global}]>] lhsmap rhsmap

                                      where [...] is optional
                                      {...} pick one

                                      lhs restrictions apply to where map is available to be used,
                                      rhs restrictions apply to where maps will be expanded from.

                                      Regards,
                                      C Campbell

                                      --
                                      Charles E Campbell, Jr, PhD _ __ __
                                      Goddard Space Flight Center / /_/\_\_/ /
                                      cec@... /_/ \/_//_/
                                      PGP public key: http://www.erols.com/astronaut/pgp.html/
                                    • Bram Moolenaar
                                      ... But private to what? is not a word that clearly defines what it s for. ... Hmm, I get the idea. However, the rhs= and lhs= make it a bit
                                      Message 18 of 18 , Oct 13, 2000
                                      • 0 Attachment
                                        Charles Campbell wrote:

                                        > Thus saith Bram Moolenaar:
                                        > > Would <private> work different from <SID> then? Or is it just the name?
                                        > Just the name; private refers to purpose, sid (presumably script identifier)
                                        > refers to method of implementation.

                                        But private to what? <private> is not a word that clearly defines what it's
                                        for.

                                        > Whew, my head was spinning after all that (map <buffer> , map <local>,
                                        > noremap <script>). What about
                                        >
                                        > map|noremap|etc [<{lhs|rhs}={buffer,script,local,global}[,{lhs|rhs}={buffer,script,local,global}]>] lhsmap rhsmap
                                        >
                                        > where [...] is optional
                                        > {...} pick one
                                        >
                                        > lhs restrictions apply to where map is available to be used,
                                        > rhs restrictions apply to where maps will be expanded from.

                                        Hmm, I get the idea. However, the "rhs=" and "lhs=" make it a bit
                                        complicated. And I don't understand what "local" and "global" would stand
                                        for. what would they do?

                                        A variant that looks a bit nicer to me:

                                        :map [<buffer>|<script>] lhs [<buffer>|<script>] rhs

                                        Using <buffer> before lhs means the mapping is local to the current buffer.
                                        Using <script> before the lhs means the mapping is local to the script. Only
                                        items in the script will expand it.

                                        OK so far.

                                        <buffer> before the rhs means, eh, only remap mappings local to a buffer here?
                                        Doesn't sound too useful.
                                        <script> before the rhs means to only remap key sequences for a mapping local
                                        to the script.

                                        The problem here lies in the implementation. When looking for mappings to
                                        expand, how can Vim know from which script some key sequence came from? It
                                        would mean that for every mapped character, Vim would need to remember the ID
                                        of the script that expanded it. Complicated...

                                        I think the idea to use <SID> is in fact simpler: You can put it in mappings
                                        you want to keep local to the script. It also works in the rhs. It's easy to
                                        see which mapping is triggered where.

                                        --
                                        Women are probably the main cause of free software starvation.

                                        /// Bram Moolenaar Bram@... http://www.moolenaar.net \\\
                                        \\\ Vim: http://www.vim.org ICCF Holland: http://iccf-holland.org ///
                                      Your message has been successfully submitted and would be delivered to recipients shortly.