Device depending neovim configuration - lua

I have a short question.
Currently, I am spending (way too much time) modding my neovim setup.
I have multiple devices where I use my setup and sync those with git (second-best feature, after restoring my config every time I destroy everything) but there are some small differences in my configuration like plugins, which I don't need on my on-the-way-notebook.
Is there any way to differ in the lua configuration, on which device is currently running neovim?
Sure, multi-branching would be a way, but I'd like a more comfortable way.
Thanks for helping

You could use hostname to determine your device and use it to create configuration with conditions.
Lua code to get hostname :
local function get_hostname()
local f = io.popen ("/bin/hostname")
local hostname = f:read("*a") or ""
f:close()
hostname =string.gsub(hostname, "\n$", "")
return hostname
end
Neovim configuration :
if get_hostname() == "foo" then
do_something
else
do_otherthing
end

Related

Cross-platform method to get user's configuration home in Lua

The major operating systems seem to have a designated place to store configuration files.
On Linux it would be something like $HOME/.myprogram/data or $HOME/.config/myprogram/data, or perhaps a better practice would be to read $XDG_CONFIG_HOME.
On macOS it would be $HOME/.myprogram/data or $HOME/Library/Preferences/myprogram/data.
On Windows it would be %appdata%/myprogram/data.
How to get such value in a portable manner in Lua?
Check the existence condition of a variable with...
if (os.getenv('XDG_CONFIG_HOME')) then
os.execute('ls ' .. os.getenv('XDG_CONFIG_HOME'))
else -- Or: elseif (nextcondition) then
print('XDG_CONFIG_HOME', 'Not exists')
-- Maybe next check here?
end
But be aware that a user could start Lua with only that environment that Lua needs.
Like...
lua ()
{
env -i DISPLAY=:0 LANG='de_DE.UTF-8' TERM='xterm-256color' LUA_PATH='./lua/?.lua' LUA_CPATH='./lua/?.so' /usr/local/bin/lua "${#}"
}
Then check for XDG_CONFIG_HOME will allways fail.
Because above environment knows nothing about HOME, USER and XDG_CONFIG_HOME.
PS: I know a place too where my linux system saves configs/savegames or whatever
${HOME}/.local/share/

How can I reload my Neovim config written in lua with a shortcut?

I want to reload my neovim configuration files with just a couple of keystrokes instead of having to restart the app. I was able to do this when using an init.vim with the following command:
nnoremap <leader>sv <cmd>source $MYVIMRC<CR>
$MYVIMRC points correctly to my config entry point.
The problem is that I switched to using lua, and now I can't do the same. I have read the docs and tried variants of the following without success:
util.nnoremap("<leader>sv", "<cmd>luafile $MYVIMRC<CR>")
Finally, I found a solution doing this:
function load(name)
local path = vim.fn.stdpath('config') .. '/lua/' .. name .. '.lua'
dofile(path)
end
load('plugins')
load('config/mapping')
load('lsp/init')
Which is buggy and feels wrong.
Is there any way to do this? I read the example in vimpeccable, but I want to see the other available options since I would rather not install another plugin.
I know that plenary includes a function to reload modules, but I don't understand how to use it. A complete example of that would be good too since I already use plenary in my config.
I am a new Neovim user, so I guess my solution may not work for some edge cases.
This function flushes the module of current buffer:
local cfg = vim.fn.stdpath('config')
Flush = function()
local s = vim.api.nvim_buf_get_name(0)
if string.match(s, '^' .. cfg .. '*') == nil then
return
end
s = string.sub(s, 6 + string.len(cfg), -5)
local val = string.gsub(s, '%/', '.')
package.loaded[val] = nil
end
You can call it whenever you write to a buffer with this autocommand:
autocmd BufWrite *.lua,*vim call v:lua.Flush()
This way, after you execute :source $MYVIMRC it will also reload changed Lua modules.

why redis cannot execute non deterministic commands in lua script

SPOP is not allowed to be executed in lua. And if you do some non-deterministic commands firstly, then you is not allowed to execute write commands. This seems confusing to me. So why redis has such limitation?
It's explained fairly well in the Redis docs here.
The scripts are replicated to slaves by sending the script over and running it on the slave, so the script needs to always produce the same results every time it's run or the data on the slave will diverge from the data on the master.
You could try the new 'scripts effects replication' in the same link if you need perform non deterministic operations in a script.
you need to run this replicate commands function before any data changing command
redis.replicate_commands()
it's explained here
On a single Redis instance I cannot think about any negativ effect.
But say you're running some master-slave setup. the result of those lua scripts which calls e.g. TIME wouldn't be equal on the master.
you can act like what proposed at the last of error description
Additional information: ERR Error running script (call to
f_082d853d36ea323f47b6b00d36b7db66dac0bebd): #user_script:10:
#user_script: 10: Write commands not allowed after non deterministic
commands. Call redis.replicate_commands() at the start of your script
in order to switch to single commands replication mode.
Call redis.replicate_commands() at the start of your script in order to switch to single commands replication mode.
note that because of redis.call('time') call is non deterministic.
local function ticks(key,ticks)
redis.replicate_commands()
local t = ticks
local time = redis.call('time')
local last=redis.call('get',key..'_last')
if last==t then
local inc=redis.call('incr',key..'cnt')
t = t+inc
else
redis.call('set',key..'cnt',0)
end
redis.call('set',key..'_last',t)
return t
end
return ticks(#key,#ticks)

Reboot a System through Lua Script

I need to reboot System through a Lua Script.
I need to write some string before the Reboot happens and need to write a string in a Lua
script once the Reboot is done.
Example :
print("Before Reboot System")
Reboot the System through Lua script
print("After Reboot System")
How would I accomplish this?
You can use os.execute to issue system commands. For Windows, it's shutdown -r, for Posix systems it's just reboot. Your Lua code will therefore look like this:
Be aware that part of the reboot command is stopping active programs, like your Lua script. That means that any data stored in RAM will be lost. You need to write any data you want to keep to disk, using, for instance, table serialization.
Unfortunately, without more knowledge of your environment, I can't tell you how to call the script again. You could be able to append a call to your script to the end of ~/.bashrc or similar.
Make sure that loading this data and starting at a point after you call your reboot function is the first thing that you do when you come back! You don't want to get stuck in an endless reboot loop where the first thing your computer does when it turns on is to turn itself off. Something like this should work:
local function is_rebooted()
-- Presence of file indicates reboot status
if io.open("Rebooted.txt", "r") then
os.remove("Rebooted.txt")
return true
else
return false
end
end
local function reboot_system()
local f = assert(io.open("Rebooted.txt", "w"))
f:write("Restarted! Call On_Reboot()")
-- Do something to make sure the script is called upon reboot here
-- First line of package.config is directory separator
-- Assume that '\' means it's Windows
local is_windows = string.find(_G.package.config:sub(1,1), "\\")
if is_windows then
os.execute("shutdown -r");
else
os.execute("reboot")
end
end
local function before_reboot()
print("Before Reboot System")
reboot_system()
end
local function after_reboot()
print("After Reboot System")
end
-- Execution begins here !
if not is_rebooted() then
before_reboot()
else
after_reboot()
end
(Warning - untested code. I didn't feel like rebooting. :)
There is no way to do what you are asking in Lua. You may be able to do this using os.execute depending on your system and set up but Lua's libraries only include what is possible in the standard c libraries which does not include operating system specific functionality like restart.

How can I determine the OS of the system from within a Lua script?

Ok I need to determine the system's OS from a Lua script, but Lua as such has no API for this, so I use os.getenv() and query enviromental variables. On Windows checking the enviromental variable "OS" gives me the name of the system's OS, but is there some variable that exists on both Windows and most flavors of Unix that can be checked?
You can try package.config:sub(1,1). It returns the path separator, which is '\\' on Windows and '/' on Unixes...
On a Unix system, try os.capture 'uname' where os.capture is defined below:
function os.capture(cmd, raw)
local f = assert(io.popen(cmd, 'r'))
local s = assert(f:read('*a'))
f:close()
if raw then return s end
s = string.gsub(s, '^%s+', '')
s = string.gsub(s, '%s+$', '')
s = string.gsub(s, '[\n\r]+', ' ')
return s
end
This will help on all flavors of unix and on Mac OSX.
If it fails, you might be on a Windows system? Or check os.getenv 'HOME'.
When lua is compiled, it is configured slightly differently depending on what operating system it is compiled for.
Many of the strings which are set in the 'package' module can thus be used to distinguish which system it was compiled for.
For instance, when lua loads C-based modules which are distributed as dynamic libraries, it has to know the extension used for those libraries, which is different on each OS.
Thus, you can use a function like the following to determine the OS.
local BinaryFormat = package.cpath:match("%p[\\|/]?%p(%a+)")
if BinaryFormat == "dll" then
function os.name()
return "Windows"
end
elseif BinaryFormat == "so" then
function os.name()
return "Linux"
end
elseif BinaryFormat == "dylib" then
function os.name()
return "MacOS"
end
end
BinaryFormat = nil
I guess that if you just need Windows/Unix detection, you could check the filesystem for the existence of /etc or /bin or /boot directories. Aditionally, if you need to know which distro is it, most Linux distros have a little file in /etc showing the distro and version, sadly they all name it differently.
Unixes should have the $HOME variable (while Windows doesn't have that), so you can check it (after checking the OS variable is empty).
FWIW, the simplest function I can think of:
function MyScript:OS()
return package.config:sub(1,1) == "\\" and "win" or "unix"
end

Resources