0

I'm trying to write a Lua function for Neovim that, with the help of a few Bash commands, checks if a process is running; if it's running, close it, and if it's not, run a new instance.

Here's what I've managed to write so far:

isrunning = vim.cmd([[!pgrep -u $UID -x livereload > /dev/null && echo "true" || echo "false"]])
print(isrunning)

if isrunning == "true" then
  print('Closing Livereload...')
  vim.cmd('!killall livereload')
else
  print('Opening Livereload...')
  vim.cmd('!cd build; livereload &; firefox http://localhost:35729/"%<.html"')
end

The problem is that even if livereload is already running and the value of isrunning is "true", the first half of the if statement never runs, only what's after else. What do I need to change to fix that?


Update: Here's the output of :luafile %, when the above code is run in Neovim 0.5.0:

:!pgrep -u $UID -x livereload > /dev/null && echo "true" || echo "false"
true

:!cd build; livereload &; firefox http://localhost:35729/"livereload.html"

opening...

That made me think that the second line, true, must be the output of the command print(isrunning). After having some discussion in the comments section, I realized that this is not the case.

Here's the output when I change the print command to print("Answer: " .. isrunning .. "Length: " .. isrunning:len())

:!pgrep -u $UID -x livereload > /dev/null && echo "true" || echo "false"
true

Answer: Length: 0
:!cd build; livereload &; firefox http://localhost:35729/"livereload.html"

opening...

So, Neovim correctly shows the output of !pgrep -u $UID -x livereload > /dev/null && echo "true" || echo "false", but that output doesn't seem to be stored in the variable isrunning.

2 Answers2

3

if isrunning were "true" you would enter the if branch, but that is obviously not the case.

echo adds a trailing newline so isrunning is more likely to be "true\n" which of course is unequal to "true".

Use echo -n to suppress the trailing new line or check vs the correct value or use string.find or string.match instead of the ==

From the bash manual:

echo echo [-neE] [arg …] Output the args, separated by spaces, terminated with a newline. The return status is 0 unless a write error occurs. If -n is specified, the trailing newline is suppressed...

Piglet
  • 18,719
  • 2
  • 16
  • 30
  • I've tried all your suggestions, but none of them work. – user247824 May 10 '21 at 17:11
  • that's not a particularly informative comment. what is the value of `isrunning`? `print(isrunning, isrunning:len())` – Piglet May 10 '21 at 19:02
  • Sorry about that comment, I meant that the first part of the if statement would still not run. To answer your question, the value is ` 0` (with a space in front of 0). – user247824 May 10 '21 at 20:38
  • well last time you said it is "true", so what changed? it certainly did not change from "true" to " 0" because of the -n option – Piglet May 10 '21 at 20:54
  • I have updated the original question. Let me know if you need any more information. – user247824 May 11 '21 at 12:11
0

I've finally come up with a solution, which is twofold:

  1. Using the combination of io.popen and a file handle, as written in this answer to another question. This allows the value of echo to be read from Lua.
  2. Using echo -n to suppress the newline character, as mentioned by Piglet in an answer here.

With these changes in place, here's the final code:

handle = io.popen([[pgrep -u $UID -x livereload > /dev/null && echo -n "true" || echo -n "false"]])
isrunning = handle:read("*a")
handle:close()

if isrunning == "true" then
  print('closing...')
  vim.cmd('!killall livereload')
else
  print('opening...')
  vim.cmd('!cd build; livereload &; firefox http://localhost:35729/"%<.html"')
end