Can I pass the output of a node.js script to `less` without input` | less` at startup?

For example, my script will generate a lot of results using process.stdout.write(). I know that I can pass them in lessby running it as node mycode.js | less -N.

But is there a way so that I can run the pipeline inside my code so that other people can run my code normally node mycode.jsand still get my output in less?

+4
source share
2 answers

Yes, you can output the output of your node program less input through the regular API of the main module child_process. However, the problem will be a control one. If you run your node program, it will control pty and have less access to pty, so interacting with fewer input commands will not work. AFAIK (others may very well know better than me) there is no clean way to do this from your node program, so I will just write a shell script shell to do this and name it.

The closest feature I found in npm is default-pager , but from my quick test build it doesn't work .: - (

+1
source

Node, : node-kexec.

, ( CoffeeScript):

page = (cb)->

   # If we reach this point in the code and $_PAGINATED is already set, then we've
   # successfully paginated the script and should now actually run the code meant
   # to be run *inside* a pager.
   if process.env['_PAGINATED']?
      return cb()

   # I use tricks like this to control the pager itself; they can be super-dirty,
   # though, and mutating shell-command lines without a *lot* of careful
   # invocation logic is generally a bad idea unless you have a good reason:
   pager = process.env.PAGER || 'less --chop-long-lines'
   pager = pager.replace /less(\s|$)/, 'less --RAW-CONTROL-CHARS$1'

   # I use this elsewhere in my code-base to override `term.columns` if it is
   # unset; because the pager often doesn't properly report terminal-width
   process.env['PAGINATED_COLUMNS'] = term.columns
   process.env['_PAGINATED'] = 'yes'

   # This is a horrible hack. Thanks, Stack Overflow.
   #    <https://stackoverflow.com/a/22827128>
   escapeShellArg = (cmd)-> "'" + cmd.replace(/\'/g, "'\\''") + "'"

   # This is how we *re-invoke* precisely the exact instructions that our script /
   # executable was originally given; in addition to ensuring that `process.argv`
   # is the same by doing this, `kexec` will already ensure that our replacement
   # inherits our `process.stdout` and etc.
   #
   # (These arguments are invoked *in a shell*, as in `"sh" "-c" ...`, by
   # `kexec()`!)
   params = process.argv.slice()
   params = params.map (arg)-> escapeShellArg arg
   params.push '|'
   params.push pager

   log.debug "!! Forking and exec'ing to pager: `#{pager}`"
   log.wtf "-- Invocation via `sh -c`:", params.join ' '

   kexec params.join ' '

, ; - page(print_help_text) ( ).

: , , , ; , , page(), ; , . ( , .) , , , page(), , .

( , ​​ Node, exec, ​​ Ruby's. :P)


Nota bene: , --[no-]pager. , .

, , , ; kexec package.json optionalDependencies, try/catch ( , optional), . , , - , , .

+1

Source: https://habr.com/ru/post/1537042/


All Articles