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

Re: Help with unwanted shell character expansion

Expand Messages
  • Yakov Lerner
    ... Easy. Here s the function that sets buffername without escaping. function! LiteralSetBufferName(name) we need to escape following chars: $ ` ~ % # * ?
    Message 1 of 9 , Aug 1, 2006
    • 0 Attachment
      On 7/31/06, Bob Hiestand <bob.hiestand@...> wrote:
      > Question two:
      >
      > Is there a way to set the buffer name without the name being subject
      > to shell metacharacter expansion?

      Easy. Here's the function that sets buffername without escaping.

      function! LiteralSetBufferName(name)
      " we need to escape following chars: $ ` ~ \ % # * ?
      let escaped = substitute(a:name, '[$`~%#*?\\]', '\\&', 'g')
      exe "file ".escaped
      endfun
      :command! -nargs=1 FILE :call LiteralSetBufferName(<q-args>)

      And here's remapping of :file command to this function/command:

      cabbrev f <c-R>=(getcmdtype()==':' && getcmdpos()==1 ? 'F' : 'f')<cr>
      cabbrev fi <c-R>=(getcmdtype()==':' && getcmdpos()==1 ? 'FI' : 'fi')<cr>
      cabbrev fil <c-R>=(getcmdtype()==':' && getcmdpos()==1 ? 'FIL' : 'fil')<cr>
      cabbrev file <c-R>=(getcmdtype()==':' && getcmdpos()==1 ? 'FILE' : 'file')<cr>

      Yakov
    • Yakov Lerner
      ... Correction. I wanted to write: Here s the function that sets buffername without any metacharacter expansion.
      Message 2 of 9 , Aug 1, 2006
      • 0 Attachment
        On 8/1/06, Yakov Lerner <iler.ml@...> wrote:
        > Here's the function that sets buffername without escaping.

        Correction. I wanted to write:

        Here's the function that sets buffername without any metacharacter expansion.
      • Bob Hiestand
        ... Thanks, Tony. I should provide context for my request. For my cvscommand plugin, which opens new buffers containing the results of CVS operations
        Message 3 of 9 , Aug 1, 2006
        • 0 Attachment
          On 7/31/06, A.J.Mechelynck <antoine.mechelynck@...> wrote:
          > Bob Hiestand wrote:
          > > Question one:
          > >
          > > Is there a way to achieve execution of system commands without using
          > > the shell? Here I'm thinking (for example) of, in perl, the
          > > difference between using a single argument to exec() and using
          > > multiple arguments. In the first version, shell characters are
          > > expanded, in the second, they are not.
          > >
          > > If there is no such functionality currently, is this a planned
          > > feature? I believe that such a feature would make writing portable
          > > plugins easier.
          >
          > AFAIK, the only way to execute an external program from Vim with no
          > shell wrapping is to set the 'shell' option itself to the program name.
          > There may be drawbacks and pitfalls to that approach, though.
          >
          > >
          > > Question two:
          > >
          > > Is there a way to set the buffer name without the name being subject
          > > to shell metacharacter expansion? As far as I know, only :edit,
          > > :split, :new, :write, and :file allow setting the buffer name, and
          > > those all apply shell expansion. I know that characters can be
          > > escaped, but that involved knowledge of which characters are
          > > significant on each platform and again leads to unportable code (or
          > > highly complex code that attempts to be portable by taking each system
          > > into account). I would like a function to set the buffer name
          > > (potentially for a buffer specified by number) or for the '%' register
          > > to be writable.
          > >
          > > Thank you,
          > >
          > > bob
          > >
          > >
          >
          > A buffer name is usually a (potential) file name. Which characters are
          > allowed in a filename is system-dependent. On Dos and on 16-bit Windows,
          > only 8+3 names are allowed (with no embedded spaces). On Unix, case is
          > usually significant while on Windows it usually isn't. And so on.
          >
          > Also, Windows versions of Vim expand wildcards, while Unix versions
          > leave the expansion (except for ** which is a Vim-specific extension) to
          > the shell.
          >
          > The buffer name can also be set by ":saveas", ":view", ":sview"... I'm
          > not sure I got them all. I expect all of these to also expand, for
          > instance, environment variables. ":saveas" is (IIUC) equivalent to
          > altering the current buffer's name then writing it under the new name.
          > If the new name already exists, ":saveas filename" will fail but
          > ":saveas! filename" will succeed (unless of course there is a further
          > write-error, such as a "disk full" condition).
          >
          > IIUC, all Vim's internal file-related commands accept a "unix-like"
          > filename syntax, and Vim translates it if necessary to the OS's syntax:
          > e.g., when Vim for Windows receives the command ":view
          > $VIMRUNTIME/vimrc_example.vim" (with an environment variable and using a
          > forward slash as separator) the string it passes to the Windows "file
          > open" function will be something like "C:\Program
          > Files\vim\vim70\vimrc_example.vim" (without the quotes and with a
          > terminating null byte IIUC, but also with the environment variable
          > resolved and, most important, with backslashes as separators).
          > Similarly, in Vim for Windows embedded spaces are backslash-escaped (as
          > in Unix), even though the Windows syntax is not to use any embedded
          > escaping but to wrap the whole name in double quotes.
          >
          > If you want to build "portable" names for newly-created files, then
          >
          > (assuming you can disregard pre-Win32 Dos-like systems) I suggest
          > limiting yourself to lowercase letters, digits, underscore and period.
          > Some systems allow more than that (and some OS versions accept Unicode
          > non-ASCII characters in filenames) but I believe that with [0-9a-z_.]
          > you can be fairly certain that your filename will be legal "almost
          > everywhere", and that different names will refer to different files.
          >
          >
          > Best regards,
          > Tony.
          >

          Thanks, Tony. I should provide context for my request. For my
          cvscommand plugin, which opens new buffers containing the results of
          CVS operations performed on the file associated with the current
          buffer, I need to be able to name the resulting scratch buffers.
          These buffers will be explicitly not associated with files.

          I used to have these as nameless files, and used the statusline to
          pull up custom variables set by the plugin to create a suitable
          display name (something like "[CVS log originalFileName]"). The
          problem with this solution is that the buffer list commands just show
          the nameless scratch buffers, of course, making navigation difficult.

          As an alternative, in the new version of the plugin, I explicitly name
          the buffers. However, that means that the original file name appears
          in the buffer name, and is subject to shell expansion.

          While it is indeed possible to do as Yakov suggests and try to escape
          the shell meta-characters, I've experienced some difficulty in making
          that work across multiple platforms consistently (primarily Linux,
          Windows (various flavors), Windows + cygwin (my personal terror)). I
          actually already use the escape command, and ran into issues when
          Windows interpreted the resulting escaped character as a backslash +
          original character. While the help mentions a work-around for this in
          the case of the '[' character, I frankly don't want to have to worry
          with this particular source of bugs.

          It occurred to me that, particularly for scratch buffers, it ought to
          be possible to explicitly set the name without regard for file system
          conventions.

          Thanks for the responses,

          Bob
        • Bob Hiestand
          As is too often the case, I didn t read enough documentation. I think this is not a well-known feature. ... Yes, by using backtick notation along with the =
          Message 4 of 9 , Aug 3, 2006
          • 0 Attachment
            As is too often the case, I didn't read enough documentation. I think
            this is not a well-known feature.

            On 7/31/06, Bob Hiestand <bob.hiestand@...> wrote:

            > Question two:
            >
            > Is there a way to set the buffer name without the name being subject
            > to shell metacharacter expansion? As far as I know, only :edit,
            > :split, :new, :write, and :file allow setting the buffer name, and
            > those all apply shell expansion. I know that characters can be
            > escaped, but that involved knowledge of which characters are
            > significant on each platform and again leads to unportable code (or
            > highly complex code that attempts to be portable by taking each system
            > into account). I would like a function to set the buffer name
            > (potentially for a buffer specified by number) or for the '%' register
            > to be writable.

            Yes, by using backtick notation along with the '=' expression prefix,
            non-expansion is possible.

            For example,

            :e `=unescapedFileName`

            Thanks all for the replies,

            Bob
          • Yakov Lerner
            ... Does this really work fo you ? First, many characters are interpreted specially inside `=...`, Those are (,),+,- and all vim ... E121: Undefined variable:
            Message 5 of 9 , Aug 3, 2006
            • 0 Attachment
              On 8/3/06, Bob Hiestand <bob.hiestand@...> wrote:
              > As is too often the case, I didn't read enough documentation. I think
              > this is not a well-known feature.
              >
              > On 7/31/06, Bob Hiestand <bob.hiestand@...> wrote:
              >
              > > Question two:
              > >
              > > Is there a way to set the buffer name without the name being subject
              > > to shell metacharacter expansion? As far as I know, only :edit,
              > > :split, :new, :write, and :file allow setting the buffer name, and
              > > those all apply shell expansion. I know that characters can be
              > > escaped, but that involved knowledge of which characters are
              > > significant on each platform and again leads to unportable code (or
              > > highly complex code that attempts to be portable by taking each system
              > > into account). I would like a function to set the buffer name
              > > (potentially for a buffer specified by number) or for the '%' register
              > > to be writable.
              >
              > Yes, by using backtick notation along with the '=' expression prefix,
              > non-expansion is possible.
              >
              > For example,
              >
              > :e `=unescapedFileName`

              Does this really work fo you ? First, many characters
              are interpreted specially inside `=...`, Those are (,),+,- and all vim
              operators (see val.txt). Second, if I try your examlpe, I get:

              :e `=unescapedFileName`
              E121: Undefined variable: unescapedFIleName
              "`=unescapedFileName`" [New File]
              And then filename is set to
              `=unescapedFileName`

              Note how filename includes backticks and equal sign.

              Or did you possibly mean :e `='unescapedFileName'` ?

              Yakov
            • Bob Hiestand
              ... Another way to do this appears to be using the bufnr function with the create optional parameter set. I have not extensively tested it, but it seems
              Message 6 of 9 , Aug 7, 2006
              • 0 Attachment
                On 8/3/06, Bob Hiestand <bob.hiestand@...> wrote:
                > On 8/3/06, Yakov Lerner <iler.ml@...> wrote:
                > > On 8/3/06, Bob Hiestand <bob.hiestand@...> wrote:
                > > > As is too often the case, I didn't read enough documentation. I think
                > > > this is not a well-known feature.
                > > >
                > > > On 7/31/06, Bob Hiestand <bob.hiestand@...> wrote:
                > > >
                > > > > Question two:
                > > > >
                > > > > Is there a way to set the buffer name without the name being subject
                > > > > to shell metacharacter expansion? As far as I know, only :edit,
                > > > > :split, :new, :write, and :file allow setting the buffer name, and
                > > > > those all apply shell expansion. I know that characters can be
                > > > > escaped, but that involved knowledge of which characters are
                > > > > significant on each platform and again leads to unportable code (or
                > > > > highly complex code that attempts to be portable by taking each system
                > > > > into account). I would like a function to set the buffer name
                > > > > (potentially for a buffer specified by number) or for the '%' register
                > > > > to be writable.
                > > >
                > > > Yes, by using backtick notation along with the '=' expression prefix,
                > > > non-expansion is possible.
                > > >
                > > > For example,
                > > >
                > > > :e `=unescapedFileName`
                > >
                > > Does this really work fo you ? First, many characters
                > > are interpreted specially inside `=...`, Those are (,),+,- and all vim
                > > operators (see val.txt). Second, if I try your examlpe, I get:
                > >
                > > :e `=unescapedFileName`
                > > E121: Undefined variable: unescapedFIleName
                > > "`=unescapedFileName`" [New File]
                > > And then filename is set to
                > > `=unescapedFileName`
                > >
                > > Note how filename includes backticks and equal sign.
                > >
                > > Or did you possibly mean :e `='unescapedFileName'` ?
                > >
                > > Yakov
                > >
                >
                > Sorry, to be clear, unescapedFileName is a variable.

                Another way to do this appears to be using the 'bufnr' function with
                the 'create' optional parameter set. I have not extensively tested
                it, but it seems to be a useful alternative.
              Your message has been successfully submitted and would be delivered to recipients shortly.