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

Output/Input is not to/from a terminal

Expand Messages
  • Walter Briscoe
    With a vim built with Make_ivc.mak on w2ksp3, I locked up a terminal session with the following contrived example: C: wfb vim bld echo hello | vim t.t Vim:
    Message 1 of 6 , Apr 30, 2003
    • 0 Attachment
      With a vim built with Make_ivc.mak on w2ksp3, I locked up a terminal
      session with the following contrived example:
      C:\wfb\vim\bld> echo hello | vim > t.t
      Vim: Warning: Output is not to a terminal
      Vim: Warning: Input is not from a terminal

      Neither message is documented.

      :help todo contains
      7 Allow using Vim in a pipe: "ls | vim -u xxx.vim - | yyy". Only needs
      implementing ":w" to stdout in the buffer that was read from stdin.

      I did a quick and dirty proof of concept on this. It worked once in
      w2ksp3 with a vimd built with Make_ivc.mak. It does not work with gvimd
      because stdout is unsupported by windoze programs.
      The command which worked was
      C:\wfb\vim\bld\vim62a\src> echo hello| vimd "+set ff=unix" +x - > t.x
      Vim: Warning: Output is not to a terminal

      C:\wfb\vim\bld\vim62a\src> dumpfile t.x
      00000000: 68 65 6C 6C 6F 0A - hello.

      It is quite right. 0D 0A is transformed to 0D 0D 0A as shown below when
      ff=dos
      C:\wfb\vim\bld\vim62a\src> echo hello| vimd "+set ff=dos" +x - > t.x
      Vim: Warning: Output is not to a terminal

      C:\wfb\vim\bld\vim62a\src> dumpfile t.x
      00000000: 68 65 6C 6C 6F 0D 0D 0A - hello...


      *** src/0ex_cmds.c Sat Apr 19 14:05:56 2003
      --- src/ex_cmds.c Wed Apr 30 12:29:58 2003
      ***************
      *** 2055,2060 ****
      --- 2055,2061 ----
      do_write(eap)
      exarg_T *eap;
      {
      + extern int stdout_isatty; /* is stdout a terminal? - hack to allow w to stdout */
      int other;
      char_u *fname = NULL; /* init to shut up gcc */
      char_u *ffname;
      ***************
      *** 2129,2135 ****
      #ifdef FEAT_QUICKFIX
      bt_dontwrite_msg(curbuf) ||
      #endif
      ! check_fname() == FAIL || check_readonly(&eap->forceit, curbuf)))
      goto theend;

      if (!other)
      --- 2130,2136 ----
      #ifdef FEAT_QUICKFIX
      bt_dontwrite_msg(curbuf) ||
      #endif
      ! (stdout_isatty && check_fname() == FAIL) || check_readonly(&eap->forceit, curbuf)))
      goto theend;

      if (!other)
      *** src/0fileio.c Mon Apr 21 16:08:54 2003
      --- src/fileio.c Wed Apr 30 13:50:38 2003
      ***************
      *** 2403,2411 ****
      vim_acl_T acl = NULL; /* ACL copied from original file to
      backup or new file */
      #endif
      !
      ! if (fname == NULL || *fname == NUL) /* safety check */
      ! return FAIL;

      /*
      * Disallow writing from .exrc and .vimrc in current directory for
      --- 2403,2409 ----
      vim_acl_T acl = NULL; /* ACL copied from original file to
      backup or new file */
      #endif
      ! extern int stdout_isatty; /* is stdout a terminal? - hack to allow w to stdout */

      /*
      * Disallow writing from .exrc and .vimrc in current directory for
      ***************
      *** 2414,2424 ****
      if (check_secure())
      return FAIL;

      ! /* Avoid a crash for a long name. */
      ! if (STRLEN(fname) >= MAXPATHL)
      {
      ! EMSG(_(e_longname));
      ! return FAIL;
      }

      #ifdef FEAT_MBYTE
      --- 2412,2428 ----
      if (check_secure())
      return FAIL;

      ! if (stdout_isatty)
      {
      ! if (fname == NULL || *fname == NUL) /* safety check */
      ! return FAIL;
      !
      ! /* Avoid a crash for a long name. */
      ! if (STRLEN(fname) >= MAXPATHL)
      ! {
      ! EMSG(_(e_longname));
      ! return FAIL;
      ! }
      }

      #ifdef FEAT_MBYTE
      ***************
      *** 3391,3396 ****
      --- 3395,3410 ----
      * (this may happen when the user reached his quotum for number of files).
      * Appending will fail if the file does not exist and forceit is FALSE.
      */
      + if (!stdout_isatty)
      + {
      + fd = 1;
      + #if defined(MSDOS) || defined(MSWIN) || defined(OS2)
      + /* Force binary I/O on stdout to avoid CR-LF -> LF conversion. */
      + if (get_fileformat(curbuf) == EOL_UNIX)
      + setmode(1, O_BINARY);
      + #endif
      + }
      + else
      while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
      ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
      : (O_CREAT | O_TRUNC))
      *** src/0main.c Mon Apr 28 09:11:58 2003
      --- src/main.c Wed Apr 30 14:04:28 2003
      ***************
      *** 29,34 ****
      --- 29,36 ----
      # include <limits.h>
      #endif

      + int stdout_isatty; /* is stdout a terminal? - hack to allow w to stdout */
      +
      #if defined(UNIX) || defined(VMS)
      static int file_owned __ARGS((char *fname));
      #endif
      ***************
      *** 141,147 ****
      int diff_mode = FALSE; /* start with 'diff' set */
      #endif
      int evim_mode = FALSE; /* started as "evim" */
      - int stdout_isatty; /* is stdout a terminal? */
      int input_isatty; /* is active input a terminal? */
      #ifdef MSWIN
      int full_path = FALSE;
      --- 143,148 ----

      --
      Walter Briscoe
    • Bram Moolenaar
      ... It s a nice hack, but it s not nearly enough. You also need to take care of temp files, these still need to be written to a real file. And things like
      Message 2 of 6 , Apr 30, 2003
      • 0 Attachment
        Walter Briscoe wrote:

        > :help todo contains
        > 7 Allow using Vim in a pipe: "ls | vim -u xxx.vim - | yyy". Only needs
        > implementing ":w" to stdout in the buffer that was read from stdin.
        >
        > I did a quick and dirty proof of concept on this. It worked once in
        > w2ksp3 with a vimd built with Make_ivc.mak. It does not work with gvimd
        > because stdout is unsupported by windoze programs.
        > The command which worked was
        > C:\wfb\vim\bld\vim62a\src> echo hello| vimd "+set ff=unix" +x - > t.x

        It's a nice hack, but it's not nearly enough. You also need to take
        care of temp files, these still need to be written to a real file. And
        things like the gzip plugin. This requires thinking of how to tell Vim
        it should write to stdout instead of a file.

        There are more important things to work on before adding another
        half-done feature...

        --
        Support your right to bare arms! Wear short sleeves!

        /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
        /// Creator of Vim - Vi IMproved -- http://www.Vim.org \\\
        \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
        \\\ Help AIDS victims, buy at Amazon -- http://ICCF.nl/click1.html ///
      • Andrew Pimlott
        ... I had no idea this was a todo, and I didn t look at your implementation, but I ve done this. I use a wrapper script to map some file descriptors, and a
        Message 3 of 6 , Apr 30, 2003
        • 0 Attachment
          On Wed, Apr 30, 2003 at 02:11:59PM +0100, Walter Briscoe wrote:
          > :help todo contains
          > 7 Allow using Vim in a pipe: "ls | vim -u xxx.vim - | yyy". Only needs
          > implementing ":w" to stdout in the buffer that was read from stdin.

          I had no idea this was a todo, and I didn't look at your
          implementation, but I've done this. I use a wrapper script to map
          some file descriptors, and a vim script to write the stdin buffer
          when it's unloaded. It's a quick hack, but do you see any problem
          with it is principle?

          I made :bunload, not :w, write the buffer to stdout, since my
          intuition is that you're only "happy" with the buffer when you close
          it. Plus, I :w habitually, and wouldn't want this to write to
          stdout. What would happen if you :w twice?

          vif:

          #!/bin/sh

          OPTS=$(getopt -o xg -n vif --long xterm,gui -- "$@")
          eval set -- "$OPTS"

          VIM='vim --cmd "runtime filter.vim"'
          CMD="$VIM -"

          while true; do
          case $1 in
          -x|--xterm) CMD="xterm -e sh -c '$VIM - <&4' 4<&0"; shift ;;
          -g|--gui) CMD="$VIM -g -"; shift ;;
          --) shift ; break ;;
          esac
          done

          eval exec $CMD 3>&1 >&2

          filter.vim:

          autocmd StdinReadPost * set buftype=nowrite | let b:stdin_buf = 1
          autocmd BufUnload * call Maybe_output()

          function Maybe_output()
          if ! exists("b:stdin_buf")
          return
          endif

          w! /dev/fd/3
          endfunction

          One obvious lack in vim (as far as I can tell) is a way to make an
          autocommand apply only to the current buffer. This is a particular
          problem when the buffer is unnamed. b:stdin_buf is used solely to
          work around this.

          (Actually, in writing this message, I found a bug. If the buffer is
          unloaded but vim is not exiting, the buffer variable is already
          cleared when the autocmd is called. So my b:stdin_buf work-around
          fails. Could the autocmd be called before variables are cleared?
          Or do I misunderstand what happens? Maybe I should set a global
          variable to the stdin bufno instead, and check that.)

          Andrew
        • Walter Briscoe
          In message of Wed, 30 Apr 2003 22:02:22 in , Bram Moolenaar writes ... I shall abandon this. I
          Message 4 of 6 , May 1, 2003
          • 0 Attachment
            In message <200304302002.h3UK2M708164@...> of Wed, 30 Apr 2003
            22:02:22 in , Bram Moolenaar <Bram@...> writes
            >
            >Walter Briscoe wrote:
            >
            >> :help todo contains
            >> 7 Allow using Vim in a pipe: "ls | vim -u xxx.vim - | yyy". Only needs
            >> implementing ":w" to stdout in the buffer that was read from stdin.
            >>
            >> I did a quick and dirty proof of concept on this. It worked once in
            >> w2ksp3 with a vimd built with Make_ivc.mak. It does not work with gvimd
            >> because stdout is unsupported by windoze programs.
            >> The command which worked was
            >> C:\wfb\vim\bld\vim62a\src> echo hello| vimd "+set ff=unix" +x - > t.x
            >
            >It's a nice hack, but it's not nearly enough. You also need to take
            >care of temp files, these still need to be written to a real file. And
            >things like the gzip plugin. This requires thinking of how to tell Vim
            >it should write to stdout instead of a file.
            >
            >There are more important things to work on before adding another
            >half-done feature...
            >
            I shall abandon this.
            I leave the missing documentation and/or message change to Bram.
            --
            Walter Briscoe
          • Walter Briscoe
            In message of Wed, 30 Apr 2003 22:39:53 in , Andrew Pimlott writes ... [snip] This work is in
            Message 5 of 6 , May 1, 2003
            • 0 Attachment
              In message <20030501023953.GP30778@...> of Wed, 30 Apr 2003
              22:39:53 in , Andrew Pimlott <vim-dev@...> writes
              >On Wed, Apr 30, 2003 at 02:11:59PM +0100, Walter Briscoe wrote:
              >> :help todo contains
              >> 7 Allow using Vim in a pipe: "ls | vim -u xxx.vim - | yyy". Only needs
              >> implementing ":w" to stdout in the buffer that was read from stdin.
              >
              >I had no idea this was a todo, and I didn't look at your
              >implementation, but I've done this. I use a wrapper script to map
              >some file descriptors, and a vim script to write the stdin buffer
              >when it's unloaded. It's a quick hack, but do you see any problem
              >with it is principle?
              >
              >I made :bunload, not :w, write the buffer to stdout, since my
              >intuition is that you're only "happy" with the buffer when you close
              >it. Plus, I :w habitually, and wouldn't want this to write to
              >stdout. What would happen if you :w twice?
              [snip]
              This work is in a narrower context than vim itself which interested me.
              It looks good to me. It was interesting to see getopt (singular name)
              deal with long option names. I think IEEE Std 1003.1-2001 does not have
              getopt in that context. It has getopts (plural name) without the ability
              to handle long option names.
              --
              Walter Briscoe
            • Andrew Pimlott
              ... Oh, I m sure it is a GNU-ism. I cribbed the use of getopt from a file getopt-parse.bash.gz that got installed in an examples directory of util-linux on
              Message 6 of 6 , May 2, 2003
              • 0 Attachment
                On Fri, May 02, 2003 at 07:21:06AM +0100, Walter Briscoe wrote:
                > It was intresting to see getopt (singular name)
                > deal with long option names. I think IEEE Std 1003.1-2001 does not have
                > getopt in that context. It has getopts (plural name) without the ability
                > to handle long option names.

                Oh, I'm sure it is a GNU-ism. I cribbed the use of getopt from a
                file "getopt-parse.bash.gz" that got installed in an examples
                directory of util-linux on my (Debian) system. I'd never used any
                form of getopt* in a shell script.

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