Can not make binds work with Lua

Hi. First off, I am new of this year to Linux and have only used Hyprland for 3 weeks or so, but like it and want to rice it.

I have had few problems, only icons in waybar not working until the lua change. I thought I would change to lua now, rather than continue ricing in soon obsolete hyprlang. Everything went supersmooth, following the wiki and making a new set of configs.

But the binds.lua, referenced with require() from hyprland.lua has given me a headache. Any one had similar problems or can spot the problem? Any input would be appreciated :smile: I run CachyOS with Hyprland 0.55.1

Binds do not work and I always get the same message, even with the official config example.

require (modules.binds"): bad argument #1 to ‘?’ (string expected, got nil)

I tried to move everything from binds.lua into hyprland.lua and then got this error message instead:

Your config has errors: bad argument #1 to ‘?’ (string expected, got nil)

stack trackback:

[C]: in ?

[C]: in field ‘exec_cmd’

(1 more…)

Also worth noting I have tried to change from UWSM-manager to Hyprland but the same result there. And somehow, the emergency shortcuts no longer works either. I have to keep my Vivaldi windows open to be able to trick myself into the terminal and file manager/kate. If I closed these now, I would be stuck I guess :sweat_smile:

hyprland.lua :

require(“modules.monitors”)
require(“modules.programs”)
require(“modules.binds”)
require(“modules.autostart”)
require(“modules.env”)
require(“modules.decorations”)
require(“modules.animations”)
require(“modules.windowrules”)
require(“modules.layout”)
require(“modules.misc”)
require(“modules.input”)

modules/ Binds.lua

hl.exec_cmd(“dbus-update-activation-environment --systemd --all”)
hl.exec_cmd(“systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP”)

local mainMod = “SUPER”
local closeWindowBind = hl.bind(mainMod .. " + C", hl.dsp.window.close())
– closeWindowBind:set_enabled(false)

hl.bind(mainMod .. " + Q", hl.dsp.exec_cmd(terminal))

– hl.bind(mainMod .. " + A", hl.dsp.exec_cmd(waybar/scripts/launch.sh))

hl.bind(mainMod .. " + A", hl.dsp.exec_cmd(“pkill waybar; waybar &”))
hl.bind(mainMod .. " + B", hl.dsp.exec_cmd(swaync-client -t))
hl.bind(mainMod .. " + D", hl.dsp.exec_cmd(menu))
hl.bind(mainMod .. " + E", hl.dsp.exec_cmd(fileManager))
hl.bind(mainMod .. " + F", hl.dsp.exec_cmd(Fullscreen))
–hl.bind(mainMod .. " + H", hl.dsp.exec_cmd(cliphist list | rofi -dmenu -display-columns 2 -p “Clipboard” -theme ~/.config/rofi/style-1.rasi | cliphist decode | wl-copy))
hl.bind(mainMod .. " + J", hl.dsp.layout(“togglesplit”)) – dwindle only
hl.bind(mainMod .. " + M", hl.dsp.exec_cmd(wlogout))
hl.bind(mainMod .. " + P", hl.dsp.window.pseudo())
hl.bind(mainMod .. " + R", hl.dsp.exec_cmd(pwvucontrol))

– Example special workspace (scratchpad)
hl.bind(mainMod .. " + S", hl.dsp.workspace.toggle_special(“magic”))
hl.bind(mainMod .. " + SHIFT + S", hl.dsp.window.move({ workspace = “special:magic” }))
hl.bind(mainMod .. " + T", hl.dsp.exec_cmd(cachyos-pi))
hl.bind(mainMod .. " + V", hl.dsp.window.float({ action = “toggle” }))
hl.bind(mainMod .. " + W", hl.dsp.exec_cmd(killactive))
hl.bind(mainMod .. " + Z", hl.dsp.exec_cmd(vivaldi))

– Normal Binds :
– hl.bind(“Print”, hl.dsp.exec_cmd(hyprshot -m region -o ~/Pictures/Screenshots))

– To switch between windows in a floating workspace:
hl.bind(“SUPER + Tab”, function()
hl.dispatch(hl.dsp.window.cycle_next()) – Change focus to another window
hl.dispatch(hl.dsp.window.bring_to_top()) – Bring it to the top
end)

– Move focus with mainMod + arrow keys
hl.bind(mainMod .. " + left", hl.dsp.focus({ direction = “left” }))
hl.bind(mainMod .. " + right", hl.dsp.focus({ direction = “right” }))
hl.bind(mainMod .. " + up", hl.dsp.focus({ direction = “up” }))
hl.bind(mainMod .. " + down", hl.dsp.focus({ direction = “down” }))

– Switch workspaces with mainMod + [0-9]
– Move active window to a workspace with mainMod + SHIFT + [0-9]
for i = 1, 10 do
local key = i % 10 – 10 maps to key 0
hl.bind(mainMod .. " + " .. key, hl.dsp.focus({ workspace = i}))
hl.bind(mainMod .. " + SHIFT + " .. key, hl.dsp.window.move({ workspace = i }))
end

-- Scroll through existing workspaces with mainMod + scroll
hl.bind(mainMod .. " + mouse_down", hl.dsp.focus({ workspace = "e+1" }))
hl.bind(mainMod .. " + mouse_up",   hl.dsp.focus({ workspace = "e-1" }))

-- Move/resize windows with mainMod + LMB/RMB and dragging
hl.bind(mainMod .. " + mouse:272", hl.dsp.window.drag(),   { mouse = true })
hl.bind(mainMod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true })

-- Laptop multimedia keys for volume and LCD brightness
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"), { locked = true, repeating = true })
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"),      { locked = true, repeating = true })
hl.bind("XF86AudioMute",        hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"),     { locked = true, repeating = true })
hl.bind("XF86AudioMicMute",     hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"),   { locked = true, repeating = true })
hl.bind("XF86MonBrightnessUp",  hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%+"),                  { locked = true, repeating = true })
hl.bind("XF86MonBrightnessDown",hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%-"),                  { locked = true, repeating = true })

-- Requires playerctl
hl.bind("XF86AudioNext",  hl.dsp.exec_cmd("playerctl next"),       { locked = true })
hl.bind("XF86AudioPause", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true })
hl.bind("XF86AudioPlay",  hl.dsp.exec_cmd("playerctl play-pause"), { locked = true })
hl.bind("XF86AudioPrev",  hl.dsp.exec_cmd("playerctl previous"),   { locked = true })

Yes, you have quite a few instances of bad syntax:

hl.bind(mainMod .. " + T", hl.dsp.exec_cmd(cachyos-pi))

is bad. You forgot quotes around the literal, "cachyos-pi".

Thank you!!! I was blind, but now I can see :grin: :blue_heart:

Yes, that did the trick!!

Edit:

Inserting quotes for values after exec.cmd removes hyprland error message.

And half the binds works.

But some do not, and if I do not put all in quotes, including terminal, menu etc, I get the error message.

Thus, menu, terminal, filemanager, killactive, fullscreen do not work. Is there some other syntax I have wrong here? Terminal, filemanager and menu is set as default programs in programs.lua and have quotes.

I now moved the local lines into the top of the binds.lua

Otherwise the ones that can not have quotes will give error warning and binds will fail.

That is very strange, but works. Local references seem to have a problem not being on top in the lua file with the binds.

That still leaves some not working:

Fullscreen, killactive, togglesplit,

I can delete killactive and do not really need togglesplit. But Fullscreen would be nice.

Tried another syntax but it gave an error for me, but not for the owner of the config, it seems.

hl.bind(mainMod .. " + F", hl.dsp.window.fullscreen({ mode = “fullscreen”, action = “toggle” }))

For me this gives unexpected symbol error.

Edit:

To get working binds this was in the end the recipie:

  1. Quotes for values on exec.cmd() except for the default programs.
  2. Move both default programs and binds into main config and remove require() for those.
  3. Put locals on top before the hl. sections. in binds chapter.

This is now my hyprland.lua:

----- CONFIG -----

---- MY SOURCING FILES ----

require(“modules.monitors”)


---- MY PROGRAMS ----

local terminal = “kitty”
local fileManager = “dolphin”
local menu = “pkill rofi || bash ~/.config/rofi/launcher.sh”

– example from other user to look at :
– local applauncher = “rofi -show drun -show-icons -theme”
– local idlehandler = “swayidle -w timeout 300 ‘swaylock -f -c 000000’ before-sleep ‘swaylock -f -c 000000’ timeout 600 ‘hyprctl dispatch dpms off’ resume ‘hyprctl dispatch dpms on’”
– local capturing = “XDG_CURRENT_DESKTOP=Sway flameshot gui -r | wl-copy”
– local theme = “~/Downloads/rounded-nord-dark.rasi”
– local theme1 = “~/Downloads/launchpad.rasi”


---- KEYBINDINGS ----

– Binds – Hyprland Wiki

local mainMod = “SUPER”
local closeWindowBind = hl.bind(mainMod .. " + C", hl.dsp.window.close())
– closeWindowBind:set_enabled(false)

hl.exec_cmd(“dbus-update-activation-environment --systemd --all”)
hl.exec_cmd(“systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP”)

hl.bind(mainMod .. " + Q", hl.dsp.exec_cmd(terminal))
hl.bind(mainMod .. " + A", hl.dsp.exec_cmd(“pkill waybar; waybar &”))
hl.bind(mainMod .. " + SHIFT + A", hl.dsp.exec_cmd(“waybar/scripts/launch.sh”))
hl.bind(mainMod .. " + B", hl.dsp.exec_cmd(“swaync-client -t”))
hl.bind(mainMod .. " + D", hl.dsp.exec_cmd(menu))
hl.bind(mainMod .. " + E", hl.dsp.exec_cmd(fileManager))
hl.bind(mainMod .. " + M", hl.dsp.window.fullscreen({ mode = “maximized”, action = “toggle” }))
hl.bind(mainMod .. " + F", hl.dsp.window.fullscreen({ mode = “fullscreen”, action = “toggle” }))
hl.bind(mainMod .. " + H", hl.dsp.exec_cmd(“cliphist list | rofi -dmenu -display-columns 2 -p Clipboard theme ~/.config/rofi/style-1.rasi | cliphist decode | wl-copy”))
hl.bind(mainMod .. " + J", hl.dsp.layout(“togglesplit”)) – dwindle only
hl.bind(mainMod .. " + M", hl.dsp.exec_cmd(“wlogout”))
hl.bind(mainMod .. " + P", hl.dsp.window.pseudo())
hl.bind(mainMod .. " + R", hl.dsp.exec_cmd(“pwvucontrol”))

– Example special workspace (scratchpad)
hl.bind(mainMod .. " + S", hl.dsp.workspace.toggle_special(“magic”))
hl.bind(mainMod .. " + SHIFT + S", hl.dsp.window.move({ workspace = “special:magic” }))
hl.bind(mainMod .. " + T", hl.dsp.exec_cmd(“cachyos-pi”))
hl.bind(mainMod .. " + V", hl.dsp.window.float({ action = “toggle” }))
hl.bind(mainMod .. " + W", hl.dsp.exec_cmd(“killactive”))
hl.bind(mainMod .. " + Z", hl.dsp.exec_cmd(“vivaldi”))

– Normal Binds :
hl.bind(“Print”, hl.dsp.exec_cmd(“hyprshot -m region -o ~/Pictures/Screenshots”))

– Switch workspaces with mainMod + [0-9]
– Move active window to a workspace with mainMod + SHIFT + [0-9]
for i = 1, 10 do
local key = i % 10 – 10 maps to key 0
hl.bind(mainMod .. " + " .. key, hl.dsp.focus({ workspace = i}))
hl.bind(mainMod .. " + SHIFT + " .. key, hl.dsp.window.move({ workspace = i }))
end

-- To switch between windows in a floating workspace:
hl.bind("SUPER + Tab", function()
hl.dispatch(hl.dsp.window.cycle_next())    -- Change focus to another window
hl.dispatch(hl.dsp.window.bring_to_top())  -- Bring it to the top
end)

-- Move focus with mainMod + arrow keys
hl.bind(mainMod .. " + left",  hl.dsp.focus({ direction = "left" }))
hl.bind(mainMod .. " + right", hl.dsp.focus({ direction = "right" }))
hl.bind(mainMod .. " + up",    hl.dsp.focus({ direction = "up" }))
hl.bind(mainMod .. " + down",  hl.dsp.focus({ direction = "down" }))

-- Scroll through existing workspaces with mainMod + scroll
hl.bind(mainMod .. " + mouse_down", hl.dsp.focus({ workspace = "e+1" }))
hl.bind(mainMod .. " + mouse_up",   hl.dsp.focus({ workspace = "e-1" }))

-- Move/resize windows with mainMod + LMB/RMB and dragging
hl.bind(mainMod .. " + mouse:272", hl.dsp.window.drag(),   { mouse = true })
hl.bind(mainMod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true })

-- Laptop multimedia keys for volume and LCD brightness
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"), { locked = true, repeating = true })
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"),      { locked = true, repeating = true })
hl.bind("XF86AudioMute",        hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"),     { locked = true, repeating = true })
hl.bind("XF86AudioMicMute",     hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"),   { locked = true, repeating = true })
hl.bind("XF86MonBrightnessUp",  hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%+"),                  { locked = true, repeating = true })
hl.bind("XF86MonBrightnessDown",hl.dsp.exec_cmd("brightnessctl -e4 -n2 set 5%-"),                  { locked = true, repeating = true })

-- Requires playerctl
hl.bind("XF86AudioNext",  hl.dsp.exec_cmd("playerctl next"),       { locked = true })
hl.bind("XF86AudioPause", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true })
hl.bind("XF86AudioPlay",  hl.dsp.exec_cmd("playerctl play-pause"), { locked = true })
hl.bind("XF86AudioPrev",  hl.dsp.exec_cmd("playerctl previous"),   { locked = true })

– require(“hypridle.conf”)
require(“modules.autostart”)
require(“modules.env”)
require(“modules.decorations”)
require(“modules.animations”)
require(“modules.windowrules”)
require(“modules.layout”)
require(“modules.misc”)
require(“modules.input”)

This is my working fullscreen toggle:

hl.bind(mainMod .. " + SHIFT + F", hl.dsp.window.fullscreen({ action = “toggle” }))