Plugin os.execute() command causes editor display bug
mikek88 opened this issue · comments
Upon execution of the plugin code below, the editor strangely shifts each line as you move through it with the arrow keys. It I remove the "-v" (verbose) option from the copy command the problem goes away. But I do want the results of the execute.
N.B. I'm using micro version 2.0.14.
local micro = import("micro")
local config = import("micro/config")
function init()
config.MakeCommand("test", testCommand, config.NoComplete)
end
function testCommand(bp)
local s, err = os.execute("cp -v -a main.lua main.lua2")
if err ~= nil then
micro.InfoBar():Error(err)
end
end
When you run os.execute()
, the command's stdout is just dumped onto the same console where micro prints its output, so it messes with micro.
What you want is a function such as micro's ExecCommand()
or RunCommand()
(documented in help plugins
) that reads the command's output into a string, and then you can do with this output whatever you need to do with it.
I tried using ExecCommand() and RunCommand(), but couldn't get them to deal with shell variables. The code above is the minimum to recreate the bug that I saw. The code below is what I want to do, which is to append the date to a file. It works with os.execute(), but not with shell.ExecCommand() or shell.RunCommand(). And os.execute(), of course, has the problem I showed.
Perhaps this is two bugs?
local micro = import("micro")
local config = import("micro/config")
local shell = import("micro/shell")
function init()
config.MakeCommand("test", testCommand, config.NoComplete)
end
function testCommand(bp)
--shell.ExecCommand("cp", "-v -a main.lua main.lua-$(date +\"%Y%m%d\")")
shell.RunCommand("cp -v -a main.lua main.lua-$(date +\"%Y%m%d\")")
end
If you want to use shell features you can execute it in a shell, eg.
shell.RunCommand("sh -c 'cp -v -a main.lua main.lua-$(date +%Y%m%d)'")
Of course you could also get the date on the Lua side of things to avoid using a subshell:
shell.RunCommand(string.format("cp -v -a main.lua main.lua-%s", os.date("%Y%m%d")))
That works. Thank you.
That works. Thank you.
So this issue can be closed, right?
Isn't this technically still a bug? The output from os.execute() messes with micro.
Nope. Full-screen terminal applications (micro, vim, mutt, mc and so on) work by writing characters and escape sequences to their stdout. (That is how they communicate with the terminal, to let the terminal know which characters to draw where and in what colors and so on.) So if you write Lua code that runs a program that simply uses the current process's stdout, e.g. the same stdout micro is using to communicate with the terminal, the outcome is unpredictable. So you need to take care to appropriately redirect the program's stdout somewhere (especially since you want to do that anyway, since you probably want your Lua code to get this output to do something with it, rather than just randomly dump it on the screen at some undefined location, right?). And micro provides Lua functions allowing to do that.
But os.execute() is dumping the output to "s, err", no? And if not, then it seems to me that os.execute() can't be used ever.
But os.execute() is dumping the output to "s, err", no?
https://www.lua.org/manual/5.4/manual.html#pdf-os.execute
os.execute ([command])
This function is equivalent to the ISO C function system. It passes command to be executed by an operating system shell. Its first result is true if the command terminated successfully, or fail otherwise. After this first result the function returns a string plus a number, as follows:
"exit": the command terminated normally; the following number is the exit status of the command.
"signal": the command was terminated by a signal; the following number is the signal that terminated the command.
And if not, then it seems to me that os.execute() can't be used ever.
It can be used, if the program using it is not a full-screen terminal application and doesn't care about its output.
Okay, thanks.
So, the issue can be closed.