From ab56f537957418dc7b6be1ad1ba46e092fa0fc6c Mon Sep 17 00:00:00 2001 From: Syed Daanish Date: Fri, 11 Sep 2026 13:39:48 +0100 Subject: [PATCH] Improve configs and minor bugs. --- config.rb | 186 +++++++++++++++++++++++++----------------- flake.nix | 2 + scripts/power.sh | 43 ++++++++++ scripts/run.sh | 28 +++++++ scripts/startup.sh | 8 ++ src/bindings/core.ml | 1 + src/bindings/ws_op.ml | 25 ++++++ src/mruby/bindings.ml | 4 + src/mruby/initial.ml | 124 ++-------------------------- src/shims.c | 40 ++++----- 10 files changed, 245 insertions(+), 216 deletions(-) create mode 100644 scripts/power.sh create mode 100644 scripts/run.sh create mode 100644 scripts/startup.sh diff --git a/config.rb b/config.rb index 776edf4..08ffa36 100644 --- a/config.rb +++ b/config.rb @@ -1,136 +1,174 @@ -# ==== State ==== +system 'bash ~/main/ocaml/epq/scripts/startup.sh >/dev/null 2>&1 &' -MAX_PROJECTS = 9 -SUBS = 2 # workspaces per project - -$current_project = 1 # 1..MAX_PROJECTS -$current_sub = 0 # 0..SUBS-1 - -# For each special workspace, remembers which workspace you were on -# before you jumped into it -- so hitting the mode key again toggles back. -$special_origin = {} +MAX_PROJECTS = 3 SPECIAL = { - terminal: { cmd: "kitty" }, - browser: { cmd: "firefox" }, - music: { cmd: "spotify" }, - misc: { cmd: nil }, # doesn't start anything - todo: { cmd: nil }, # doesn't start anything + term1: { cmd: 'kitty' }, + term2: { cmd: 'kitty' }, + browser: { cmd: 'firefox' }, + misc: { cmd: nil } } -# ==== Helpers ==== +$current = 0 -def project_ws(n, sub) - :"p#{n}_#{sub}" +$p_sub = Array.new(9, 0) + +def project_ws(n) + :"p#{n}_#{$p_sub[$current]}" end -def running?(process) - system("pgrep #{process} > /dev/null 2>&1") -end - -def go_project(n, sub) - $current_project = n - $current_sub = sub - jump_ws project_ws(n, sub) +def go_project(n) + $current = n + jump_ws project_ws($current) end def in_project?(ws) !SPECIAL.key?(ws) end -puts "hello1" - -# Toggle between a special-mode workspace (terminal/browser/music/misc/todo) -# and whatever workspace you were last on. Starts the associated app if -# it isn't already running. `ws` is the current workspace, passed in by -# the bind block (bind gives us (window, current_ws)). def go_special(name, ws) cfg = SPECIAL.fetch(name) if ws == name - target = $special_origin[name] || project_ws($current_project, $current_sub) + target = project_ws($current) jump_ws target else - $special_origin[name] = ws jump_ws name - system("#{cfg[:cmd]} >/dev/null 2>&1 &") if cfg[:cmd] && !running?(cfg[:cmd]) + system("#{cfg[:cmd]} >/dev/null 2>&1 &") if cfg[:cmd] && ws_empty?(name) end end -# ==== Untouched bindings ==== - -bind ?q do |x| +bind 'q' do |x| kill x end -bind ?w do - system "kitty >/dev/null 2>&1 &" +bind 'w' do + system 'kitty >/dev/null 2>&1 &' end -bind ?e do - exit +bind 'e' do + system 'bash ~/main/ocaml/epq/scripts/power.sh >/dev/null 2>&1 &' end -bind ?f do |x| +bind 'd' do + system 'bash ~/main/ocaml/epq/scripts/run.sh >/dev/null 2>&1 &' +end + +bind 'v' do + system 'CM_LAUNCHER=rofi clipmenu >/dev/null 2>&1 &' +end + +bind 'a' do + system 'bash', '-c', " + maim -c 0.3,0.5,1.0,0.8 -s | tee /tmp/screenshot_temp.png | xclip -selection clipboard -t image/png; + if [ -s '/tmp/screenshot_temp.png' ]; then + mv /tmp/screenshot_temp.png ~/screenshots/$(date +%Y-%m-%d_%H:%M:%S).png; + fi + " +end + +bind 123, :none do + system 'bash', '-c', %q( + pactl set-sink-volume @DEFAULT_SINK@ +5%; + vol=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -o '[0-9]\+%' | head -n1); + dunstify "Volume Adjusted" "" -h int:value:$vol -r 997 + ) +end + +bind 122, :none do + system 'bash', '-c', %q( + pactl set-sink-volume @DEFAULT_SINK@ -5%; + vol=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -o '[0-9]\+%' | head -n1); + dunstify "Volume Adjusted" "" -h int:value:$vol -r 997 + ) +end + +bind 121, :none do + system 'bash', '-c', %q( + pactl set-sink-mute @DEFAULT_SINK@ toggle; + vol=$(pactl get-sink-volume @DEFAULT_SINK@ | grep -o '[0-9]\+%' | head -n1); + dunstify "Volume Adjusted" "" -h int:value:$vol -r 997 + ) +end + +bind 232, :none do + system 'bash', '-c', %q( + brightnessctl set 5%-; + pct=$(brightnessctl -m | cut -d, -f4 | tr -d ' %'); + dunstify "Brightness" "" -h int:value:$pct -r 998 + ) +end + +bind 233, :none do + system 'bash', '-c', %q( + brightnessctl set 5%+; + pct=$(brightnessctl -m | cut -d, -f4 | tr -d ' %'); + dunstify "Brightness" "" -h int:value:$pct -r 998 + ) +end + +bind 'x' do + system 'kitty -e fish -c "editor" >/dev/null 2>&1 &' +end + +bind 'c' do + system 'kitty -e fish -c "y" >/dev/null 2>&1 &' +end + +bind 's' do |x| toggle_float x end -# ==== Mode switches ==== - -bind ?[ do |_, ws| - go_special :terminal, ws +bind 'f' do + system 'kitty -e fish -c "btop" >/dev/null 2>&1 &' end -bind ?] do |_, ws| - go_special :misc, ws +bind '[' do |_, ws| + go_special :term1, ws end -bind "tab" do |_, ws| +bind ']' do |_, ws| + go_special :term2, ws +end + +bind 79, :none do |_, ws| go_special :browser, ws end bind 89 do |_, ws| - go_special :music, ws + go_special :misc, ws end -bind 81 do |_, ws| - go_special :todo, ws +bind 118, :none do + system 'bash', '-c', + 'dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause >/dev/null 2>&1 &' end -puts "hello2" - -# ==== Project navigation ==== - -(1..MAX_PROJECTS).each do |n| - bind n.to_s do - go_project(n, $current_sub) +(0..MAX_PROJECTS - 1).each do |n| + bind (n + 1).to_s do + go_project(n) end end bind 86, :none do |_, ws| next unless in_project?(ws) - n = (($current_project - 2) % MAX_PROJECTS) + 1 - go_project(n, $current_sub) + + n = (($current - 1 + MAX_PROJECTS) % MAX_PROJECTS) + go_project(n) end bind 82, :none do |_, ws| next unless in_project?(ws) - n = ($current_project % MAX_PROJECTS) + 1 - go_project(n, $current_sub) -end -bind 79, :none do |_, ws| - next unless in_project?(ws) - go_project($current_project, ($current_sub + 1) % SUBS) + n = (($current + 1) % MAX_PROJECTS) + go_project(n) end bind 80, :none do |_, ws| next unless in_project?(ws) - go_project($current_project, ($current_sub - 1 + SUBS) % SUBS) + + $p_sub[$current] = $p_sub[$current] == 1 ? 0 : 1 + go_project($current) end -# ==== Startup ==== - -go_project(1, 0) - -puts "hello3" +go_project(0) diff --git a/flake.nix b/flake.nix index b2036e2..18f29ce 100644 --- a/flake.nix +++ b/flake.nix @@ -100,6 +100,8 @@ ocamlPackages.utop ocamlPackages.ocaml-lsp ocamlPackages.ocamlformat + clang-tools + solargraph ]; shellHook = '' diff --git a/scripts/power.sh b/scripts/power.sh new file mode 100644 index 0000000..75917f8 --- /dev/null +++ b/scripts/power.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +set -euo pipefail + +opts=" Lock +󰒲 Suspend + Shutdown +󰜉 Reboot + Hibernate + Stop KutuWM" + +sel=$(printf "%s\n" "$opts" | dmenu -i -p "Select Power Option:" \ + -nf '#e0af68' -nb '#1f2335' -sb '#f7768e' -sf '#1a1b26' -fn 'AgaveNerdFont-16') + +[ -z "$sel" ] && exit 0 + +case "$sel" in +*Shutdown*) + confirm=$(printf "No\nYes" | dmenu -i -p "Are you sure you want to shutdown? :" \ + -nf '#e0af68' -nb '#1f2335' -sb '#f7768e' -sf '#1a1b26' -fn 'AgaveNerdFont-16') + [ "$confirm" = "Yes" ] && exec shutdown -h now + ;; +*Reboot*) + confirm=$(printf "No\nYes" | dmenu -i -p "Are you sure you want to reboot? :" \ + -nf '#e0af68' -nb '#1f2335' -sb '#f7768e' -sf '#1a1b26' -fn 'HurmitNerdFont-16') + [ "$confirm" = "Yes" ] && exec reboot + ;; +*Hibernate*) + confirm=$(printf "No\nYes" | dmenu -i -p "Are you sure you want to hibernate? :" \ + -nf '#e0af68' -nb '#1f2335' -sb '#f7768e' -sf '#1a1b26' -fn 'AgaveNerdFont-16') + [ "$confirm" = "Yes" ] && exec systemctl --system hibernate + ;; +*Stop\ KutuWM*) + #exec kutu-run.rb stop TODO. + pkill X + ;; +*Suspend*) + exec systemctl --system suspend + ;; +*Lock*) + ~/dotfiles/scripts/lock.sh & + ;; +esac diff --git a/scripts/run.sh b/scripts/run.sh new file mode 100644 index 0000000..2f2b12f --- /dev/null +++ b/scripts/run.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +declare -A aliases=( + [editor]="kitty -e fish -c editor" + [yazi]="kitty -e fish -c yazi" + [btop]="kitty -e fish -c btop" +) + +choice=$( + { + printf '%s\n' "${!aliases[@]}" + compgen -c + } | + grep -v -E '^(\..*|if|fi|case|esac|for|done|while|until|select|function|return|continue|break|time|exec|source|alias|builtin|read|export|unset|local|set|declare|typeset|:|\.|\[|coproc|l|ll|ls|then|else|elif|do|in|\{|\}|!|\[\[|\]\]|_.*|compgen)$' | + sort -u | + dmenu -i -p "Enter command  " \ + -nf '#4abaaf' -nb '#1f2335' -sb '#7aa2f7' -sf '#102030' -fn 'AgaveNerdFont-16' +) + +[ -z "$choice" ] && exit 0 + +if [[ -v "aliases[$choice]" ]]; then + eval "${aliases[$choice]}" >/dev/null 2>&1 & +else + "$choice" >/dev/null 2>&1 & +fi + +disown diff --git a/scripts/startup.sh b/scripts/startup.sh new file mode 100644 index 0000000..57b96b1 --- /dev/null +++ b/scripts/startup.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +xset s off +xset -dpms + +xsetroot -cursor_name left_ptr + +setxkbmap us diff --git a/src/bindings/core.ml b/src/bindings/core.ml index 7bdc439..4d18813 100644 --- a/src/bindings/core.ml +++ b/src/bindings/core.ml @@ -17,5 +17,6 @@ let register_callbacks state = Window_op.register_toggle_float state; Ws_op.register_jump state; Ws_op.register_ws_count state; + Ws_op.register_ws_empty state; Keybinds.register_bind state; Keybinds.register_unbind state diff --git a/src/bindings/ws_op.ml b/src/bindings/ws_op.ml index 2c4a0f3..2542409 100644 --- a/src/bindings/ws_op.ml +++ b/src/bindings/ws_op.ml @@ -61,3 +61,28 @@ let register_ws_count (state : Kutu.State.wm_state) = Mruby.Bindings.mrb_define_method state.mrb (Mruby.Types.Mrb_state.get_object_class state.mrb) "ws_count" ws_count (Unsigned.UInt32.of_int 0) + +let register_ws_empty (state : Kutu.State.wm_state) = + let mrb_get_args = + foreign "mrb_get_args" + (ptr Mruby.Types.Mrb_state.typ + @-> string + @-> ptr Mruby.Types.Mrb_sym.typ + @-> returning int) + in + let ws_empty (mrb : Mruby.Types.Mrb_state.t structure ptr) + (self : Mruby.Types.Mrb_value.t structure) = + let name = allocate Mruby.Types.Mrb_sym.typ (Unsigned.UInt32.of_int 0) in + ignore (mrb_get_args mrb "n" name); + let name = Mruby.Bindings.mrb_sym_name mrb !@name in + match Hashtbl.find_opt state.workspaces name with + | Some ws -> + let is_empty = ws.ws_root = None && List.is_empty ws.ws_fwindows in + Mruby.Bindings.mrb_bool_value + (Unsigned.UInt32.of_int (if is_empty then 1 else 0)) + | None -> Mruby.Bindings.mrb_bool_value (Unsigned.UInt32.of_int 1) + in + Mruby.Bindings.mrb_define_method state.mrb + (Mruby.Types.Mrb_state.get_object_class state.mrb) + "ws_empty?" ws_empty + (Mruby.Bindings.mrb_args_req 1) diff --git a/src/mruby/bindings.ml b/src/mruby/bindings.ml index 06fe824..78024fa 100644 --- a/src/mruby/bindings.ml +++ b/src/mruby/bindings.ml @@ -28,6 +28,10 @@ let mrb_int_value = foreign "kutu_mrb_int_value" (ptr Types.Mrb_state.typ @-> uint32_t @-> returning Types.Mrb_value.typ) +let mrb_bool_value = + foreign "kutu_mrb_bool_value" + (uint32_t @-> returning Types.Mrb_value.typ) + let mrb_intern_cstr = foreign "mrb_intern_cstr" (ptr Types.Mrb_state.typ @-> string @-> returning Types.Mrb_sym.typ) diff --git a/src/mruby/initial.ml b/src/mruby/initial.ml index 36fea1e..78a94fa 100644 --- a/src/mruby/initial.ml +++ b/src/mruby/initial.ml @@ -13,10 +13,15 @@ KEY_MAP = { "e" => 26, "r" => 27, "f" => 41, + "s" => 39, + "a" => 38, + "d" => 40, "n" => 57, "b" => 56, "m" => 58, "v" => 55, + "x" => 53, + "c" => 54, "]" => 35, "[" => 34, "1" => 10, @@ -34,65 +39,6 @@ KEY_MAP = { CONFIG_FILE = "%s" DEFAULT = <<'CODE' -# ==== State ==== - -MAX_PROJECTS = 9 -SUBS = 2 # workspaces per project - -$current_project = 1 # 1..MAX_PROJECTS -$current_sub = 0 # 0..SUBS-1 - -# For each special workspace, remembers which workspace you were on -# before you jumped into it -- so hitting the mode key again toggles back. -$special_origin = {} - -SPECIAL = { - terminal: { cmd: "kitty" }, - browser: { cmd: "firefox" }, - music: { cmd: "spotify" }, - misc: { cmd: nil }, # doesn't start anything - todo: { cmd: nil }, # doesn't start anything -} - -# ==== Helpers ==== - -def project_ws(n, sub) - :"p#{n}_#{sub}" -end - -def running?(process) - system("pgrep #{process} > /dev/null 2>&1") -end - -def go_project(n, sub) - $current_project = n - $current_sub = sub - jump_ws project_ws(n, sub) -end - -def in_project?(ws) - !SPECIAL.key?(ws) -end - -# Toggle between a special-mode workspace (terminal/browser/music/misc/todo) -# and whatever workspace you were last on. Starts the associated app if -# it isn't already running. `ws` is the current workspace, passed in by -# the bind block (bind gives us (window, current_ws)). -def go_special(name, ws) - cfg = SPECIAL.fetch(name) - - if ws == name - target = $special_origin[name] || project_ws($current_project, $current_sub) - jump_ws target - else - $special_origin[name] = ws - jump_ws name - system("#{cfg[:cmd]} >/dev/null 2>&1 &") if cfg[:cmd] && !running?(cfg[:cmd]) - end -end - -# ==== Untouched bindings ==== - bind ?q do |x| kill x end @@ -104,66 +50,6 @@ end bind ?e do exit end - -bind ?f do |x| - toggle_float x -end - -# ==== Mode switches ==== - -bind ?[ do |_, ws| - go_special :terminal, ws -end - -bind ?] do |_, ws| - go_special :misc, ws -end - -bind "tab" do |_, ws| - go_special :browser, ws -end - -bind 89 do |_, ws| - go_special :music, ws -end - -bind 81 do |_, ws| - go_special :todo, ws -end - -# ==== Project navigation ==== - -(1..MAX_PROJECTS).each do |n| - bind n.to_s do - go_project(n, $current_sub) - end -end - -bind 86, :none do |_, ws| - next unless in_project?(ws) - n = (($current_project - 2) %% MAX_PROJECTS) + 1 - go_project(n, $current_sub) -end - -bind 82, :none do |_, ws| - next unless in_project?(ws) - n = ($current_project %% MAX_PROJECTS) + 1 - go_project(n, $current_sub) -end - -bind 79, :none do |_, ws| - next unless in_project?(ws) - go_project($current_project, ($current_sub + 1) %% SUBS) -end - -bind 80, :none do |_, ws| - next unless in_project?(ws) - go_project($current_project, ($current_sub - 1 + SUBS) %% SUBS) -end - -# ==== Startup ==== - -go_project(1, 0) CODE BINDINGS = [] diff --git a/src/shims.c b/src/shims.c index f25aa02..355aaf5 100644 --- a/src/shims.c +++ b/src/shims.c @@ -1,30 +1,24 @@ +#include +#include +#include +#include #include #include -#include -#include -#include -mrb_value -kutu_mrb_int_value(mrb_state *mrb, uint64_t value) -{ - return mrb_int_value(mrb, (mrb_int)value); +mrb_value kutu_mrb_int_value(mrb_state *mrb, uint32_t value) { + return mrb_int_value(mrb, (mrb_int)value); } -mrb_value -kutu_mrb_symbol_value(mrb_sym i) -{ - return mrb_symbol_value(i); -} +mrb_value kutu_mrb_symbol_value(mrb_sym i) { return mrb_symbol_value(i); } -void -kutu_mrb_load_file(mrb_state *mrb, const char *filename) -{ - FILE *file = fopen(filename, "rb"); - if (file == NULL) { - mrb_raisef(mrb, E_RUNTIME_ERROR, - "could not open file: %s", filename); - return; - } - mrb_load_file(mrb, file); - fclose(file); +mrb_value kutu_mrb_bool_value(uint32_t b) { return mrb_bool_value(b); } + +void kutu_mrb_load_file(mrb_state *mrb, const char *filename) { + FILE *file = fopen(filename, "rb"); + if (file == NULL) { + mrb_raisef(mrb, E_RUNTIME_ERROR, "could not open file: %s", filename); + return; + } + mrb_load_file(mrb, file); + fclose(file); }