2

I'm looking at some obfuscated JS:

const f = Buffer.from("Lw==", "base64");
// select ^---------------------------^

How can I send the selection to node -p and replace?

I tried :'<,'>!node -p, but that produced undefined, because it sent the whole line instead of just the selected part of the line. It also deleted the indent and const f = , which I didn't want to do.

Chaim Leib Halbert
  • 2,194
  • 20
  • 23

3 Answers3

2

Ex commands operate on lines, not on arbitrary text, so you can forget about :w or :!.

Here is a working solution but I'm afraid there is no dedicated built-in method so you won't be able to avoid at least some level of complexity:

v<motion>
:'<,'>s/\%V.*\%V/\=system('node -p ' . shellescape(submatch(0) . '.toString()'))->trim()/<CR>

That's obviously quite a lot to remember and type but you can turn it into a visual mode mapping for more convenience:

xnoremap <key> :s/\%V.*\%V/\=system('node -p ' . shellescape(submatch(0) . '.toString()'))->trim()/<CR>

which you can then use like this:

v<motion><key>

But a real solution would also deal with sanitizing input and output, handling errors, handling multiline input and output, etc.

romainl
  • 186,200
  • 21
  • 280
  • 313
0
d
:call setreg('a', system('printf "%s" "$(echo '.shellescape(@").'".toString()" | node -p)"'))
"aP

This produced the expected / as output in the correct position:

const f = /;

However, it feels overly complicated compared to the linewise version. I'm looking for a better way.

Chaim Leib Halbert
  • 2,194
  • 20
  • 23
0

Another approach is to temporarily isolate the selection to its own line.

<ESC>           "exit visual mode
`>a             "append after selection
.toString()     "modify JS before sending to node -p
<CR><ESC>
`<i             "insert before selection
<CR><ESC>
V               "select line
:'<,'>!node -p  "do the usual linewise filter
k               "go previous line
3gJ             "join 3 lines without adding or removing spaces

Unfortunately this will do strange things if the command returns multiple lines.

Chaim Leib Halbert
  • 2,194
  • 20
  • 23