Migrate Vim/Vimscript for asynchronously running external editors to Lua/Neovim - lua

In my Vim's configuration file init.vim I am using code, that sets a default viewer for practically any kind of file suffix. Here I will demonstrate only an example for .md files:
let g:netrw_browsex_viewer="-"
function! NFH_md(f)
call asyncrun#run("", "cwd", "typora " . a:f)
endfunction
First paragraph makes sure to choose the function based on suffix of the file ("URI under cursor"). Second paragraph shows a function whose name i.e. NFH_md implies that this is the function opened when .md file is in the "URI under the cursor". Inside this function there is an call that opens an external program typora asynchronously so that I am still able to continue using Vim.
If you want to know more use :help netrw_browsex_viewer.
I tried porting the mentioned Vim script to Neovim & Lua but I only managed to port first line:
vim.g.netrw_browsex_viewer="-"
For I don't know, how to properly port the second paragraph. This is why for now I just use Vimscript source code like this:
vim.api.nvim_exec(
[[
function! NFH_md(f)
call asyncrun#run("", "cwd", "marktext " . a:f)
endfunction
]],
false
)
But I would love to translate all the code to Lua - Could anyone help a bit to translate this remaining Vimscript code to Lua?

Related

LibreOffice: embed script in script URL

In LibreOffice, It is possible to run python scripts like this:
sURL = "vnd.sun.star.script:file.function?language=Python&location=document"
oScript = scriptProv.getScript(sURL)
x = oScript.Invoke(args, Array(), Array())
In that example 'file' is a filename, and 'function' is the name of a function in that file.
Is it possible to embed script in that URL? sURL="vnd.." & scriptblock & "?language.."
(It seems like the kind of thing that might be possible with the correct URL, or might not be possible if just not supported).
We can use Python's eval() function. Here is an example inspired by JohnSUN's explanation in the discussion. Note: xray() uses XrayTool to show output, but you could replace that line with any output method of your choosing, such as writing to a file.
def runArbitraryCode(*args):
url = args[0]
codeString = url.split("&codeToRun=")[1]
x = eval(codeString)
xray(x)
Now enter this formula in Calc and Ctrl+click on it.
=HYPERLINK("vnd.sun.star.script:misc_examples.py$runArbitraryCode?language=Python&location=user&codeToRun=5+1")
Result: 6
Obligatory caveat: Running eval() on an unknown string is about the worst idea imaginable in terms of security. So hopefully you're the one controlling the URL and not some black hat hacker!

Using io.tmpfile() with shell command, ran via io.popen, in Lua?

I'm using Lua in Scite on Windows, but hopefully this is a general Lua question.
Let's say I want to write a temporary string content to a temporary file in Lua - which I want to be eventually read by another program, - and I tried using io.tmpfile():
mytmpfile = assert( io.tmpfile() )
mytmpfile:write( MYTMPTEXT )
mytmpfile:seek("set", 0) -- back to start
print("mytmpfile" .. mytmpfile .. "<<<")
mytmpfile:close()
I like io.tmpfile() because it is noted in https://www.lua.org/pil/21.3.html :
The tmpfile function returns a handle for a temporary file, open in read/write mode. That file is automatically removed (deleted) when your program ends.
However, when I try to print mytmpfile, I get:
C:\Users\ME/sciteLuaFunctions.lua:956: attempt to concatenate a FILE* value (global 'mytmpfile')
>Lua: error occurred while processing command
I got the explanation for that here Re: path for io.tmpfile() ?:
how do I get the path used to generate the temp file created by io.tmpfile()
You can't. The whole point of tmpfile is to give you a file handle without
giving you the file name to avoid race conditions.
And indeed, on some OSes, the file has no name.
So, it will not be possible for me to use the filename of the tmpfile in a command line that should be ran by the OS, as in:
f = io.popen("python myprog.py " .. mytmpfile)
So my questions are:
Would it be somehow possible to specify this tmpfile file handle as the input argument for the externally ran program/script, say in io.popen - instead of using the (non-existing) tmpfile filename?
If above is not possible, what is the next best option (in terms of not having to maintain it, i.e. not having to remember to delete the file) for opening a temporary file in Lua?
You can get a temp filename with os.tmpname.
local n = os.tmpname()
local f = io.open(n, 'w+b')
f:write(....)
f:close()
os.remove(n)
If your purpose is sending some data to a python script, you can also use 'w' mode in popen.
--lua
local f = io.popen(prog, 'w')
f:write(....)
#python
import sys
data = sys.stdin.readline()

How do I change the deafult require search directory for Lua?

I know this is possible because I have changed it before. I changed it to a custom directory that Lua checks for modules/libraries.
If you don't know what I'm saying, here's what I'm saying: I want to be able to change the directories Lua checks to find the file I'm trying to require.
For some reason, whenever I run require it doesn't check the current directory for the file. I have tried googling how to do it and no answers. The time when I changed this was when I was talking to someone who programmed Love2D and he walked me through the steps, but that conversation is gone and I can't find it.
Any help is appreciated, just let me know! And if you have any questions don't forget to ask!
Thanks!
You refer to the Lua 5.4 Reference Manual:
require
...
First require queries package.preload[modname]. If it has a value,
this value (which must be a function) is the loader. Otherwise require
searches for a Lua loader using the path stored in package.path. If
that also fails, it searches for a C loader using the path stored in
package.cpath. If that also fails, it tries an all-in-one loader (see
package.searchers).
Let's click on package.path
A string with the path used by require to search for a Lua loader.
At start-up, Lua initializes this variable with the value of the
environment variable LUA_PATH_5_4 or the environment variable LUA_PATH
or with a default path defined in luaconf.h, if those environment
variables are not defined. A ";;" in the value of the environment
variable is replaced by the default path.
So either you that string at runtime as you would modify any other string.
Or you change the value of your system variable LUA_PATH_5_4 in case you want to change it system wide.
I think you can figure out the rest yourself.
Just print package.path and have a look at what's inside.
My recommendation is to write a loader for path dependent require.
Because a script that modifies package.path and then loads another script that modifies also package.path ends up with a messy package.path.
A loader function in package.preload['name_of_loader_function'] returns in package.loaded
This is showing by a simple example...
( Shown in console: lua -i )
> package.preload['new_require']=function() return {'New to Lua?'} end
> newtab=require('new_require')
> table.concat(newtab)
New to Lua?
> table.concat(package.loaded.new_require)
New to Lua?
After that you can construct your loader with loadfile() and full path to your lua code.
But this time without extra () than it returns to package.loaded.
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
> package.preload['tprint']=loadfile('/tmp/tprint.lua')
> tprint=require('tprint')
> tprint(os)
Using pairs() for table print out
execute = function: 0x565d8a90
clock = function: 0x565d8b90
time = function: 0x565d8dc0
date = function: 0x565d8f60
remove = function: 0x565d8970
exit = function: 0x565d8a00
rename = function: 0x565d8910
difftime = function: 0x565d8b40
getenv = function: 0x565d89c0
setlocale = function: 0x565d88b0
tmpname = function: 0x565d8bd0
What was happen?
require checks package.preload for a loader for 'tprint'
require found and execute 'tprint' field function in package.preload
package.preload.tprint returning its value to package.loaded.tprint
require returns package.loaded.tprint to global tprint function
tprint is ready for use and typed with table argument prints out table keys/values
This works only if no package.loaded.tprint exists.
Because require() looks first in package.loaded.tprint and if absent in package.preload.tprint.

Lua io.write() not working

I am using a luvit Lua environment to run my lua code through my control panel. I am looking to write to a .txt file, but with the simple code that i am running, its not working.
The reason I wish to write to a .txt file is to log notices from my Discord Bot I am working on in the Discordia library.
I have a folder called MezzaBOT. In this file i have a write.lua file and also a log.txt file. I have this simple code in my write.lua file:
io.output('log.txt')
io.write('hello\n')
io.close()
I then run in my command promt with Luvit environment:
>luvit Desktop\mezzabot\write.lua
I don't get any errors but the log.txt file continues to stay empty. Am I missing a line in my code, or do i need to access log.txt differently?
edit: my new code is the following
file = io.open('log.txt')
file:write('hello', '\n')
file:close()
and it is not making a new line for each time with \n
edit B:
Ok, i found my problem, its creating a log.txt in my C:\Users\PC.
One other problem is when writing, its not making a new line with the \n. Can someone please help me?
Lua, by default, opens files in read mode. You need to explicitly open a file in write mode if you want to write to it (see manual)
file = io.open('log.txt', 'w')
file:write('hello', '\n')
file:close()
Should work :)

How do I make sure that a directory name is quoted in OMake?

I have a relatively complicated suite of OMake files designed for cross-compiling on a specific platform. My source is in C++.
I'm building from Windows and I need to pass to the compiler include directories which have spaces in their names. The way that the includes string which is inserted in the command line to compile files is created is by the line:
public.PREFIXED_INCLUDES = $`(addprefix $(INCLUDES_OPT), $(set $(absname $(INCLUDES))))
At some other point in the OMake files I have a line like:
INCLUDES += $(dir "$(LIBRARY_LOCATION)/Path with spaces/include")
In the middle of the command line this expands to:
-IC:\Library location with spaces\Path with spaces\include
I want it to expand to:
-I"C:\Library location with spaces\Path with spaces\include"
I don't want to change anything but the "INCLUDES += ..." line if possible, although modifying something else in that file is also fine. I don't want to have to do something like change the definition of PREFIXED_INCLUDES, as that's in a suite of OMake files which are part of an SDK which may change beneath me. Is this possible? If so, how can I do it? If not, in what ways can I make sure that includes with spaces in them are quoted by modifying little makefile code (hopefully one line)?
The standard library function quote adds escaped quotes around its argument, so it should do the job:
INCLUDES += $(quote $(dir "$(LIBRARY_LOCATION)/Path with spaces/include"))
If needed, see quote in Omake manual.
In case someone else is having the same problem, I thought I'd share the solution I eventually went with, having never figured out how to surround with quotes. Instead of putting quotes around a name with spaces in it I ended up converting the path to the short (8.3) version. I did this via a a simple JScript file called shorten.js and a one line OMake function.
The script:
// Get Access to the file system.
var FileSystemObject = WScript.CreateObject("Scripting.FileSystemObject");
// Get the short path.
var shortPath = FileSystemObject.GetFolder(WScript.Arguments(0)).ShortPath;
// Output short path.
WScript.StdOut.Write(shortPath);
The function:
ShortDirectoryPath(longPath) =
return $(dir $(shell cscript /Nologo $(dir ./tools/shorten.js) "$(absname $(longPath))"))
So now I just use a line like the following for includes:
INCLUDES += $(ShortDirectoryPath $(dir "$(LIBRARY_LOCATION)/Path with spaces/include"))

Resources