Compare commits

...

10 commits

91 changed files with 15758 additions and 248 deletions

View file

@ -18,10 +18,10 @@ hilbish.appendPath('~/.rye/shims')
hilbish.appendPath('/usr/local/bin') hilbish.appendPath('/usr/local/bin')
hilbish.appendPath('/opt/local/bin') hilbish.appendPath('/opt/local/bin')
local hinter = require('.hinter') --local hinter = require('.hinter')
local syntax = require('.syntax') local syntax = require('.syntax')
local fish_completer = require('.fish_completer') --local fish_completer = require('.fish_completer')
--local carapace_completer = require('.carapace') local carapace_completer = require('.carapace')
local starship = require('.starship') local starship = require('.starship')
require('homebrew') require('homebrew')
@ -54,12 +54,11 @@ hilbish.aliases.add('lla', 'exa --long --all')
hilbish.aliases.add('lt', 'exa --icons --tree') hilbish.aliases.add('lt', 'exa --icons --tree')
hilbish.aliases.add('lta', 'exa --icons --tree --all') hilbish.aliases.add('lta', 'exa --icons --tree --all')
-- dotfile management hilbish.aliases.add('mnt', 'udisksctl mount -b')
hilbish.aliases.add('dotfiles', 'git --git-dir=' .. home_dir .. '/workspace/dippin-dotfiles/ --work-tree=' .. home_dir .. '/') hilbish.aliases.add('umnt', 'udisksctl unmount -b')
-- Other environment variables -- Other environment variables
os.setenv("KAKOUNE_POSIX_SHELL", "/bin/dash") os.setenv("KAKOUNE_POSIX_SHELL", "/usr/bin/dash")
os.setenv("CARAPACE_BRIDGES", "zsh,fish,bash,inshellisense") os.setenv("CARAPACE_BRIDGES", "zsh,fish,bash,inshellisense")
-- Syntax highlighting -- Syntax highlighting
@ -68,10 +67,10 @@ function hilbish.highlighter(line)
end end
-- Hinter -- Hinter
function hilbish.hinter(line, _) --function hilbish.hinter(line, _)
return hinter.hinter(line) -- return hinter.hinter(line)
end --end
-- Completers -- Completers
hilbish.complete('command.git', fish_completer.fish_completer) hilbish.complete('command.git', carapace_completer.complete_func)
hilbish.complete('command.pacman', fish_completer.fish_completer) hilbish.complete('command.pacman', carapace_completer.complete_func)

156
.config/hypr/hyprland.conf Normal file
View file

@ -0,0 +1,156 @@
monitor = DP-1, 1920x1080, 1920x0, 1
monitor = DP-2, 1920x1080, 0x0, 1
$terminal = wezterm
$menu = wofi --show drun
$locker = hyprlock
exec-once = waybar & hyprpaper
exec-once = hyprpm reload -n
env = XCURSOR_SIZE,24
env = HYPRCURSOR_SIZE,24
general {
gaps_in = 5
gaps_out = 20
border_size = 2
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
col.inactive_border = rgba(595959aa)
resize_on_border = false
allow_tearing = false
layout = hy3
}
decoration {
rounding = 10
rounding_power = 2
active_opacity = 1.0
inactive_opacity = 1.0
shadow {
enabled = true
range = 4
render_power = 3
color = rgba(1a1a1aee)
}
blur {
enabled = true
size = 3
passes = 1
vibrancy = 0.1696
}
}
animations {
enabled = yes, please :)
bezier = easeOutQuint,0.23,1,0.32,1
bezier = easeInOutCubic,0.65,0.05,0.36,1
bezier = linear,0,0,1,1
bezier = almostLinear,0.5,0.5,0.75,1.0
bezier = quick,0.15,0,0.1,1
animation = global, 1, 10, default
animation = border, 1, 5.39, easeOutQuint
animation = windows, 1, 4.79, easeOutQuint
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
animation = windowsOut, 1, 1.49, linear, popin 87%
animation = fadeIn, 1, 1.73, almostLinear
animation = fadeOut, 1, 1.46, almostLinear
animation = fade, 1, 3.03, quick
animation = layers, 1, 3.81, easeOutQuint
animation = layersIn, 1, 4, easeOutQuint, fade
animation = layersOut, 1, 1.5, linear, fade
animation = fadeLayersIn, 1, 1.79, almostLinear
animation = fadeLayersOut, 1, 1.39, almostLinear
animation = workspaces, 1, 1.94, almostLinear, fade
animation = workspacesIn, 1, 1.21, almostLinear, fade
animation = workspacesOut, 1, 1.94, almostLinear, fade
}
input {
kb_layout = us
kb_variant =
kb_model =
kb_options =
kb_rules =
follow_mouse = 1
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
touchpad {
natural_scroll = false
}
}
gestures {
workspace_swipe = false
}
plugin {
hy3 {
}
}
$mainMod = SUPER # Sets "Windows" key as main modifier
bind = $mainMod, Return, exec, $terminal
bind = $mainMod, C, killactive,
bind = $mainMod, M, exit,
bind = $mainMod, V, togglefloating,
bind = $mainMod, D, exec, $menu
bind = $mainMod, L, exec, $locker
bind = $mainMod, left, hy3:movefocus, l
bind = $mainMod, right, hy3:movefocus, r
bind = $mainMod, up, hy3:movefocus, u
bind = $mainMod, down, hy3:movefocus, d
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
bind = $mainMod SHIFT, 4, movetoworkspace, 4
bind = $mainMod SHIFT, 5, movetoworkspace, 5
bind = $mainMod SHIFT, 6, movetoworkspace, 6
bind = $mainMod SHIFT, 7, movetoworkspace, 7
bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPause, exec, playerctl play-pause
bindl = , XF86AudioPlay, exec, playerctl play-pause
bindl = , XF86AudioPrev, exec, playerctl previous

View file

@ -0,0 +1,26 @@
general {
grace = 1
}
background {
path = screenshot
blur_passes = 2
}
input-field {
size = 20%, 5%
outline_thickness = 3
inner_color = rgba(0, 0, 0, 0.0) # no fill
outer_color = rgba(33ccffee) rgba(00ff99ee) 45deg
check_color=rgba(00ff99ee) rgba(ff6633ee) 120deg
fail_color=rgba(ff6633ee) rgba(ff0066ee) 40deg
font_color = rgb(143, 143, 143)
fade_on_empty = false
rounding = 15
position = 0, -20
halign = center
valign = center
}

View file

@ -0,0 +1,4 @@
preload = ~/.config/hypr/wallpaper/irish_forest.jpg
wallpaper = DP-1,~/.config/hypr/wallpaper/irish_forest.jpg
wallpaper = DP-2,~/.config/hypr/wallpaper/irish_forest.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 MiB

View file

@ -1,8 +1,8 @@
map global normal <F2> :toggle-whitespace<ret> map global user 'b' ':fzf-buflist<ret>' -docstring 'Select buffer from list'
map global normal <F4> :buffer-switcher<ret> map global user 'f' ':xplr<ret>' -docstring 'File finder'
map global normal <F5> :xplr<ret> map global user 'g' ':lazygit<ret>' -docstring 'Open lazygit'
map global normal <F6> :lazygit<ret> map global user 'l' ':fzf-lines<ret>' -docstring 'Jump to line'
map global user 'p' ':paste-sys-after<ret>' -docstring 'Paste from clipboard after selection'
map global user 'p' '<a-!>pbpaste<ret>' -docstring 'Paste from clipboard' map global user 'P' ':paste-sys-before<ret>' -docstring 'Paste from clipboard before selection'
map global user 'P' '!pbpaste<ret>' -docstring 'Paste from clipboard' map global user 'w' ':toggle-whitespace<ret>' -docstring 'Toggle whitespace highlighter'
map global user 'y' '<a-|>pbcopy<ret>' -docstring 'Yank to clipboard' map global user 'y' ':yank-sys<ret>' -docstring 'Yank to clipboard'

View file

@ -1,17 +1,20 @@
colorscheme everforest-dark-soft colorscheme everforest-dark-soft
set-option global ui_options terminal_set_title=no terminal_assistant=cat # The cat is critically important. set-option global ui_options terminal_set_title=no
set-option global tabstop 4 set-option global tabstop 4
set-option global indentwidth 4 set-option global indentwidth 4
add-highlighter global/ show-matching add-highlighter global/ show-matching
declare-option str windowing_placement horizontal #declare-option str windowing_placement horizontal
# With the way that Kakoune's windowing detection is currently set up, the wezterm module will never be loaded. # With the way that Kakoune's windowing detection is currently set up, the wezterm module will never be loaded.
# So, we need to fix the order in which windowing modules are declared. # So, we need to fix the order in which windowing modules are declared.
# TODO: submit a PR to Kakoune fixing this.
declare-option str-list windowing_modules 'tmux' 'screen' 'zellij' 'kitty' 'wezterm' 'iterm' 'appleterminal' 'sway' 'wayland' 'x11' declare-option str-list windowing_modules 'tmux' 'screen' 'zellij' 'kitty' 'wezterm' 'iterm' 'appleterminal' 'sway' 'wayland' 'x11'
set-option global windowing_placement horizontal
hook global WinCreate .* %{ hook global WinCreate .* %{
add-highlighter window/number-lines number-lines -hlcursor add-highlighter window/number-lines number-lines -hlcursor
} }

View file

@ -1,5 +1,5 @@
source "%val{config}/bundle/kak-bundle/rc/kak-bundle.kak" source "%val{config}/bundle/kak-bundle/rc/kak-bundle.kak"
bundle-noload kak-bundle "ln -sf ~/workspace/kak-bundle/" bundle-noload kak-bundle "https://codeberg.org/jdugan6240/kak-bundle"
bundle kakoune-lsp "https://github.com/kakoune-lsp/kakoune-lsp" %{ bundle kakoune-lsp "https://github.com/kakoune-lsp/kakoune-lsp" %{
set-option global lsp_diagnostic_line_error_sign  set-option global lsp_diagnostic_line_error_sign 
@ -7,6 +7,8 @@ bundle kakoune-lsp "https://github.com/kakoune-lsp/kakoune-lsp" %{
set-option global lsp_diagnostic_line_info_sign set-option global lsp_diagnostic_line_info_sign
set-option global lsp_diagnostic_line_warning_sign  set-option global lsp_diagnostic_line_warning_sign 
set-option global lsp_hover_anchor true
# kakoune-lsp doesn't have a command to enable auto-hover per buffer, # kakoune-lsp doesn't have a command to enable auto-hover per buffer,
# only supporting enabling auto-hover globally, # only supporting enabling auto-hover globally,
# which causes issues in filetypes that don't have lsp set up. # which causes issues in filetypes that don't have lsp set up.
@ -35,40 +37,43 @@ bundle kakoune-lsp "https://github.com/kakoune-lsp/kakoune-lsp" %{
# We want to be explicit about lsp server settings per filetype # We want to be explicit about lsp server settings per filetype
# So, we are disabling the default lsp server hooks # So, we are disabling the default lsp server hooks
remove-hooks global lsp-filetype-.* remove-hooks global lsp-filetype-.*
set global lsp_debug true
} }
bundle-install-hook kakoune-lsp %{ bundle-install-hook kakoune-lsp %{
cargo install --locked --force --path . CARGO_PROFILE_RELEASE_LTO=false cargo install --locked --force --path .
} }
bundle-noload everforest.kak "ln -sf ~/workspace/everforest.kak/" bundle-theme everforest.kak "https://codeberg.org/jdugan6240/everforest.kak"
bundle-install-hook everforest.kak %{
mkdir -p "${kak_config}/colors"
ln -sf "${kak_opt_bundle_path}/everforest.kak" "${kak_config}/colors/"
}
bundle-cleaner everforest.kak %{
rm "${kak_config}/colors/everforest.kak"
}
bundle luar "https://github.com/gustavo-hms/luar" %@ bundle luar "https://github.com/gustavo-hms/luar" %@
require-module luar require-module luar
# Luar's highlighters are very subtly broken so we need to replace them # Luar's highlighters are very subtly broken so we need to replace them.
# TODO: submit a PR to luar with these fixes. # These aren't perfect either, as they assume the "lua" or "fennel" command invocation is the first thing in the line,
# but whatever - when both "lua" and "fennel" can appear in many contexts, it's hard to be robust without a true parser.
remove-highlighter shared/kakrc/code/lua
remove-highlighter shared/kakrc/lua1 remove-highlighter shared/kakrc/lua1
remove-highlighter shared/kakrc/lua2 remove-highlighter shared/kakrc/lua2
remove-highlighter shared/kakrc/lua3 remove-highlighter shared/kakrc/lua3
remove-highlighter shared/kakrc/lua4 remove-highlighter shared/kakrc/lua4
add-highlighter shared/kakrc/lua1 region -recurse '\{' '(^|\h)lua\s(([\s{}\w%/$-|''"])* )?%\{\K' '\}' ref lua remove-highlighter shared/kakrc/code/fennel
add-highlighter shared/kakrc/lua2 region -recurse '\(' '(^|\h)lua\s(([\s{}\w%/$-|''"])* )?%\(\K' '\)' ref lua remove-highlighter shared/kakrc/fennel1
add-highlighter shared/kakrc/lua3 region -recurse '\[' '(^|\h)lua\s(([\s{}\w%/$-|''"])* )?%\[\K' '\]' ref lua remove-highlighter shared/kakrc/fennel2
add-highlighter shared/kakrc/lua4 region -recurse '<' '(^|\h)lua\s(([\s{}\w%/$-|''"])* )?%<\K' '>' ref lua remove-highlighter shared/kakrc/fennel3
remove-highlighter shared/kakrc/fennel4
add-highlighter shared/kakrc/code/lua regex (^\s*)lua(?:(?=\s)|\z) 0:keyword
add-highlighter shared/kakrc/lua1 region -recurse '\{' '^\s*lua\s(([\s{}\w%/$-|''"])* )?%\{\K' '\}' ref lua
add-highlighter shared/kakrc/lua2 region -recurse '\(' '^\s*lua\s(([\s{}\w%/$-|''"])* )?%\(\K' '\)' ref lua
add-highlighter shared/kakrc/lua3 region -recurse '\[' '^\s*lua\s(([\s{}\w%/$-|''"])* )?%\[\K' '\]' ref lua
add-highlighter shared/kakrc/lua4 region -recurse '<' '^\s*lua\s(([\s{}\w%/$-|''"])* )?%<\K' '>' ref lua
add-highlighter shared/kakrc/code/fennel regex (^\s*)fennel(?:(?=\s)|\z) 0:keyword
add-highlighter shared/kakrc/fennel1 region -recurse '\{' '^\s*fennel\s(([\s{}\w%/$-|''"])* )?%\{\K' '\}' ref fennel
add-highlighter shared/kakrc/fennel2 region -recurse '\(' '^\s*fennel\s(([\s{}\w%/$-|''"])* )?%\(\K' '\)' ref fennel
add-highlighter shared/kakrc/fennel3 region -recurse '\[' '^\s*fennel\s(([\s{}\w%/$-|''"])* )?%\[\K' '\]' ref fennel
add-highlighter shared/kakrc/fennel4 region -recurse '<' '^\s*fennel\s(([\s{}\w%/$-|''"])* )?%<\K' '>' ref fennel
@ @
bundle kakoune-buffer-switcher "https://github.com/occivink/kakoune-buffer-switcher" %{
# Make the current buffer more visible
set-face global BufferSwitcherCurrent value
}
bundle kakoune-focus "https://github.com/caksoylar/kakoune-focus" %{ bundle kakoune-focus "https://github.com/caksoylar/kakoune-focus" %{
map global user <space> ':focus-toggle<ret>' -docstring "toggle selections focus" map global user <space> ':focus-toggle<ret>' -docstring "toggle selections focus"
} }
@ -78,45 +83,83 @@ bundle kakship https://github.com/eburghar/kakship %{
} }
bundle-install-hook kakship %{ bundle-install-hook kakship %{
cargo install --force --path . --root ~/.local cargo install --force --path . --root ~/.local
[ ! -e $kak_config/starship.toml ] && cp starship.toml $kak_config/ if [ ! -e $kak_config/starship.toml ]; then
cp starship.toml $kak_config/
fi
} }
bundle-cleaner kakship %{ bundle-cleaner kakship %{
rm ~/.local/bin/kakship rm ~/.local/bin/kakship
} }
bundle popup.kak https://github.com/enricozb/popup.kak
bundle-install-hook popup.kak %{
cargo install --force --path .
}
bundle-cleaner popup.kak %{
cargo uninstall kak-popup
}
bundle-customload kak-tree-sitter https://git.sr.ht/~hadronized/kak-tree-sitter %{ bundle-customload kak-tree-sitter https://git.sr.ht/~hadronized/kak-tree-sitter %{
evaluate-commands %sh{ kak-tree-sitter -dks --init $kak_session } evaluate-commands %sh{ kak-tree-sitter -dks --init $kak_session --with-highlighting -vvvvv }
# kak-tree-sitter sometimes gets out of sync during editing, especially with large files
# so, whenever we get back to normal mode, force an update
hook global ModeChange .*:normal %{
tree-sitter-buffer-update
}
} }
bundle-install-hook kak-tree-sitter %{ bundle-install-hook kak-tree-sitter %{
cargo install --force --path ./kak-tree-sitter cargo install --force --path kak-tree-sitter
cargo install --force --path ./ktsctl cargo install --force --path ktsctl
} }
bundle-cleaner kak-tree-sitter %{ bundle-cleaner kak-tree-sitter %{
cargo uninstall kak-tree-sitter cargo uninstall kak-tree-sitter
cargo uninstall ktsctl cargo uninstall ktsctl
} }
bundle-noload kakeidoscope "git clone --recurse-submodules https://git.sr.ht/~orchid/kakeidoscope" bundle kakeidoscope https://git.sr.ht/~orchid/kakeidoscope %{
#hook global WinCreate .* kakeidoscope-enable-window
}
bundle-install-hook kakeidoscope %{ bundle-install-hook kakeidoscope %{
cd src cargo install --force --path .
make
mv kakeidoscope ~/.local/bin/
} }
bundle-cleaner kakeidoscope %{ bundle-cleaner kakeidoscope %{
rm ~/.local/bin/kakeidoscope cargo uninstall kakeidoscope
}
bundle-updater kakeidoscope %{
git pull --recurse-submodules
} }
bundle peneira https://github.com/gustavo-hms/peneira %{ bundle-noload kak-rainbower %{
require-module peneira # This is the last commit of kak-rainbower that worked
git clone https://github.com/crizan/kak-rainbower
cd kak-rainbower
git reset --hard 692c196650edd97da9ed6c275bb9b261630d063d
}%{
set-option global rainbow_mode 0
hook global WinCreate .* %{
rainbow-enable-window
}
} }
bundle-install-hook kak-rainbower %{
c++ rc/rainbower.cpp -o rc/rainbower
}
bundle-updater kak-rainbower %{
# This is the last commit of kak-rainbower that worked
#git reset --hard 692c196650edd97da9ed6c275bb9b261630d063d
git reset --hard frederick-the-great
}
bundle kak-rainbow https://github.com/Bodhizafa/kak-rainbow %{
hook global WinCreate .* %{
rainbow-enable-window
}
}
bundle pairs.kak https://github.com/42xel/pairs.kak %{
pairs_enable
}
bundle parinfer-rust https://github.com/eraserhd/parinfer-rust %{
hook global WinSetOption filetype=(clojure|fennel|lisp|picolisp|racket|scheme) %{
parinfer-enable-window -smart
}
}
bundle-install-hook parinfer-rust %{
cargo install --force --path .
}
bundle-cleaner parinfer-rust %{
cargo uninstall parinfer-rust
}
# Automatically clean any unregistered plugins
bundle-clean

View file

@ -0,0 +1,22 @@
hook global WinSetOption filetype=fennel %{
set-option buffer lsp_servers %{
[fennel-ls]
root_globs = [".git", ".hg", "fennel.lua"]
command = "/home/ANT.AMAZON.COM/dugajame/fennel-ls/fennel-ls"
}
lsp-enable-buffer
softtab-enable
}
hook global ModuleLoaded fennel %{
# By default, Kakoune highlights colon strings in the "keyword" face.
# This is incorrect - they should be highlighted as strings.
# So, we override the builtin highlighter with our own.
remove-highlighter shared/fennel/colon-string
add-highlighter shared/fennel/colon-string region '\W\K:[-\w?\\^_!$%&*+./@|<=>]' '(?![-\w?\\^_!$%&*+./@|<=>])' fill string
# Kakoune's default fennel support also doesn't properly highlight values,
# so we patch the lua highlighter in here
remove-highlighter shared/fennel/code/value
add-highlighter shared/fennel/code/value regex \b(false|nil|true|self|[0-9]+(:?\.[0-9])?(:?[eE]-?[0-9]+)?|0x[0-9a-fA-F]+)\b 0:value
}

View file

@ -19,4 +19,6 @@ hook global WinSetOption filetype=go %{
} }
lsp-enable-buffer lsp-enable-buffer
lsp-semantic-tokens-enable lsp-semantic-tokens-enable
set-option buffer indentwidth 0 # Use tabs
} }

View file

@ -10,4 +10,10 @@ hook global ModuleLoaded kak %@
~ catch %$ ~ catch %$
echo -debug "Error: kakrc: can't declare additional kakrc highlighters: %val{error}" echo -debug "Error: kakrc: can't declare additional kakrc highlighters: %val{error}"
$ $
# highlighting for bundle_sh_code
try %~
add-highlighter shared/kakrc/bundle_sh_code region -recurse '\{' '\bbundle_sh_code\s+%\{' '\}' ref sh
~ catch %$
echo -debug "Error: kakrc: can't declare additional kakrc highlighters: %val{error}"
$
@ @

9
.config/kak/filetypes/kdl.kak Executable file
View file

@ -0,0 +1,9 @@
hook global WinSetOption filetype=kdl %{
set-option buffer lsp_servers %{
[kdl-lsp]
root_globs = [".git", ".hg"]
command = "kdl-lsp"
}
lsp-enable-buffer
softtab-enable
}

View file

@ -2,9 +2,17 @@ hook global WinSetOption filetype=lua %{
set-option buffer lsp_servers %{ set-option buffer lsp_servers %{
[lua-language-server] [lua-language-server]
root_globs = [".luarc.json", ".git", ".hg"] root_globs = [".luarc.json", ".git", ".hg"]
command = "lua-language-server" command = "/home/ANT.AMAZON.COM/dugajame/lua-language-server/bin/lua-language-server"
# [emmylua_ls]
# root_globs = [".luarc.json", ".git", ".hg"]
# command = "emmylua_ls"
} }
lsp-semantic-tokens-enable lsp-semantic-tokens-enable
softtab-enable softtab-enable
lsp-enable-buffer lsp-enable-buffer
} }
hook global ModuleLoaded lua %{
# Support highlighting shebangs
add-highlighter shared/lua/shebang region '^#!' '$' fill comment
}

View file

@ -7,7 +7,7 @@ hook global WinSetOption filetype=python %{
[ruff] [ruff]
root_globs = ["requirements.txt", "setup.py", "pyrightconfig.json", ".git", ".hg"] root_globs = ["requirements.txt", "setup.py", "pyrightconfig.json", ".git", ".hg"]
command = "ruff" command = "ruff"
args = ["server", "--preview"] args = ["server"]
} }
lsp-enable-buffer lsp-enable-buffer
lsp-semantic-tokens-enable lsp-semantic-tokens-enable

16
.config/kak/filetypes/rust.kak Executable file
View file

@ -0,0 +1,16 @@
hook global WinSetOption filetype=rust %{
set-option buffer lsp_servers %{
# [rust-analyzer]
# root_globs = ["Cargo.toml"]
# single_instance = true
# command = "rust-analyzer"
# [rls]
# root_globs = ["Cargo.toml"]
# command = "rls"
[ra-multiplex]
root_globs = ["Cargo.toml"]
command = "ra-multiplex"
}
lsp-enable-buffer
#lsp-semantic-tokens-enable
}

View file

@ -11,7 +11,11 @@ load config plugins
# Additional syntaxes # Additional syntaxes
load syntaxes capnp load syntaxes capnp
load syntaxes hjson
load syntaxes hyprlang
load syntaxes json5
load syntaxes kdl load syntaxes kdl
load syntaxes kitty
load syntaxes rainbow_csv load syntaxes rainbow_csv
load syntaxes sshconfig load syntaxes sshconfig
@ -22,6 +26,9 @@ load utils whitespace
# Tool integration # Tool integration
load tools clipboard
load tools fzf
load tools kitty
load tools lazygit load tools lazygit
load tools xplr load tools xplr
@ -35,10 +42,13 @@ load config mappings
# Filetype-specific configs # Filetype-specific configs
load filetypes fennel
load filetypes go load filetypes go
load filetypes kak load filetypes kak
load filetypes kdl
load filetypes lua load filetypes lua
load filetypes python load filetypes python
load filetypes rust
load filetypes sh load filetypes sh
load filetypes yaml load filetypes yaml

112
.config/kak/syntaxes/hjson.kak Executable file
View file

@ -0,0 +1,112 @@
# http://hjson.github.io
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
# Detection
# ‾‾‾‾‾‾‾‾‾
hook global BufCreate .*[.](hjson) %{
set-option buffer filetype hjson
}
# Initialization
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
hook global WinSetOption filetype=hjson %{
require-module hjson
hook window ModeChange pop:insert:.* -group hjson-trim-indent hjson-trim-indent
hook window InsertChar .* -group hjson-indent hjson-indent-on-char
hook window InsertChar \n -group hjson-indent hjson-indent-on-new-line
hook -once -always window WinSetOption filetype=.* %{ remove-hooks window hjson-.+ }
}
hook -group hjson-highlight global WinSetOption filetype=hjson %{
add-highlighter window/hjson ref hjson
hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/hjson }
}
provide-module hjson %(
# Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾
add-highlighter shared/hjson regions
add-highlighter shared/hjson/code default-region group
add-highlighter shared/hjson/string region '"' (?<!\\)(\\\\)*" fill string
add-highlighter shared/hjson/string2 region "'" (?<!\\)(\\\\)*' fill string
add-highlighter shared/hjson/triple_string region -match-capture ("""|''') (?<!\\)(?:\\\\)*("""|''') fill string
add-highlighter shared/hjson/comment1 region '#' '$' fill comment
add-highlighter shared/hjson/comment2 region '//' '$' fill comment
add-highlighter shared/hjson/multiline_comment region /\* \*/ fill comment
# The below isn't perfect, as it doesn't work if multiple member-value pairs are defined on the same line,
# and it mistakenly highlights comments at the end of a quoteless string,
# but eh - it's good enough for the vast majority of real-world cases,
# and it's annoying to make this work right with Kakoune highlighters alone.
add-highlighter shared/hjson/code/ regex ^(\s*[^,:\[\]\{\}\s]+):\s+([^\{\}\[\]:,][^\r\n]*)? 1:variable 2:string
add-highlighter shared/hjson/code/ regex \b(true|false|null|\d+(?:\.\d+)?(?:[eE][+-]?\d*)?)\b 0:value
# Commands
# ‾‾‾‾‾‾‾‾
define-command -hidden hjson-trim-indent %{
# remove trailing white spaces
try %{ execute-keys -draft -itersel x s \h+$ <ret> d }
}
define-command -hidden hjson-indent-on-char %<
evaluate-commands -draft -itersel %<
# align closer token to its opener when alone on a line
try %< execute-keys -draft <a-h> <a-k> ^\h+[\]}]$ <ret> m <a-S> 1<a-&> >
>
>
define-command -hidden hjson-indent-on-new-line %{
evaluate-commands -itersel -draft %{
execute-keys <semicolon>
try %{
evaluate-commands -draft -save-regs '/"' %{
# Ensure previous line is a comment
# This only supports "#" comments (because hjson supporting # and // comments was a mistake)
execute-keys -draft kxs^\h*#+\h*<ret>
# now handle the coment continuation logic
try %{
# try and match a regular block comment, copying the prefix
execute-keys -draft -save-regs '' k x 1s^(\h*#+\h*)\S.*$ <ret> y
execute-keys -draft P
} catch %{
try %{
# try and match a regular block comment followed by a single
# empty comment line
execute-keys -draft -save-regs '' kKx 1s^(\h*#+\h*)\S+\n\h*#+\h*$ <ret> y
execute-keys -draft P
} catch %{
try %{
# try and match a pair of empty comment lines, and delete
# them if we match
execute-keys -draft kKx <a-k> ^\h*#+\h*\n\h*#+\h*$ <ret> <a-d>
} catch %{
# finally, we need a special case for a new line inserted
# into a file that consists of a single empty comment - in
# that case we can't expect to copy the trailing whitespace,
# so we add our own
execute-keys -draft -save-regs '' k x1s^(\h*#+)\h*$<ret> y
execute-keys -draft P
execute-keys -draft i<space>
}
}
}
}
# trim trailing whitespace on the previous line
try %{ execute-keys -draft k x s\h+$<ret> d }
}
}
}
)

View file

@ -0,0 +1,76 @@
# https://hyprland.org/
hook global BufCreate .*/hypr/.*[.]conf %{
set-option buffer filetype hyprlang
}
# Initialization
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
hook global WinSetOption filetype=hyprlang %{
require-module hyprlang
hook window ModeChange pop:insert:.* -group hyprlang-trim-indent hyprlang-trim-indent
hook window InsertChar .* -group hyprlang-indent hyprlang-indent-on-char
hook window InsertChar \n -group hyprlang-indent hyprlang-indent-on-new-line
hook -once -always window WinSetOption filetype=.* %{ remove-hooks window hyprlang-.+ }
}
hook -group hyprlang-highlight global WinSetOption filetype=hyprlang %{
add-highlighter window/hyprlang ref hyprlang
hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/hyprlang }
}
provide-module hyprlang %@
# Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾
add-highlighter shared/hyprlang regions
add-highlighter shared/hyprlang/code default-region group
add-highlighter shared/hyprlang/string region '"' (?<!\\)(\\\\)*" fill string
add-highlighter shared/hyprlang/line_comment region '#' $ fill comment
add-highlighter shared/hyprlang/code/variable regex ((?<![-:])\b\w+)\s*= 1:variable
add-highlighter shared/hyprlang/code/dollarvar regex (\$\w+)\b 1:value
add-highlighter shared/hyprlang/code/builtin regex \b(true|false)\b 0:value
add-highlighter shared/hyprlang/code/binary regex \b(0b[01_]+)\b 0:value
add-highlighter shared/hyprlang/code/octal regex \b(0o[0-7_]+)\b 0:value
add-highlighter shared/hyprlang/code/hex regex \b(0x[a-fA-F0-9_]+)\b 0:value
add-highlighter shared/hyprlang/code/decimal regex \b([0-9-+][0-9_]*)\b 0:value
add-highlighter shared/hyprlang/code/float regex \b([0-9-+][0-9_]*\.[0-9_]+)\b 0:value
add-highlighter shared/hyprlang/code/float_exp regex \b([0-9-+][0-9_]*(\.[0-9_]+)?[eE][-+]?[0-9_]+)\b 0:value
# Commands
# ‾‾‾‾‾‾‾‾
define-command -hidden hyprlang-trim-indent %{
# remove trailing white spaces
try %{ execute-keys -draft -itersel x s \h+$ <ret> d }
}
define-command -hidden hyprlang-indent-on-char %<
evaluate-commands -draft -itersel %<
# align closer token to its opener when alone on a line
try %< execute-keys -draft <a-h> <a-k> ^\h+[\]}]$ <ret> m <a-S> 1<a-&> >
>
>
define-command -hidden hyprlang-indent-on-new-line %<
evaluate-commands -draft -itersel %<
# preserve previous line indent
try %{ execute-keys -draft <semicolon> K <a-&> }
# filter previous line
try %{ execute-keys -draft k : hyprlang-trim-indent <ret> }
# indent after lines ending with opener token
try %< execute-keys -draft k x <a-k> [[{]\h*$ <ret> j <a-gt> >
# deindent closer token(s) when after cursor
try %< execute-keys -draft x <a-k> ^\h*[}\]] <ret> gh / [}\]] <ret> m <a-S> 1<a-&> >
>
>
@

78
.config/kak/syntaxes/json5.kak Executable file
View file

@ -0,0 +1,78 @@
# http://json5.org
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
# Detection
# ‾‾‾‾‾‾‾‾‾
hook global BufCreate .*[.](json5) %{
set-option buffer filetype json5
}
# Initialization
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
hook global WinSetOption filetype=json5 %{
require-module json5
hook window ModeChange pop:insert:.* -group json5-trim-indent json5-trim-indent
hook window InsertChar \n -group json5-insert json5-insert-on-new-line
hook window InsertChar \n -group json5-indent json5-indent-on-new-line
hook window InsertChar .* -group json5-indent json5-indent-on-char
hook -once -always window WinSetOption filetype=.* %{ remove-hooks window json5-.+ }
}
hook -group json5-highlight global WinSetOption filetype=json5 %{
add-highlighter window/json5 ref json5
hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/json5 }
}
provide-module json5 %(
# Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾
add-highlighter shared/json5 regions
add-highlighter shared/json5/code default-region group
add-highlighter shared/json5/string region '"' (?<!\\)(\\\\)*" fill string
add-highlighter shared/json5/string2 region "'" (?<!\\)(\\\\)*' fill string
add-highlighter shared/json5/comment region '//' '$' fill comment
add-highlighter shared/json5/multiline_comment region /\* \*/ fill comment
add-highlighter shared/json5/code/ regex \b(true|false|null|\d+(?:\.\d+)?(?:[eE][+-]?\d*)?|0x[\da-fA-F]+)\b 0:value
# Commands
# ‾‾‾‾‾‾‾‾
define-command -hidden json5-insert-on-new-line %[
# copy // comments prefix and following white spaces
try %{ execute-keys -draft <semicolon><c-s>kx s ^\h*\K/{2,}\h* <ret> y<c-o>P<esc> }
]
define-command -hidden json5-trim-indent %{
# remove trailing white spaces
try %{ execute-keys -draft -itersel x s \h+$ <ret> d }
}
define-command -hidden json5-indent-on-char %<
evaluate-commands -draft -itersel %<
# align closer token to its opener when alone on a line
try %< execute-keys -draft <a-h> <a-k> ^\h+[\]}]$ <ret> m <a-S> 1<a-&> >
>
>
define-command -hidden json5-indent-on-new-line %<
evaluate-commands -draft -itersel %<
# preserve previous line indent
try %{ execute-keys -draft <semicolon> K <a-&> }
# filter previous line
try %{ execute-keys -draft k : json5-trim-indent <ret> }
# indent after lines ending with opener token
try %< execute-keys -draft k x <a-k> [[{]\h*$ <ret> j <a-gt> >
# deindent closer token(s) when after cursor
try %< execute-keys -draft x <a-k> ^\h*[}\]] <ret> gh / [}\]] <ret> m <a-S> 1<a-&> >
>
>
)

View file

@ -1,4 +1,5 @@
# https://kdl.dev # https://kdl.dev
# Currently only supports kdl v1
hook global BufCreate .*[.](kdl) %{ hook global BufCreate .*[.](kdl) %{
set-option buffer filetype kdl set-option buffer filetype kdl

225
.config/kak/syntaxes/kitty.kak Executable file
View file

@ -0,0 +1,225 @@
# https://sw.kovidgoyal.net/kitty/
hook global BufCreate .*/kitty/.*[.]conf %{
set-option buffer filetype kitty-conf
}
hook global BufCreate .*/kitty/.*[.]session %{
set-option buffer filetype kitty-session
}
hook global WinSetOption filetype=kitty-conf %{
require-module kitty-conf
set-option window static_words %opt{kitty_conf_static_words}
hook -once -always window WinSetOption filetype=.* %{ remove-hooks window kitty-conf-.+ }
}
hook -group kitty-conf-highlight global WinSetOption filetype=kitty-conf %{
add-highlighter window/kitty-conf ref kitty-conf
hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/kitty-conf }
}
hook global WinSetOption filetype=kitty-session %{
require-module kitty-session
set-option window static_words %opt{kitty_session_static_words}
hook -once -always window WinSetOption filetype=.* %{ remove-hooks window kitty-session-.+ }
}
hook -group kitty-session-highlight global WinSetOption filetype=kitty-session %{
add-highlighter window/kitty-session ref kitty-session
hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/kitty-session }
}
provide-module kitty-conf %{
# Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾
add-highlighter shared/kitty-conf regions
add-highlighter shared/kitty-conf/code default-region group
add-highlighter shared/kitty-conf/line_comment region ^# $ fill comment
add-highlighter shared/kitty-conf/string region '"' (?<!\\)(\\\\)*" fill string
add-highlighter shared/kitty-conf/string2 region "'" (?<!\\)(\\\\)*' fill string
add-highlighter shared/kitty-conf/code/keybind regex ^\s*map\s([^\s]+) 1:value
add-highlighter shared/kitty-conf/code/kitty_mod regex ^\s*kitty_mod\s([^\s]+) 1:value
add-highlighter shared/kitty-conf/code/include regex ^\s*include\s(.*) 1:string
add-highlighter shared/kitty-conf/code/globinclude regex ^\s*globinclude\s(.*) 1:string
add-highlighter shared/kitty-conf/code/geninclude regex ^\s*geninclude\s(.*) 1:string
add-highlighter shared/kitty-conf/code/envinclude regex ^\s*envinclude\s(.*) 1:string
add-highlighter shared/kitty-conf/code/ regex \b(yes|no|no-op)\b 0:value
add-highlighter shared/kitty-conf/code/ regex '(?i)\b0x[\da-f]+\b' 0:value
add-highlighter shared/kitty-conf/code/ regex '(?i)\b0o?[0-7]+\b' 0:value
add-highlighter shared/kitty-conf/code/ regex '(?i)\b([1-9]\d*|0)\b' 0:value
add-highlighter shared/kitty-conf/code/ regex '(?i)\b0b[01]+\b' 0:value
add-highlighter shared/kitty-conf/code/ regex '(?i)\bU\+[\da-f]+\b' 0:value
add-highlighter shared/kitty-conf/code/ regex (?i)\b"#([\da-f]{8}|[\da-f]{6}|[\da-f]{3})"\b 0:value
evaluate-commands %sh{
kitty_mods="alt super cmd command ⌘ control ctrl ^ kitty_mod opt option ⌥ shift ⇧"
kitty_keywords="action_alias active_border_color active_tab_background
active_tab_font_style active_tab_foreground active_tab_title_template
allow_cloning allow_hyperlinks allow_remote_control background
background_blur background_image background_image_layout
background_image_linear background_opacity background_tint
background_tint_gaps bell_border_color bell_on_tab bell_path bold_font
bold_italic_font box_drawing_scale clear_all_mouse_actions
clear_all_shortcuts clear_selection_on_clipboard_loss click_interval
clipboard_control clipboard_max_size clone_source_strategies
close_on_child_death color0 color1 color2 color3 color4 color5 color6
color7 color8 color9 color10 color11 color12 color13 color14 color15
color16 color17 color18 color19 color20 color21 color22 color23 color24
color25 color26 color27 color28 color29 color30 color31 color32 color33
color34 color35 color36 color37 color38 color39 color40 color41 color42
color43 color44 color45 color46 color47 color48 color49 color50 color51
color52 color53 color54 color55 color56 color57 color58 color59 color60
color61 color62 color63 color64 color65 color66 color67 color68 color69
color70 color71 color72 color73 color74 color75 color76 color77 color78
color79 color80 color81 color82 color83 color84 color85 color86 color87
color88 color89 color90 color91 color92 color93 color94 color95 color96
color97 color98 color99 color100 color101 color102 color103 color104
color105 color106 color107 color108 color109 color110 color111 color112
color113 color114 color115 color116 color117 color118 color119 color120
color121 color122 color123 color124 color125 color126 color127 color128
color129 color130 color131 color132 color133 color134 color135 color136
color137 color138 color139 color140 color141 color142 color143 color144
color145 color146 color147 color148 color149 color150 color151 color152
color153 color154 color155 color156 color157 color158 color159 color160
color161 color162 color163 color164 color165 color166 color167 color168
color169 color170 color171 color172 color173 color174 color175 color176
color177 color178 color179 color180 color181 color182 color183 color184
color185 color186 color187 color188 color189 color190 color191 color192
color193 color194 color195 color196 color197 color198 color199 color200
color201 color202 color203 color204 color205 color206 color207 color208
color209 color210 color211 color212 color213 color214 color215 color216
color217 color218 color219 color220 color221 color222 color223 color224
color225 color226 color227 color228 color229 color230 color231 color232
color233 color234 color235 color236 color237 color238 color239 color240
color241 color242 color243 color244 color245 color246 color247 color248
color249 color250 color251 color252 color253 color254 color255
command_on_bell confirm_os_window_close copy_on_select cursor
cursor_beam_thickness cursor_blink_interval cursor_shape
cursor_shape_unfocused cursor_stop_blinking_after cursor_text_color
cursor_trail cursor_trail_decay cursor_trail_start_threshold
cursor_underline_thickness default_pointer_shape detect_urls dim_opacity
disable_ligatures draw_minimal_borders dynamic_background_opacity editor
enable_audio_bell enabled_layouts env exe_search_path
file_transfer_confirmation_bypass filter_notification focus_follows_mouse
font_family font_features font_size force_ltr foreground forward_stdio
hide_window_decorations inactive_border_color inactive_tab_background
inactive_tab_font_style inactive_tab_foreground inactive_text_alpha
initial_window_height initial_window_width input_delay italic_font
kitten_alias kitty_mod linux_bell_theme linux_display_server listen_on
macos_colorspace macos_custom_beam_cursor macos_hide_from_tasks
macos_menubar_title_max_length macos_option_as_alt
macos_quit_when_last_window_closed macos_show_window_title_in
macos_thicken_font macos_titlebar_color macos_traditional_fullscreen
macos_window_resizable map mark1_background mark1_foreground
mark2_background mark2_foreground mark3_background mark3_foreground
menu_map modify_font mouse_hide_wait mouse_map narrow_symbols
notify_on_cmd_finish open_url_with paste_actions placement_strategy
pointer_shape_when_dragging pointer_shape_when_grabbed
remember_window_size remote_control_password repaint_delay
resize_debounce_time resize_in_steps scrollback_fill_enlarged_window
scrollback_indicator_opacity scrollback_lines scrollback_pager
scrollback_pager_history_size select_by_word_characters
select_by_word_characters_forward selection_background
selection_foreground shell shell_integration show_hyperlink_targets
single_window_margin_width single_window_padding_width startup_session
strip_trailing_spaces symbol_map sync_to_monitor tab_activity_symbol
tab_bar_align tab_bar_background tab_bar_edge tab_bar_margin_color
tab_bar_margin_height tab_bar_margin_width tab_bar_min_tabs tab_bar_style
tab_fade tab_powerline_style tab_separator tab_switch_strategy
tab_title_max_length tab_title_template term terminfo_type
text_composition_strategy text_fg_override_threshold
touch_scroll_multiplier transparent_background_colors undercurl_style
underline_exclusion underline_hyperlinks update_check_interval url_color
url_excluded_characters url_prefixes url_style visual_bell_color
visual_bell_duration visual_window_select_characters watcher
wayland_enable_ime wayland_titlebar_color wheel_scroll_min_lines
wheel_scroll_multiplier window_alert_on_bell window_border_width
window_logo_alpha window_logo_path window_logo_position window_logo_scale
window_margin_width window_padding_width window_resize_step_cells
window_resize_step_lines"
kitty_actions="change_font_size clear_selection clear_terminal click close_os_window
close_other_os_windows close_other_tabs_in_os_window
close_other_windows_in_tab close_shared_ssh_connections close_tab
close_window close_window_with_confirmation combine
copy_and_clear_or_interrupt copy_ansi_to_clipboard copy_or_interrupt
copy_to_buffer copy_to_clipboard create_marker debug_config detach_tab
detach_window disable_ligatures_in discard_event doubleclick doublepress
dump_lines_with_attrs edit_config_file eighth_window fifth_window
first_window focus_visible_window fourth_window goto_layout goto_tab
hide_macos_app hide_macos_other_apps input_unicode_character kitten
kitty_shell last_used_layout launch layout_action load_config_file
minimize_macos_window mouse_click_url mouse_click_url_or_select
mouse_handle_click mouse_select_command_output mouse_selection
mouse_show_command_output move_tab_backward move_tab_forward move_window
move_window_backward move_window_forward move_window_to_top
neighboring_window new_os_window new_os_window_with_cwd new_tab
new_tab_with_cwd new_window new_window_with_cwd next_layout next_tab
next_window ninth_window no-op nth_os_window nth_window open_url
open_url_with_hints pass_selection_to_program paste paste_from_buffer
paste_from_clipboard paste_from_selection paste_selection
paste_selection_or_clipboard pop_keyboard_mode press previous_tab
previous_window push_keyboard_mode quit release remote_control
remote_control_script remove_marker reset_window_sizes resize_window
scroll_end scroll_home scroll_line_down scroll_line_up scroll_page_down
scroll_page_up scroll_prompt_to_bottom scroll_prompt_to_top scroll_to_mark
scroll_to_prompt second_window select_tab send_key send_text
set_background_opacity set_colors set_tab_title set_window_title
seventh_window show_error show_first_command_output_on_screen
show_kitty_doc show_kitty_env_vars show_last_command_output
show_last_non_empty_command_output show_last_visited_command_output
show_scrollback signal_child sixth_window sleep start_resizing_window
swap_with_window tenth_window third_window toggle_fullscreen toggle_layout
toggle_macos_secure_keyboard_entry toggle_marker toggle_maximized
toggle_tab triplepress"
kitty_include="envinclude geninclude globinclude include"
join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; }
printf %s\\n "declare-option str-list kitty_conf_static_words $(join "${kitty_mods}" ' ') $(join "${kitty_keywords}" ' ') $(join "${kitty_actions}" ' ') $(join "${kitty_include}" ' ')"
printf %s\\n "add-highlighter shared/kitty-conf/code/ regex '\b($(join "${kitty_mods}" '|'))\b' 0:keyword"
printf %s\\n "add-highlighter shared/kitty-conf/code/ regex '\b($(join "${kitty_keywords}" '|'))\b' 0:keyword"
printf %s\\n "add-highlighter shared/kitty-conf/code/ regex '\b($(join "${kitty_actions}" '|'))\b' 0:function"
printf %s\\n "add-highlighter shared/kitty-conf/code/ regex '\b($(join "${kitty_include}" '|'))\b' 0:keyword"
}
}
provide-module kitty-session %{
# Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾
add-highlighter shared/kitty-session regions
add-highlighter shared/kitty-session/code default-region group
add-highlighter shared/kitty-session/line_comment region ^# $ fill comment
add-highlighter shared/kitty-session/string region '"' (?<!\\)(\\\\)*" fill string
add-highlighter shared/kitty-session/string2 region "'" (?<!\\)(\\\\)*' fill string
add-highlighter shared/kitty-session/code/ regex '(?i)\b0x[\da-f]+\b' 0:value
add-highlighter shared/kitty-session/code/ regex '(?i)\b0o?[0-7]+\b' 0:value
add-highlighter shared/kitty-session/code/ regex '(?i)\b([1-9]\d*|0)\b' 0:value
add-highlighter shared/kitty-session/code/ regex '(?i)\b0b[01]+\b' 0:value
add-highlighter shared/kitty-session/code/ regex '(?i)\bU\+[\da-f]+\b' 0:value
evaluate-commands %sh{
kitty_session_commands="new_tab new_os_window layout launch focus enabled_layouts cd title os_window_size os_window_class"
join() { sep=$2; eval set -- $1; IFS="$sep"; echo "$*"; }
printf %s\\n "declare-option str-list kitty_session_static_words $(join "${kitty_session_commands}" ' ')"
printf %s\\n "add-highlighter shared/kitty-session/code/ regex '\b($(join "${kitty_session_commands}" '|'))\b' 0:keyword"
}
}

16
.config/kak/tools/clipboard.kak Executable file
View file

@ -0,0 +1,16 @@
declare-option str yank_sys_clipboard_cmd %sh{
test "$(uname)" = "Darwin" && echo "pbcopy" || echo "xsel -ib"
}
declare-option str paste_sys_clipboard_cmd %sh{
test "$(uname)" = "Darwin" && echo "pbpaste" || echo "xsel -ob"
}
define-command yank-sys -docstring "yank into the system clipboard" %{
execute-keys -draft "<a-|>%opt{yank_sys_clipboard_cmd}<ret>"
}
define-command paste-sys-before -docstring "paste from the system clipboard before selection" %{
execute-keys -draft "!%opt{paste_sys_clipboard_cmd}<ret>"
}
define-command paste-sys-after -docstring "paste from the system clipboard after selection" %{
execute-keys -draft "<a-!>%opt{paste_sys_clipboard_cmd}<ret>"
}

29
.config/kak/tools/fzf.kak Executable file
View file

@ -0,0 +1,29 @@
# https://junegunn.github.io/fzf
define-command fzf-buflist -docstring "Use fzf to select buffer" %{
set-register f %sh{ printf "%s" "$kak_buflist" | tr ' ' '\n' }
wezterm-terminal-tab sh -c %{
PATH=$PATH:~/.fzf/bin/
kak_session=$1 kak_client=$2 buflist=$3
shift 3
# Note: we need to replace ~ with $HOME here; otherwise bat can't find the file for preview
output=$(printf "$buflist" | sed "s|~|$HOME|" | fzf --preview 'bat --color=always {}')
kak_cmd="evaluate-commands -client $kak_client buffer $output"
echo $kak_cmd | kak -p $kak_session
} -- %val{session} %val{client} %reg{f}
}
define-command fzf-lines -docstring "Use fzf to jump to line in current buffer" %{
set-register f %sh{ mktemp }
execute-keys -draft '%<a-|> nl -b a > $kak_reg_f<ret>'
wezterm-terminal-tab sh -c %{
PATH=$PATH:~/.fzf/bin/
kak_session=$1 kak_client=$2 buffile=$3
shift 3
output=$(fzf --layout=reverse < $buffile)
set -- $output
kak_cmd="evaluate-commands -client $kak_client execute-keys '${1}g'"
rm $buffile
echo $kak_cmd | kak -p $kak_session
} -- %val{session} %val{client} %reg{f}
}

39
.config/kak/tools/kitty.kak Executable file
View file

@ -0,0 +1,39 @@
# https://sw.kovidgoyal.net/kitty
# The following assumes the "splits" layout.
hook global ModuleLoaded kitty %{
define-command kitty-launch-impl -params 3.. %{
nop %sh{
location=$1
type=$2
shift 2
match=""
if [ -n "$kak_client_env_KITTY_WINDOW_ID" ]; then
match="--match=window_id:$kak_client_env_KITTY_WINDOW_ID"
fi
listen=""
if [ -n "$kak_client_env_KITTY_LISTEN_ON" ]; then
listen="--to=$kak_client_env_KITTY_LISTEN_ON"
fi
kitty @ $listen launch --no-response --location=$location --type=$type --cwd="$PWD" $match "$@"
}
} -hidden
define-command kitty-terminal-horizontal -params 1.. %{
kitty-launch-impl "vsplit" "window" %arg{@}
}
complete-command kitty-terminal-horizontal shell
define-command kitty-terminal-vertical -params 1.. %{
kitty-launch-impl "hsplit" "window" %arg{@}
}
complete-command kitty-terminal-vertical shell
define-command kitty-terminal-overlay -params 1.. %{
kitty-launch-impl "default" "overlay" %arg{@}
}
complete-command kitty-terminal-overlay shell
}

View file

@ -1,7 +1,7 @@
# https://github.com/jesseduffield/lazygit # https://github.com/jesseduffield/lazygit
define-command lazygit %{ define-command lazygit %{
popup lazygit kitty-terminal-overlay lazygit
} }
alias global lg lazygit alias global lg lazygit

View file

@ -1,9 +1,10 @@
# https://xplr.dev/ # https://xplr.dev/
# Seriously, xplr is awesome. Get it if you haven't already. # The reason to use xplr instead of fzf here is sometimes we want to edit a file
# not in the current working directory.
define-command xplr-open -params 1 %{ define-command xplr-open -params 1.. %{
evaluate-commands %sh{ evaluate-commands %sh{
for xplr_file in $1; do for xplr_file in $@; do
if [ -f "$xplr_file" ]; then if [ -f "$xplr_file" ]; then
printf "%s\n" "edit $xplr_file" printf "%s\n" "edit $xplr_file"
fi fi
@ -11,8 +12,16 @@ define-command xplr-open -params 1 %{
} }
} -hidden } -hidden
define-command xplr -params ..1 %{ define-command xplr -params ..1 -docstring "Use xplr to open file" %{
popup --title open --kak-script %{ xplr-open %opt{popup_output} } -- xplr %arg{@} wezterm-terminal-tab sh -c %{
PATH=$PATH:~/.fzf/bin/
kak_buffile=$1 kak_session=$2 kak_client=$3
shift 3
kak_pwd="${@:-$(dirname "${kak_buffile}")}"
output=$(xplr "${kak_pwd}")
kak_cmd="evaluate-commands -client $kak_client xplr-open $output"
echo $kak_cmd | kak -p $kak_session
} -- %val{buffile} %val{session} %val{client} %arg{@}
} }
# Utility command to edit a kak config file with xplr # Utility command to edit a kak config file with xplr

View file

@ -1,11 +1,11 @@
local wezterm = require("wezterm") local wezterm = require("wezterm") --[[@as Wezterm]]
local config = {} local config = {}
-- color scheme -- color scheme
config.color_scheme = "Everforest Dark Soft (Gogh)" config.color_scheme = "Everforest Dark Soft (Gogh)"
-- font -- font
config.font = wezterm.font("Fantasque Sans Mono") config.font = wezterm.font("Hack")
config.font_size = 14.0 config.font_size = 14.0
-- Ligatures in terminal/programming fonts IMO are a bad idea, -- Ligatures in terminal/programming fonts IMO are a bad idea,
-- as they require the user to mentally translate what the ligature represents, -- as they require the user to mentally translate what the ligature represents,
@ -31,4 +31,7 @@ config.inactive_pane_hsb = {
-- scrollbar -- scrollbar
config.enable_scroll_bar = true config.enable_scroll_bar = true
-- cursor
config.default_cursor_style = 'SteadyBar'
return config return config

View file

@ -1,6 +1,8 @@
local wezterm = require("wezterm") local wezterm = require("wezterm") --[[@as Wezterm]]
local util = require("util")
local act = wezterm.action local act = wezterm.action
-- We override the key bindings here, so as to explicitly define what they are rather than relying on default values.
local keys = { local keys = {
-- Tab Management -- Tab Management
{ key = "T", mods = "SHIFT|CTRL", action = act.SpawnTab "CurrentPaneDomain" }, { key = "T", mods = "SHIFT|CTRL", action = act.SpawnTab "CurrentPaneDomain" },
@ -50,6 +52,8 @@ local keys = {
{ key = "Insert", mods = "CTRL", action = act.CopyTo "PrimarySelection" }, { key = "Insert", mods = "CTRL", action = act.CopyTo "PrimarySelection" },
{ key = "Copy", mods = "NONE", action = act.CopyTo "Clipboard" }, { key = "Copy", mods = "NONE", action = act.CopyTo "Clipboard" },
{ key = "Paste", mods = "NONE", action = act.PasteFrom "Clipboard" }, { key = "Paste", mods = "NONE", action = act.PasteFrom "Clipboard" },
-- Other
{ key = "G", mods = "SHIFT|CTRL", action = wezterm.action_callback(util.open_last_output_in_less) },
} }
local key_tables = { local key_tables = {
@ -119,9 +123,56 @@ local key_tables = {
} }
} }
-- We also override the default mouse bindings, and the reasons are as follows:
-- 1) The default bindings often clobber the system clipboard, which I don't want, and
-- 2) Some of the default bindings are frivolous and unnecessary
local mouse_bindings = {
-- Left mouse button click
{
event = { Down = { streak = 1, button = "Left" } },
action = act.SelectTextAtMouseCursor("Cell"),
mods = "NONE"
},
{
event = { Up = { streak = 1, button = "Left" } },
action = act.CompleteSelectionOrOpenLinkAtMouseCursor("PrimarySelection"),
mods = "NONE"
},
-- Middle mouse button click
{
event = { Down = { streak = 1, button = "Middle" } },
action = act.PasteFrom("PrimarySelection"),
mods = "NONE"
},
{
event = { Down = { streak = 1, button = "Middle" } },
action = act.PasteFrom("Clipboard"),
mods = "ALT"
},
-- Right mouse button click
{
event = { Down = { streak = 1, button = "Right" } },
action = act.SelectTextAtMouseCursor("SemanticZone"),
mods = "CTRL|SHIFT"
},
-- Left mouse button drag
{
event = { Drag = { streak = 1, button = "Left" } },
action = act.ExtendSelectionToMouseCursor("Cell"),
mods = "NONE"
},
{
event = { Drag = { streak = 1, button = "Left" } },
action = act.StartWindowDrag,
mods = "SUPER"
}
}
local config = {} local config = {}
config.keys = keys config.keys = keys
config.disable_default_key_bindings = true config.disable_default_key_bindings = true
config.disable_default_mouse_bindings = true
config.key_tables = key_tables config.key_tables = key_tables
config.mouse_bindings = mouse_bindings
return config return config

View file

@ -7,5 +7,6 @@ config.exit_behavior = 'Close'
config.exit_behavior_messaging = 'Verbose' config.exit_behavior_messaging = 'Verbose'
config.status_update_interval = 25 config.status_update_interval = 25
config.default_prog = { '/usr/local/bin/hilbish', '-l' } config.default_prog = { '/usr/local/bin/hilbish', '-l' }
config.switch_to_last_active_tab_when_closing_tab = true
return config return config

View file

@ -1,4 +1,4 @@
local wezterm = require("wezterm") local wezterm = require("wezterm") --[[@as Wezterm]]
local util = require("util") local util = require("util")
local scheme = util.get_schemes()["Everforest Dark Soft (Gogh)"] local scheme = util.get_schemes()["Everforest Dark Soft (Gogh)"]
@ -46,11 +46,17 @@ wezterm.on("update-status", function(window, pane)
end end
table.insert(right_status, "ResetAttributes") table.insert(right_status, "ResetAttributes")
if cwd_path ~= "" then
table.insert(right_status, { Background = { Color = scheme.ansi[8] } }) table.insert(right_status, { Background = { Color = scheme.ansi[8] } })
table.insert(right_status, { Foreground = { Color = scheme.ansi[1] } }) table.insert(right_status, { Foreground = { Color = scheme.ansi[1] } })
table.insert(right_status, { Attribute = { Intensity = "Bold" } }) table.insert(right_status, { Attribute = { Intensity = "Bold" } })
table.insert(right_status, { Text = cwd_path }) table.insert(right_status, { Text = cwd_path .. " " })
end
-- domain name
table.insert(right_status, { Background = { Color = scheme.brights[1] } })
table.insert(right_status, { Foreground = { Color = scheme.ansi[8] } })
table.insert(right_status, { Text = " " .. pane:get_domain_name() .. " " })
window:set_right_status(wezterm.format(right_status)) window:set_right_status(wezterm.format(right_status))
end) end)

View file

@ -0,0 +1,5 @@
---@meta
---@alias AudibleBell
---| "SystemBeep" Perform the system beep or alert sound. This is the default. On Wayland systems, which have no system beep function, it does not produce a sound.
---| "Disabled" Don't make a sound

View file

@ -0,0 +1,31 @@
---@meta
---@alias HexColor string A color in the form "#RRGGBB" or "#RRGGBBAA" where the AA component is optional and defaults to "FF" if not specified.
---@class FileSource
---@field File string Load the specified image file. PNG, JPEG, GIF, BMP, ICO, TIFF, PNM, DDS, TGA and farbfeld files can be loaded. Animated GIF and PNG files will animate while the window has focus.
---@class FileSourceWithPath
---@field File {path: string, speed: number} Load the specified image file, which is an animated gif, and adjust the animation speed to x times its normal speed.
---@class GradientSource
---@field Gradient Gradient Generate a gradient
---@class ColorSource
---@field Color {Color: AnsiColor | HexColor} Generate an image with the specified color.
---@class BackgroundLayer
---@field source FileSource | FileSourceWithPath | GradientSource | ColorSource Defines the source of the layer texture data.
---@field attachment "Fixed" | "Scroll" | {Parallax: number} Controls whether the layer is fixed to the viewport or moves as it scrolls.
---@field repeat_x "Repeat" | "Mirror" | "NoRepeat" Controls whether the image is repeated in the x-direction.
---@field repeat_y "Repeat" | "Mirror" | "NoRepeat" Controls whether the image is repeated in the y-direction.
---@field repeat_x_size number | string Normally, when repeating, the image is tiled based on its width such that each copy of the image is immediately adjacent to the preceding instance. You may set `repeat_x_size` to a different value to increase or decrease the space between the repeated instances.
---@field repeat_y_size number | string Normally, when repeating, the image is tiled based on its width such that each copy of the image is immediately adjacent to the preceding instance. You may set `repeat_y_size` to a different value to increase or decrease the space between the repeated instances.
---@field vertical_align "Top" | "Middle" | "Bottom" Controls the initial vertical position of the layer, relative to the viewport.
---@field horizontal_align "Left" | "Center" | "Right" Controls the initial horizontal position of the layer, relative to the viewport.
---@field vertical_offset number | string Specify an offset from the initial vertical position.
---@field horizontal_offset number | string Specify an offset from the initial horizontal position.
---@field opacity number A number in the range `0` through `1.0` inclusive that is multiplied with the alpha channel of the source to adjust the opacity of the layer. The default is `1.0` to use the source alpha channel as-is. Using a smaller value makes the layer less opaque/more transparent.
---@field hsb HsbTransform A hue, saturation, brightness transformation that can be used to adjust those attributes of the layer.
---@field height "Cover" | "Contain" | number | string Controls the height of the image.
---@field width "Cover" | "Contain" | number | string Controls the width of the image.

View file

@ -0,0 +1,6 @@
---@meta
---@class DaemonOptions
---@field pid_file string Specify the location of the pid and lock file. The default location is `$XDG_RUNTIME_DIR/wezterm/pid` on X11/Wayland systems, or `$HOME/.local/share/wezterm/pid`.
---@field stdout string Specifies where a log of the stdout stream from the daemon will be placed. The default is `$XDG_RUNTIME_DIR/wezterm/stdout` on X11/Wayland systems, or `$HOME/.local/share/wezterm/stdout`.
---@field stderr string Specifies where a log of the stderr stream from the daemon will be placed. The default is `$XDG_RUNTIME_DIR/wezterm/stderr` on X11/Wayland systems, or `$HOME/.local/share/wezterm/stderr`.

View file

@ -0,0 +1,449 @@
---@meta
---@class Config
---@field font FontAttributes The baseline font to use
---@field dpi_by_screen { [string]: f64 }
---@field colors Palette The color palette
---@field switch_to_last_active_tab_when_closing_tab bool
---@field window_frame WindowFrameConfig
---@field char_select_font_size f64
---@field char_select_fg_color RgbaColor
---@field char_select_bg_color RgbaColor
---@field command_palette_font_size f64
---@field command_palette_fg_color RgbaColor
---@field command_palette_bg_color RgbaColor
---@field pane_select_font_size f64
---@field pane_select_fg_color RgbaColor
---@field pane_select_bg_color RgbaColor
---@field tab_bar_style TabBarStyle
---@field resolved_palette Palette
---@field color_scheme String
-- -- Use a named color scheme rather than the palette specified
-- -- by the colors setting.
---@field color_schemes {[String]: Palette}
-- -- Named color schemes
---@field scrollback_lines usize
-- -- How many lines of scrollback you want to retain
---@field default_prog String[]
-- -- If no `prog` is specified on the command line, use this
-- -- instead of running the user's shell.
-- -- For example, to have `wezterm` always run `top` by default
-- -- you'd use this:
-- --
-- -- ```toml
-- -- ```
-- --
-- -- `default_prog` is implemented as an array where the 0th element
-- -- is the command to run and the rest of the elements are passed
-- -- as the positional arguments to that command.
---@field default_gui_startup_args String[]
---@field default_cwd PathBuf
-- -- Specifies the default current working directory if none is specified
-- -- through configuration or OSC 7 (see docs for `default_cwd` for more
-- -- info!)
---@field exit_behavior ExitBehavior
---@field exit_behavior_messaging ExitBehaviorMessaging
---@field clean_exit_codes u32[]
---@field detect_password_input bool
---@field set_environment_variables {[String]: String}
-- -- Specifies a map of environment variables that should be set
-- -- when spawning commands in the local domain.
-- -- This is not used when working with remote domains.
---@field initial_rows u16
-- -- Specifies the height of a new window, expressed in character cells.
---@field enable_kitty_graphics bool
---@field enable_kitty_keyboard bool
---@field enable_title_reporting bool
-- -- Whether the terminal should respond to requests to read the
-- -- title string.
-- -- Disabled by default for security concerns with shells that might
-- -- otherwise attempt to execute the response.
-- -- <https://marc.info/?l=bugtraq&m=104612710031920&w=2>
---@field initial_cols u16
-- -- Specifies the width of a new window, expressed in character cells
---@field hyperlink_rules HyperlinkRule[]
---@field term String
-- -- What to set the TERM variable to
---@field font_locator FontLocatorSelection
---@field font_rasterizer FontRasterizerSelection
---@field font_shaper FontShaperSelection
---@field display_pixel_geometry DisplayPixelGeometry
---@field freetype_load_target FreeTypeLoadTarget
---@field freetype_render_target FreeTypeLoadTarget
---@field freetype_load_flags FreeTypeLoadFlags
---@field freetype_interpreter_version u32
-- -- Selects the freetype interpret version to use.
-- -- Likely values are 35, 38 and 40 which have different
-- -- characteristics with respective to subpixel hinting.
-- -- See https://freetype.org/freetype2/docs/subpixel-hinting.html
---@field freetype_pcf_long_family_names bool
---@field harfbuzz_features String[]
-- -- Specify the features to enable when using harfbuzz for font shaping.
-- -- There is some light documentation here:
-- -- <https://harfbuzz.github.io/shaping-opentype-features.html>
-- -- but it boils down to allowing opentype feature names to be specified
-- -- using syntax similar to the CSS font-feature-settings options:
-- -- <https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings>.
-- -- The OpenType spec lists a number of features here:
-- -- <https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist>
-- --
-- -- Options of likely interest will be:
-- --
-- -- * `calt` - <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#tag-calt>
-- -- * `clig` - <https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#tag-clig>
-- --
-- -- If you want to disable ligatures in most fonts, then you may want to
-- -- use a setting like this:
-- --
-- -- ```toml
-- -- harfbuzz_features ["calt=0", "clig=0", "liga=0"]
-- -- ```
-- --
-- -- Some fonts make available extended options via stylistic sets.
-- -- If you use the [Fira Code font](https://github.com/tonsky/FiraCode)
-- -- it lists available stylistic sets here:
-- -- <https://github.com/tonsky/FiraCode/wiki/How-to-enable-stylistic-sets>
-- --
-- -- and you can set them in wezterm:
-- --
-- -- ```toml
-- -- # Use this for a zero with a dot rather than a line through it
-- -- # when using the Fira Code font
-- -- harfbuzz_features ["zero"]
-- -- ```
---@field front_end FrontEndSelection
---@field webgpu_power_preference WebGpuPowerPreference
-- -- Whether to select the higher powered discrete GPU when
-- -- the system has a choice of integrated or discrete.
-- -- Defaults to low power.
---@field webgpu_force_fallback_adapter bool
---@field webgpu_preferred_adapter GpuInfo
---@field wsl_domains WslDomain[]
---@field exec_domains ExecDomain[]
---@field serial_ports SerialDomain[]
---@field unix_domains UnixDomain[]
-- -- The set of unix domains
---@field ssh_domains SSHDomainObj[]
---@field ssh_backend SshBackend
---@field tls_servers TlsDomainServer[]
-- -- When running in server mode, defines configuration for
-- -- each of the endpoints that we'll listen for connections
---@field tls_clients TlsDomainClient[]
-- -- The set of tls domains that we can connect to as a client
---@field ratelimit_mux_line_prefetches_per_second u32
-- -- Constrains the rate at which the multiplexer client will
-- -- speculatively fetch line data.
-- -- This helps to avoid saturating the link between the client
-- -- and server if the server is dumping a large amount of output
-- -- to the client.
---@field mux_output_parser_buffer_size usize
-- -- The buffer size used by parse_buffered_data in the mux module.
-- -- This should not be too large, otherwise the processing cost
-- -- of applying a batch of actions to the terminal will be too
-- -- high and the user experience will be laggy and less responsive.
---@field mux_output_parser_coalesce_delay_ms u64
-- -- How many ms to delay after reading a chunk of output
-- -- in order to try to coalesce fragmented writes into
-- -- a single bigger chunk of output and reduce the chances
-- -- observing "screen tearing" with un-synchronized output
---@field mux_env_remove String[]
---@field keys Key[]
---@field key_tables {[String]: Key[]}
---@field bypass_mouse_reporting_modifiers Modifiers
---@field debug_key_events bool
---@field normalize_output_to_unicode_nfc bool
---@field disable_default_key_bindings bool
---@field leader LeaderKey
---@field disable_default_quick_select_patterns bool
---@field quick_select_patterns String[]
---@field quick_select_alphabet String
---@field mouse_bindings Mouse[]
---@field disable_default_mouse_bindings bool
---@field daemon_options DaemonOptions
---@field send_composed_key_when_left_alt_is_pressed bool
---@field send_composed_key_when_right_alt_is_pressed bool
---@field macos_forward_to_ime_modifier_mask Modifiers
---@field treat_left_ctrlalt_as_altgr bool
---@field swap_backspace_and_delete bool
-- -- If true, the `Backspace` and `Delete` keys generate `Delete` and `Backspace`
-- -- keypresses, respectively, rather than their normal keycodes.
-- -- On macOS the default for this is true because its Backspace key
-- -- is labeled as Delete and things are backwards.
---@field enable_tab_bar bool
-- -- If true, display the tab bar UI at the top of the window.
-- -- The tab bar shows the titles of the tabs and which is the
-- -- active tab. Clicking on a tab activates it.
---@field use_fancy_tab_bar bool
---@field tab_bar_at_bottom bool
---@field mouse_wheel_scrolls_tabs bool
---@field show_tab_index_in_tab_bar bool
-- -- If true, tab bar titles are prefixed with the tab index
---@field show_tabs_in_tab_bar bool
---@field show_new_tab_button_in_tab_bar bool
---@field tab_and_split_indices_are_zero_based bool
-- -- If true, show_tab_index_in_tab_bar uses a zero-based index.
-- -- The default is false and the tab shows a one-based index.
---@field tab_max_width usize
-- -- Specifies the maximum width that a tab can have in the
-- -- tab bar. Defaults to 16 glyphs in width.
---@field hide_tab_bar_if_only_one_tab bool
-- -- If true, hide the tab bar if the window only has a single tab.
---@field enable_scroll_bar bool
---@field min_scroll_bar_height Dimension
---@field enable_wayland bool
-- -- If false, do not try to use a Wayland protocol connection
-- -- when starting the gui frontend, and instead use X11.
-- -- This option is only considered on X11/Wayland systems and
-- -- has no effect on macOS or Windows.
-- -- The default is true.
---@field enable_zwlr_output_manager bool
-- -- driver updates without breaking and losing your work.
-- -- Whether to prefer EGL over other GL implementations.
-- -- EGL on Windows has jankier resize behavior than WGL (which
-- -- is used if EGL is unavailable), but EGL survives graphics
---@field prefer_egl bool
---@field custom_block_glyphs bool
---@field anti_alias_custom_block_glyphs bool
---@field window_padding WindowPadding
-- -- Controls the amount of padding to use around the terminal cell area
---@field window_background_image PathBuf
-- -- Specifies the path to a background image attachment file.
-- -- The file can be any image format that the rust `image`
-- -- crate is able to identify and load.
-- -- A window background image is rendered into the background
-- -- of the window before any other content.
-- --
-- -- The image will be scaled to fit the window.
---@field window_background_gradient Gradient
---@field window_background_image_hsb HsbTransform
---@field foreground_text_hsb HsbTransform
---@field background BackgroundLayer[]
---@field macos_window_background_blur i64
-- -- Only works on MacOS
---@field win32_system_backdrop SystemBackdrop
-- -- Only works on Windows
---@field win32_acrylic_accent_color RgbaColor
---@field window_background_opacity f32
-- -- Specifies the alpha value to use when rendering the background
-- -- of the window. The background is taken either from the
-- -- window_background_image, or if there is none, the background
-- -- color of the cell in the current position.
-- -- The default is 1.0 which is 100% opaque. Setting it to a number
-- -- between 0.0 and 1.0 will allow for the screen behind the window
-- -- to "shine through" to varying degrees.
-- -- This only works on systems with a compositing window manager.
-- -- Setting opacity to a value other than 1.0 can impact render
-- -- performance.
---@field inactive_pane_hsb HsbTransform
-- -- inactive_pane_hue, inactive_pane_saturation and
-- -- inactive_pane_brightness allow for transforming the color
-- -- of inactive panes.
-- -- The pane colors are converted to HSV values and multiplied
-- -- by these values before being converted back to RGB to
-- -- use in the display.
-- --
-- -- The default is 1.0 which leaves the values as-is.
-- --
-- -- Modifying the hue changes the hue of the color by rotating
-- -- it through the color wheel. It is not as useful as the
-- -- other components, but is available "for free" as part of
-- -- the colorspace conversion.
-- --
-- -- Modifying the saturation can add or reduce the amount of
-- -- "colorfulness". Making the value smaller can make it appear
-- -- more washed out.
-- --
-- -- Modifying the brightness can be used to dim or increase
-- -- the perceived amount of light.
-- --
-- -- The range of these values is 0.0 and up; they are used to
-- -- multiply the existing values, so the default of 1.0
-- -- preserves the existing component, whilst 0.5 will reduce
-- -- it by half, and 2.0 will double the value.
-- --
-- -- A subtle dimming effect can be achieved by setting:
-- -- inactive_pane_saturation 0.9
-- -- inactive_pane_brightness 0.8
---@field text_background_opacity f32
---@field cursor_blink_rate u64
-- -- Specifies how often a blinking cursor transitions between visible
-- -- and invisible, expressed in milliseconds.
-- -- Setting this to 0 disables blinking.
-- -- Note that this value is approximate due to the way that the system
-- -- event loop schedulers manage timers; non-zero values will be at
-- -- least the interval specified with some degree of slop.
---@field cursor_blink_ease_in EasingFunction
---@field cursor_blink_ease_out EasingFunction
---@field animation_fps u8
---@field force_reverse_video_cursor bool
---@field default_cursor_style "SteadyBlock" | "BlinkingBlock" | "SteadyUnderline" | "BlinkingUnderline" | "SteadyBar" | "BlinkingBar"
-- -- Specifies the default cursor style. various escape sequences
-- -- can override the default style in different situations (eg:
-- -- an editor can change it depending on the mode), but this value
-- -- controls how the cursor appears when it is reset to default.
-- -- The default is `SteadyBlock`.
-- -- Acceptable values are `SteadyBlock`, `BlinkingBlock`
-- -- `SteadyUnderline`, `BlinkingUnderline`, `SteadyBar`
-- -- and `BlinkingBar`.
---@field text_blink_rate u64
-- -- Specifies how often blinking text (normal speed) transitions
-- -- between visible and invisible, expressed in milliseconds.
-- -- Setting this to 0 disables slow text blinking. Note that this
-- -- value is approximate due to the way that the system event loop
-- -- schedulers manage timers; non-zero values will be at least the
-- -- interval specified with some degree of slop.
---@field text_blink_ease_in EasingFunction
---@field text_blink_ease_out EasingFunction
---@field text_blink_rate_rapid u64
-- -- Specifies how often blinking text (rapid speed) transitions
-- -- between visible and invisible, expressed in milliseconds.
-- -- Setting this to 0 disables rapid text blinking. Note that this
-- -- value is approximate due to the way that the system event loop
-- -- schedulers manage timers; non-zero values will be at least the
-- -- interval specified with some degree of slop.
---@field text_blink_rapid_ease_in EasingFunction
---@field text_blink_rapid_ease_out EasingFunction
---@field hide_mouse_cursor_when_typing bool
-- -- If true, the mouse cursor will be hidden while typing.
-- -- This option is true by default.
---@field periodic_stat_logging u64
-- -- If non-zero, specifies the period (in seconds) at which various
-- -- statistics are logged. Note that there is a minimum period of
-- -- 10 seconds.
---@field scroll_to_bottom_on_input bool
-- -- If false, do not scroll to the bottom of the terminal when
-- -- you send input to the terminal.
-- -- The default is to scroll to the bottom when you send input
-- -- to the terminal.
---@field use_ime bool
---@field xim_im_name String
---@field ime_preedit_rendering "Builtin" | "System" Control IME preedit rendering. IME preedit is an area that is used to display the string being preedited in IME.
---@field use_dead_keys bool
---@field launch_menu SpawnCommand[]
---@field use_box_model_render bool
---@field automatically_reload_config bool
-- -- When true, watch the config file and reload it automatically
-- -- when it is detected as changing.
---@field check_for_updates bool
---@field show_update_window bool
---@field check_for_updates_interval_seconds u64
---@field enable_csi_u_key_encoding bool
-- -- When set to true, use the CSI-U encoding scheme as described
-- -- in http://www.leonerd.org.uk/hacks/fixterms/
-- -- This is off by default because @wez and @jsgf find the shift-space
-- -- mapping annoying in vim :-p
---@field window_close_confirmation "AlwaysPrompt" | "NeverPrompt" Whether to display a confirmation prompt when the window is closed by the windowing environment, either because the user closed it with the window decorations, or instructed their window manager to close it. Set this to "NeverPrompt" if you don't like confirming closing windows every time.
---@field native_macos_fullscreen_mode bool
---@field selection_word_boundary String
---@field enq_answerback String
---@field adjust_window_size_when_changing_font_size bool
---@field tiling_desktop_environments String[]
---@field use_resize_increments bool
---@field alternate_buffer_wheel_scroll_speed u8
---@field status_update_interval u64
---@field experimental_pixel_positioning bool
---@field bidi_enabled bool
---@field bidi_direction ParagraphDirectionHint
---@field skip_close_confirmation_for_processes_named String[]
---@field quit_when_all_windows_are_closed bool
---@field warn_about_missing_glyphs bool
---@field sort_fallback_fonts_by_coverage bool
---@field search_font_dirs_for_fallback bool
---@field use_cap_height_to_scale_fallback_fonts bool
---@field swallow_mouse_click_on_pane_focus bool
---@field swallow_mouse_click_on_window_focus bool
---@field pane_focus_follows_mouse bool
---@field unzoom_on_switch_pane bool
---@field max_fps u8 Limits the maximum number of frames per second that wezterm will attempt to draw.
---@field shape_cache_size usize
---@field line_state_cache_size usize
---@field line_quad_cache_size usize
---@field line_to_ele_shape_cache_size usize
---@field glyph_cache_image_cache_size usize
---@field visual_bell VisualBell
---@field audible_bell AudibleBell
---@field canonicalize_pasted_newlines NewlineCanon
---@field unicode_version u8
---@field treat_east_asian_ambiguous_width_as_wide bool
---@field allow_download_protocols bool
---@field allow_win32_input_mode bool
---@field default_domain String
---@field default_mux_server_domain String
---@field default_workspace String
---@field xcursor_theme String
---@field xcursor_size u32
---@field key_map_preference "Mapped" | "Physical" Controls how keys without an explicit phys: or mapped: prefix are treated.
---@field quote_dropped_files DroppedFileQuoting
---@field ui_key_cap_rendering UIKeyCapRendering
---@field palette_max_key_assigments_for_action usize
---@field ulimit_nofile u64
---@field ulimit_nproc u64
local WeztermConfig = {
-- The font size, measured in points
font_size = 12.0,
-- must be greater than 0
line_height = 1.0,
-- default = "default_one_point_oh_f64"
cell_width = 1.0,
---@type Dimension
-- specified by underline_thickness
cursor_thickess = 2.0,
---@type Dimension
-- specified by font
underline_thickness = 2.0,
---@type Dimension
underline_position = -2,
---@type Dimension
strikethrough_position = 2.0,
---@type "Allow" | "Never" | "WhenFollowedBySpace"
allow_square_glyphs_to_overflow_width = 'Never',
---@type WindowDecorations
window_decorations = 'TITLE | RESIZE',
---@type IntegratedTitleButton[]
integrated_title_buttons = {'Hide', 'Maximize', 'Close'},
log_unknown_escape_sequences = false,
---@type IntegratedTitleButtonAlignment
integrated_title_button_alignment = 'Right',
---@type IntegratedTitleButtonStyle
-- default is MacOsNative no Mac, Windows on all others
integrated_title_button_style = 'Windows',
-- Auto or custom color like "red"
integrated_title_button_color = 'Auto',
-- When using FontKitXXX font systems, a set of directories to search ahead of the standard font locations for fonts.
-- Relative paths are taken to be relative to the directory from which the config was loaded.
-- This tells wezterm to look first for fonts in the directory named `fonts` that is found alongside your `wezterm.lua` file.
-- As this option is an array, you may list multiple locations if you wish.
font_dirs = {'fonts'},
color_scheme_dirs = {'colorschemes'},
-- The DPI to assume
-- Override the detected DPI (dots per inch) for the display.
-- This can be useful if the detected DPI is inaccurate and the text appears either blurry or too small (especially if you are using a 4K display on X11 or Wayland).
-- The default value is system specific:
dpi = 96,
---@type BoldBrightening
-- When true ("BrightAndBold"), PaletteIndex 0-7 are shifted to bright when the font intensity is bold.
-- The brightening doesn't apply to text that is the default color.
-- can also use true or false for backwards compatibility
bold_brightens_ansi_colors = 'BrightAndBold',
}
-- TODO: finish less commonly used conig options (maybe set the defaults, might be too much time)
-- -- An optional set of style rules to select the font based
-- -- on the cell attributes
-- font_rules = Vec<StyleRule>,

View file

@ -0,0 +1,8 @@
---@meta
---@alias DroppedFileQuoting
---| "None" No quoting is performed, the file name is passed through as-is.
---| "SpacesOnly" Backslash-escape only spaces, leaving all other characters as-is. This is the default for non-Windows platforms.
---| "Posix" Use POSIX style shell word escaping.
---| "Windows" Use Windows style shell word escaping: double-quote filename with space characters in it, and leaving others as-is. This is the default on Windows.
---| "WindowsAlwaysQuoted" Like "Windows", while always double-quote the filename.

View file

@ -0,0 +1,8 @@
---@meta
---@alias UIKeyCapRendering
---| "UnixLong" - `Super`, `Meta`, `Ctrl`, `Shift`
---| "Emacs" - `Super`, `M`, `C`, `S`
---| "AppleSymbols" - Use macOS style symbols for Command, Option and so on.
---| "WindowsLong" - `Win`, `Alt`, `Ctrl`, `Shift`
---| "WindowsSymbols" - Like `WindowsLong` but using a logo for the Win key.

View file

@ -0,0 +1,16 @@
---@meta
---@alias EasingFunction
---| "Linear" The fade happens at a constant rate
---| "Ease" The fade starts slowly, accelerates sharply, and then slows gradually towards the end. This is the default.
---| "EaseIn" The fade starts slowly, and then progressively speeds up until the end, at which point it stops abruptly.
---| "EaseInOut" The fade starts slowly, speeds up, and then slows down towards the end.
---| "EaseOut" The fade starts abruptly, and then progressively slows down towards the end.
---| "{CubicBezier= number[] }" an arbitrary cubic bezier with the specified parameters.
---| "Constant" Evaluates as 0 regardless of time. Useful to implement a step transition at the end of the duration.
---@class VisualBell
---@field fade_in_function EasingFunction
---@field fade_in_duration_ms EasingFunction
---@field fade_out_function EasingFunction
---@field fade_out_duration_ms EasingFunction

View file

@ -0,0 +1,8 @@
---@meta
---@alias SystemBackdrop
---| "Auto" the system chooses. In practice, this is the same as "Disable". This is the default value.
---| "Disable" disable backdrop effects.
---| "Acrylic" enable the Acrylic blur-behind-window effect. Available on Windows 10 and 11.
---| "Mica" enable the Mica effect, available on Windows 11 build 22621 and later.
---| "Tabbed" enable the Tabbed effect, available on Windows 11 build 22621 and later.

View file

@ -0,0 +1,7 @@
---@meta
---@class WindowPadding
---@field left number | string The number of cells of padding on the left side of the window. You may express padding using a number of different units by specifying a string value with a unit suffix, for example `1px`, `1cell` or `1%`.
---@field right number | string The number of cells of padding on the right side of the window. You may express padding using a number of different units by specifying a string value with a unit suffix, for example `1px`, `1cell` or `1%`.
---@field top number | string The number of cells of padding on the top side of the window. You may express padding using a number of different units by specifying a string value with a unit suffix, for example `1px`, `1cell` or `1%`.
---@field bottom number | string The number of cells of padding on the bottom side of the window. You may express padding using a number of different units by specifying a string value with a unit suffix, for example `1px`, `1cell` or `1%`.

View file

@ -0,0 +1,5 @@
---@meta
--TODO:? incomplete
---@alias CopyModeAssignment "AcceptPattern" | "ClearPattern" | "ClearSelectionMode" | "Close" | "CycleMatchType" | "EditPattern" | "MoveBackwardSemanticZone" | "MoveBackwardSemanticZoneOfType" | "MoveBackwardWord" | "MoveDown" | "MoveForwardSemanticZone" | "MoveForwardSemanticZoneOfType" | "MoveForwardWord" | "MoveForwardWordEnd" | "MoveLeft" | "MoveRight" | "MoveToEndOfLineContent" | "MoveToScrollbackBottom" | "MoveToScrollbackTop" | "MoveToSelectionOtherEnd" | "MoveToSelectionOtherEndHoriz" | "MoveToStartOfLine" | "MoveToStartOfLineContent" | "MoveToStartOfNextLine" | "MoveToViewportBottom" | "MoveToViewportMiddle" | "MoveToViewportTop" | "MoveUp" | "NextMatch" | "NextMatchPage" | "PriorMatch" | "PriorMatchPage" | "SetSelectionMode"

View file

@ -0,0 +1,175 @@
---@meta
--TODO:? make key and mods more specific
---@alias KeyAssignment "ActivateCommandPalette" | "ActivateCopyMode" | "ActivateKeyTable" | "ActivateLastTab" | "ActivatePaneByIndex" | "ActivatePaneDirection" | "ActivateTab" | "ActivateTabRelative" | "ActivateTabRelativeNoWrap" | "ActivateWindow" | "ActivateWindowRelative" | "ActivateWindowRelativeNoWrap" | "AdjustPaneSize" | "AttachDomain" | "CharSelect" | "ClearKeyTableStack" | "ClearScrollback" | "ClearSelection" | "CloseCurrentPane" | "CloseCurrentTab" | "CompleteSelection" | "CompleteSelectionOrOpenLinkAtMouseCursor" | "Copy" | "CopyTo" | "DecreaseFontSize" | "DetachDomain" | "DisableDefaultAssignment" | "EmitEvent" | "ExtendSelectionToMouseCursor" | "Hide" | "HideApplication" | "IncreaseFontSize" | "InputSelector" | "MoveTab" | "MoveTabRelative" | "Multiple" | "Nop" | "OpenLinkAtMouseCursor" | "PaneSelect" | "Paste" | "PasteFrom" | "PastePrimarySelection" | "PopKeyTable" | "PromptInputLine" | "QuickSelect" | "QuickSelectArgs" | "QuitApplication" | "ReloadConfiguration" | "ResetFontAndWindowSize" | "ResetFontSize" | "ResetTerminal" | "RotatePanes" | "ScrollByCurrentEventWheelDelta" | "ScrollByLine" | "ScrollByPage" | "ScrollToBottom" | "ScrollToPrompt" | "ScrollToTop" | "Search" | "SelectTextAtMouseCursor" | "SendKey" | "SendString" | "SetPaneZoomState" | "Show" | "ShowDebugOverlay" | "ShowLauncher" | "ShowLauncherArgs" | "ShowTabNavigator" | "SpawnCommandInNewTab" | "SpawnCommandInNewWindow" | "SpawnTab" | "SpawnWindow" | "SplitHorizontal" | "SplitPane" | "SplitVertical" | "StartWindowDrag" | "SwitchToWorkspace" | "SwitchWorkspaceRelative" | "ToggleFullScreen" | "TogglePaneZoomState"
---@class KeyNoAction
---@field key string
---@field mods? string
---@class Key :KeyNoAction
---@field action KeyAssignment
---@class Action can also be called as function like older versions of wezterm did
local Action = {}
---@return KeyAssignment
Action.ActivateCommandPalette = function(param) end
---@return KeyAssignment
Action.ActivateCopyMode = function(param) end
---@return KeyAssignment
Action.ActivateKeyTable = function(param) end
---@return KeyAssignment
Action.ActivateLastTab = function(param) end
---@return KeyAssignment
Action.ActivatePaneByIndex = function(param) end
---@return KeyAssignment
Action.ActivatePaneDirection = function(param) end
---@return KeyAssignment
Action.ActivateTab = function(param) end
---@return KeyAssignment
Action.ActivateTabRelative = function(param) end
---@return KeyAssignment
Action.ActivateTabRelativeNoWrap = function(param) end
---@return KeyAssignment
Action.ActivateWindow = function(param) end
---@return KeyAssignment
Action.ActivateWindowRelative = function(param) end
---@return KeyAssignment
Action.ActivateWindowRelativeNoWrap = function(param) end
---@return KeyAssignment
Action.AdjustPaneSize = function(param) end
---@return KeyAssignment
Action.AttachDomain = function(param) end
---@return KeyAssignment
Action.CharSelect = function(param) end
---@return KeyAssignment
Action.ClearKeyTableStack = function(param) end
---@return KeyAssignment
Action.ClearScrollback = function(param) end
---@return KeyAssignment
Action.ClearSelection = function(param) end
---@return KeyAssignment
Action.CloseCurrentPane = function(param) end
---@return KeyAssignment
---@param param {confirm: boolean}
Action.CloseCurrentTab = function(param) end
---@return KeyAssignment
Action.CompleteSelection = function(param) end
Action.CompleteSelectionOrOpenLinkAtMouseCursor = function(param) end
---@return KeyAssignment
Action.Copy = function(param) end
---@return KeyAssignment
Action.CopyTo = function(param) end
---@return KeyAssignment
Action.DecreaseFontSize = function(param) end
---@return KeyAssignment
Action.DetachDomain = function(param) end
---@return KeyAssignment
Action.DisableDefaultAssignment = function(param) end
---@return KeyAssignment
Action.EmitEvent = function(param) end
---@return KeyAssignment
Action.ExtendSelectionToMouseCursor = function(param) end
---@return KeyAssignment
Action.Hide = function(param) end
---@return KeyAssignment
Action.HideApplication = function(param) end
---@return KeyAssignment
Action.IncreaseFontSize = function(param) end
---@return KeyAssignment
Action.InputSelector = function(param) end
---@return KeyAssignment
Action.MoveTab = function(param) end
---@return KeyAssignment
Action.MoveTabRelative = function(param) end
---@return KeyAssignment
Action.Multiple = function(param) end
---@return KeyAssignment
Action.Nop = function(param) end
---@return KeyAssignment
Action.OpenLinkAtMouseCursor = function(param) end
---@return KeyAssignment
Action.PaneSelect = function(param) end
---@return KeyAssignment
Action.Paste = function(param) end
---@return KeyAssignment
Action.PasteFrom = function(param) end
---@return KeyAssignment
Action.PastePrimarySelection = function(param) end
---@return KeyAssignment
Action.PopKeyTable = function(param) end
---@return KeyAssignment
Action.PromptInputLine = function(param) end
---@return KeyAssignment
Action.QuickSelect = function(param) end
---@return KeyAssignment
Action.QuickSelectArgs = function(param) end
---@return KeyAssignment
Action.QuitApplication = function(param) end
---@return KeyAssignment
Action.ReloadConfiguration = function(param) end
---@return KeyAssignment
Action.ResetFontAndWindowSize = function(param) end
---@return KeyAssignment
Action.ResetFontSize = function(param) end
Action.ResetTerminal = function(param) end
---@return KeyAssignment
Action.RotatePanes = function(param) end
---@return KeyAssignment
Action.ScrollByCurrentEventWheelDelta = function(param) end
---@return KeyAssignment
Action.ScrollByLine = function(param) end
---@return KeyAssignment
Action.ScrollByPage = function(param) end
---@return KeyAssignment
Action.ScrollToBottom = function(param) end
---@return KeyAssignment
Action.ScrollToPrompt = function(param) end
---@return KeyAssignment
Action.ScrollToTop = function(param) end
---@return KeyAssignment
Action.Search = function(param) end
---@return KeyAssignment
Action.SelectTextAtMouseCursor = function(param) end
---@return KeyAssignment
Action.SendKey = function(param) end
---@return KeyAssignment
Action.SendString = function(param) end
---@return KeyAssignment
Action.SetPaneZoomState = function(param) end
---@return KeyAssignment
Action.Show = function(param) end
---@return KeyAssignment
Action.ShowDebugOverlay = function(param) end
---@return KeyAssignment
Action.ShowLauncher = function(param) end
---@return KeyAssignment
Action.ShowLauncherArgs = function(param) end
---@return KeyAssignment
Action.ShowTabNavigator = function(param) end
---@return KeyAssignment
Action.SpawnCommandInNewTab = function(param) end
---@return KeyAssignment
Action.SpawnCommandInNewWindow = function(param) end
---@return KeyAssignment
Action.SpawnTab = function(param) end
---@return KeyAssignment
Action.SpawnWindow = function(param) end
---@return KeyAssignment
Action.SplitHorizontal = function(param) end
---@return KeyAssignment
Action.SplitPane = function(param) end
---@return KeyAssignment
Action.SplitVertical = function(param) end
---@return KeyAssignment
Action.StartWindowDrag = function(param) end
---@return KeyAssignment
Action.SwitchToWorkspace = function(param) end
---@return KeyAssignment
Action.SwitchWorkspaceRelative = function(param) end
---@return KeyAssignment
Action.ToggleFullScreen = function(param) end
---@return KeyAssignment
Action.TogglePaneZoomState = function(param) end

View file

@ -0,0 +1,5 @@
---@meta
--TODO: finish
---@alias GuiEvent "gui-attached" | "gui-startup"

View file

@ -0,0 +1,5 @@
---@meta
--TODO: finish
---@alias MultiplexerEvent "mux-is-process-stateful" | "mux-startup"

View file

@ -0,0 +1,5 @@
---@meta
--TODO: finish
---@alias WindowEvent "augment-command-palette" | "bell" | "format-tab-title" | "format-window-title" | "new-tab-button-click" | "open-uri" | "update-right-status" | "update-status" | "user-var-changed" | "window-config-reloaded" | "window-focus-changed" | "window-resized"

View file

@ -1,217 +1,494 @@
---@meta ---@meta
---@class WezTerm --- alias to help identify types that should actually be any
local wezterm = { ---@alias ANY any
---@module 'wezterm.color'
color = {},
---@module 'wezterm.gui' ---@alias FormatItemAttribute { Underline: "None" | "Single" | "Double" | "Curly" | "Dotted" | "Dashed" } | { Intensity: "Normal" | "Bold" | "Half" } | { Italic: boolean }
gui = {}, ---@alias FormatItemReset "ResetAttributes" Reset all attributes to default.
---@alias FormatItem { Attribute: FormatItemAttribute } | { Foreground: ColorSpec } | { Background: ColorSpec } | { Text: string } | FormatItemReset
---@module 'wezterm.mux' ---@alias CopyToTarget "Clipboard" | "PrimarySelection" | "ClipboardAndPrimarySelection"
mux = {},
---@module 'wezterm.procinfo' ---@alias SshBackend "Ssh2" | "LibSsh"
procinfo = {},
---@module 'wezterm.time' ---@alias Modifiers "NONE" | "SHIFT" | "ALT" | "CTRL" | "SUPER" | "LEFT_ALT" | "RIGHT_ALT" | "LEFT_CTRL" | "RIGHT_CTRL" | "LEFT_SHIFT" | "RIGHT_SHIFT" | "ENHANCED_KEY"
time = {}, ---| "LEADER" This is a virtual modifier used by wezterm
---@type table<string, any> ---@alias WebGpuPowerPreference "LowPower" | "HighPerformance"
GLOBAL = {},
---@type _.wezterm.KeyAssignment ---@alias FontRasterizerSelection "FreeType" Only Option
action = {},
---@type string ---@alias FontShaperSelection
config_dir = '', ---| "Allsorts" very preliminary support
---| "Harfbuzz" default
---@type string ---@alias FontLocatorSelection
config_file = '', ---| "FontConfig" Use fontconfig APIs to resolve fonts (!macos, posix systems)
---| "Gdi" Use GDI on win32 systems
---| "CoreText" Use CoreText on macOS
---| "ConfigDirsOnly" Use only the font_dirs configuration to locate fonts
---@type string ---@alias FrontEndSelection
executable_dir = '', ---| "OpenGL"
---| "WebGpu" default
---| "Software"
---@type string ---@alias DisplayPixelGeometry
home_dir = '', ---| "RGB" default
---| "BGR"
---@type table<string, string> ---@alias f32 number
nerdfonts = {},
---@type string ---@alias f64 number
target_triple = '',
---@type string ---@alias u8 integer
version = '',
---@param callback _.wezterm.ActionCallback ---@alias u16 integer
---@return _.wezterm._CallbackAction
action_callback = function(callback) end,
---@param path string ---@alias u32 integer
add_to_config_reload_watch_list = function(path) end,
---@param args string[] ---@alias u64 integer
background_child_process = function(args) end,
---@return _.wezterm.BatteryInfo[] ---@alias i64 integer
battery_info = function() end,
---@param string string ---@alias Duration u64
---@return number
column_width = function(string) end,
---@return _.wezterm.ConfigBuilder ---@alias usize number
config_builder = function() end,
---@return _.wezterm.HyperlinkRule[] ---@alias String string
default_hyperlink_rules = function() end,
---@return _.wezterm.SshDomain[] ---@alias Regex string
default_ssh_domains = function() end,
---@return _.wezterm.WslDomain[] ---@alias RgbColor string
default_wsl_domains = function() end, --
---@alias RgbaColor string
---@param event_name string ---@alias bool boolean
---@param ... any
---@return boolean
emit = function(event_name, ...) end,
---@param ssh_config_file_name? string ---@alias BoldBrightening "No" | "BrightAndBold" | "BrightOnly"
---@return table<string, string>
enumerate_ssh_hosts = function(ssh_config_file_name) end,
---@param family string ---@alias ExitBehavior "Close" | "CloseOnCleanExit" | "Hold"
---@param attributes? _.wezterm.FontAttributes --TODO: describe
---@return _.wezterm._Font
---@overload fun(attributes: _.wezterm.FontAttributesExtended): _.wezterm._Font
font = function(family, attributes) end,
---@param families string[] ---@alias ExitBehaviorMessaging "Verbose" | "Brief" | "Terse" | "None"
---@param attributes? _.wezterm.FontAttributes --TODO: describe
---@return _.wezterm._Font
---@overload fun(attributes: (string | _.wezterm.FontFallbackAttributesExtended)[]): _.wezterm._Font
font_with_fallback = function(families, attributes) end,
---@param format_items _.wezterm.FormatItem[] ---@alias IntegratedTitleButton "Hide" | "Maximize" | "Close"
---@return string
format = function(format_items) end,
---@return table<string, _.wezterm.Palette> ---@alias IntegratedTitleButtonAlignment "Right" | "Left"
get_builtin_color_schemes = function() end,
---@param pattern string ---@alias IntegratedTitleButtonStyle "Windows" | "Gnome" | "MacOsNative"
---@param relative_to? string
---@return string[]
glob = function(pattern, relative_to) end,
---@param gradient _.wezterm.Gradient ---@alias WindowDecorations "NONE" | "TITLE" | "RESIZE" | "TITLE | RESIZE"
---@param num_colors number
---@return _.wezterm.Color[]
gradient_colors = function(gradient, num_colors) end,
---@param name string ---@alias Points string
---@return boolean -- A value expressed in points, where 72 points == 1 inch.
has_action = function(name) end,
---@return string ---@alias Pixels string | number
hostname = function() end, -- A value expressed in raw pixels
---@param value any ---@alias Percent string
---@return string -- A value expressed in terms of a fraction of the maximum
json_encode = function(value) end, -- value in the same direction. For example, left padding
-- of 10% depends on the pixel width of that element.
-- The value is 1.0 == 100%. It is possible to express
-- eg: 2.0 for 200%.
---@param arg string ---@alias Cells string
---@param ... any -- A value expressed in terms of a fraction of the cell
log_error = function(arg, ...) end, -- size computed from the configured font size.
-- 1.0 == the cell size.
---@param arg string ---@alias Dimension Points | Pixels | Percent | Cells
---@param ... any
log_info = function(arg, ...) end,
---@param arg string ---@class TabBarColor
---@param ... any -- The color of the background area for the tab
log_warn = function(arg, ...) end, ---@field bg_color string
-- The color of the text for the tab
---@field fg_color string
-- Specify whether you want "Half", "Normal" or "Bold" intensity for the
-- label shown for this tab.
-- The default is "Normal"
---@field intensity "Half" | "Normal" | "Bold"
-- Specify whether you want "None", "Single" or "Double" underline for
-- label shown for this tab.
-- The default is "None"
---@field underline "None" | "Single" | "Double"
-- Specify whether you want the text to be italic (true) or not (false)
-- for this tab. The default is false.
---@field italic boolean
-- Specify whether you want the text to be rendered with strikethrough (true)
-- or not for this tab. The default is false.
---@field strikethrough boolean
---@overload fun(event_name: 'format-tab-title', callback: fun(tab: _.wezterm.TabInformation, tabs: _.wezterm.TabInformation[], panes: _.wezterm.PaneInformation, config: table, hover: boolean, max_width: integer): string | _.wezterm.FormatItem[]): nil ---@class TabBarColors
---@overload fun(event_name: 'update-right-status', callback: fun(window: _.wezterm.Window, pane: _.wezterm.Pane): nil): nil ---@field background string The text color to use when the attributes are reset to default
---@overload fun(event_name: 'window-config-reloaded', callback: fun(window: _.wezterm.Window, pane: _.wezterm.Pane): nil): nil ---@field inactive_tab_edge string
on = function(event_name, callback) end, ---@field inactive_tab_edge_hover string
---@param path_or_url string ---@alias AnsiColors "Black" | "Maroon" | "Green" | "Olive" | "Navy" | "Purple" | "Teal" | "Silver" | "Grey" | "Red" | "Lime" | "Yellow" | "Blue" | "Fuchsia" | "Aqua" | "White"
---@param application? string
open_with = function(path_or_url, application) end,
---@param string string ---@alias AC "AnsiColor"
---@param min_width number
---@return string
pad_left = function(string, min_width) end,
---@param string string ---@alias CO "Color"
---@param min_width number
---@return string
pad_right = function(string, min_width) end,
---@param table _.wezterm.MouseBindingBase ---@alias ColorSpec table<AC, AnsiColors> | table<CO, string>
---@return _.wezterm.MouseBinding ...
---@overload fun(table: _.wezterm.KeyBindingBase): _.wezterm.KeyBinding ...
permute_any_mods = function(table) end,
---@param table _.wezterm.MouseBindingBase ---@class Palette
---@return _.wezterm.MouseBinding ... ---@field foreground string The text color to use when the attributes are reset to default
---@overload fun(table: _.wezterm.KeyBindingBase): _.wezterm.KeyBinding ... ---@field background string The background color to use when the attributes are reset to default
permute_any_or_no_mods = function(table) end, ---@field cursor_fg string The color of the cursor
---@field cursor_bg string The color of the cursor
---@field cursor_border string The color of the cursor
---@field selection_fg string The color of selected text
---@field selection_bg string The color of selected text
---@field ansi string[] A list of 8 colors corresponding to the basic ANSI palette
---@field brights string[] A list of 8 colors corresponding to bright versions of the
---@field indexed { [number]: string } A map for setting arbitrary colors ranging from 16 to 256 in the color palette
---@field scrollbar_thumb string The color of the "thumb" of the scrollbar; the segment that represents the current viewable area
---@field split string The color of the split line between panes
---@field visual_bell string The color of the visual bell. If unspecified, the foreground color is used instead.
---@field compose_cursor string The color to use for the cursor when a dead key or leader state is active
---@field copy_mode_active_highlight_fg ColorSpec
---@field copy_mode_active_highlight_bg ColorSpec
---@field copy_mode_inactive_highlight_fg ColorSpec
---@field copy_mode_inactive_highlight_bg ColorSpec
---@field quick_select_label_fg ColorSpec
---@field quick_select_label_bg ColorSpec
---@field quick_select_match_fg ColorSpec
---@field quick_select_match_bg ColorSpec
local Palette = {
---@class TabBar :TabBarColors
-- Configure the color and styling for the tab bar
tab_bar = {
-- The color of the strip that goes along the top of the window
-- (does not apply when fancy tab bar is in use)
background = '#0b0022',
---@param path string ---@type TabBarColor
---@return string[] -- The active tab is the one that has focus in the window
read_dir = function(path) end, active_tab = {
-- The color of the background area for the tab
bg_color = '#2b2042',
-- The color of the text for the tab
fg_color = '#c0c0c0',
reload_configuration = function() end, -- Specify whether you want "Half", "Normal" or "Bold" intensity for the
-- label shown for this tab.
-- The default is "Normal"
intensity = 'Normal',
---@param args string[] -- Specify whether you want "None", "Single" or "Double" underline for
---@return boolean, string, string -- label shown for this tab.
run_child_process = function(args) end, -- The default is "None"
underline = 'None',
---@return boolean -- Specify whether you want the text to be italic (true) or not (false)
running_under_wsl = function() end, -- for this tab. The default is false.
italic = false,
---@param args string[] -- Specify whether you want the text to be rendered with strikethrough (true)
---@return string -- or not for this tab. The default is false.
shell_join_args = function(args) end, strikethrough = false,
},
---@param line string ---@type TabBarColor
---@return string|string[] -- Inactive tabs are the tabs that do not have focus
shell_quote_arg = function(line) end, inactive_tab = {
bg_color = '#1b1032',
fg_color = '#808080',
},
---@param milliseconds number ---@type TabBarColor
sleep_ms = function(milliseconds) end, -- You can configure some alternate styling when the mouse pointer
-- moves over inactive tabs
inactive_tab_hover = {
bg_color = '#3b3052',
fg_color = '#909090',
italic = true,
},
---@param str string ---@type TabBarColor
---@return string[] -- The new tab button that let you create new tabs
split_by_newlines = function(str) end, new_tab = {
bg_color = '#1b1032',
fg_color = '#808080',
},
---@param format string ---@type TabBarColor
---@return string -- You can configure some alternate styling when the mouse pointer
strftime = function(format) end, -- moves over the new tab button
new_tab_hover = {
bg_color = '#3b3052',
fg_color = '#909090',
italic = true,
},
},
---@param format string
---@return string
strftime_utc = function(format) end,
---@param string string
---@param min_width number
---@return string
truncate_left = function(string, min_width) end,
---@param string string
---@param min_width number
---@return string
truncate_right = function(string, min_width) end,
---@param str string
---@return string
utf16_to_utf8 = function(str) end,
} }
return wezterm ---@alias FontWeight "Thin" | "ExtraLight" | "Light" | "DemiLight" | "Book" | "Regular" | "Medium" | "DemiBold" | "Bold" | "ExtraBold" | "Black" | "ExtraBlack"
---@alias FontStretch "UltraCondensed" | "ExtraCondensed" | "Condensed" | "SemiCondensed" | "Normal" | "SemiExpanded" | "Expanded" | "ExtraExpanded" | "UltraExpanded"
---@alias FontStyle "Normal" | "Italic" | "Oblique"
---@alias FreeTypeLoadTarget "Normal" | "Light" | "Mono" | "HorizontalLcd" | "VerticalLcd"
---@alias FreeTypeLoadFlags "DEFAUlT" | "NO_HINTING" | "NO_BITMAP" | "FORCE_AUTOHINT" | "MONOCHROME" | "NO_AUTOHINT"
--TODO: = add harfbuzz_features enum
--
---@alias Fonts {fonts: FontAttributes[]}
---@class FontAttributes
---@field is_fallback? boolean
---@field is_synthetic? boolean
---@field harfbuzz_features? string[]
---@field assume_emoji_presentation? boolean
---@field scale? number
local FontAttributes = {
-- The font family name
family = 'JetBrains Mono',
---@type FontWeight
-- Whether the font should be a bold variant
weight = 'Regular',
---@type FontStretch
stretch = 'Normal',
---@type FontStyle
-- Whether the font should be an italic variant
style = 'Normal',
---@type FreeTypeLoadTarget
freetype_load_target = 'Normal',
---@type FreeTypeLoadTarget
freetype_render_target = 'Normal',
---@type FreeTypeLoadFlags
-- you can combine the flags like 'NO_HINTING|MONOCHROME' -- probably would not want to
freetype_load_flags = 'DEFAUlT',
}
---@class WindowFrameConfig
---@field inactive_titlebar_bg RgbColor
---@field active_titlebar_bg RgbColor
---@field inactive_titlebar_fg RgbColor
---@field active_titlebar_fg RgbColor
---@field inactive_titlebar_border_bottom RgbColor
---@field active_titlebar_border_bottom RgbColor
---@field button_fg RgbColor
---@field button_bg RgbColor
---@field button_hover_fg RgbColor
---@field button_hover_bg RgbColor
---@field border_left_width Dimension
---@field border_right_width Dimension
---@field border_top_height Dimension
---@field border_bottom_height Dimension
---@field border_left_color RgbaColor
---@field border_right_color RgbaColor
---@field border_top_color RgbaColor
---@field border_bottom_color RgbaColor
---@class TabBarStyle
---@field new_tab String
---@field new_tab_hover String
---@field window_hide String
---@field window_hide_hover String
---@field window_maximize String
---@field window_maximize_hover String
---@field window_close String
---@field window_close_hover String
---@class HyperlinkRule
---@field regex Regex
---@field format String
---@field highlight usize
---@class SerialDomain
---@field name String
-- The name of this specific domain. Must be unique amongst
-- all types of domain in the configuration file.
---@field port String
-- Specifies the serial device name.
-- On Windows systems this can be a name like `COM0`.
-- On posix systems this will be something like `/dev/ttyUSB0`.
-- If omitted, the name will be interpreted as the port.
---@field baud usize
-- Set the baud rate. The default is 9600 baud.
---@class GpuInfo
---@field name String
---@field device_type String
---@field backend String
---@field driver String
---@field driver_info String
---@field vendor u32
---@field device u32
---@class UnixDomain
---@field name String
-- The name of this specific domain. Must be unique amongst
-- all types of domain in the configuration file.
---@field socket_path PathBuf
-- The path to the socket. If unspecified, a resonable default
-- value will be computed.
---@field connect_automatically bool
-- If true, connect to this domain automatically at startup
---@field no_serve_automatically bool
-- If true, do not attempt to start this server if we try and fail to
-- connect to it.
---@field serve_command String[]
-- If we decide that we need to start the server, the command to run
-- to set that up. The default is to spawn:
-- `wezterm-mux-server --daemonize`
-- but it can be useful to set this to eg:
-- `wsl -e wezterm-mux-server --daemonize` to start up
-- a unix domain inside a wsl container.
---@field proxy_command String[]
-- Instead of directly connecting to `socket_path`
-- spawn this command and use its stdin/stdout in place of
-- the socket.
---@field skip_permissions_check bool
-- If true, bypass checking for secure ownership of the socket_path. This is not recommended on a multi-user system, but is useful for example when running the server inside a WSL container but with the socket on the host NTFS volume.
---@field read_timeout Duration
---@field write_timeout Duration
---@field local_echo_threshold_ms u64
-- Don't use default_local_echo_threshold_ms() here to disable the predictive echo for Unix domains by default.
---@field overlay_lag_indicator bool
-- Show time since last response when waiting for a response. It is recommended to use <https://wezfurlong.org/wezterm/config/lua/pane/get_metadata.html#since_last_response_ms> instead.
---@class LeaderKey :KeyNoAction
---@field timeout_milliseconds? u64 - `leader` stays active until a keypress is registered (whether it matches a key binding or not), or until it has been active for the duration specified by `timeout_milliseconds`, at which point it will automatically cancel itself.
---@class HyperLinkRule
---@field regex string The regular expression to match
---@field format string Controls which parts of the regex match will be used to form the link. Must have a prefix: signaling the protocol type (e.g., https:/mailto:), which can either come from the regex match or needs to be explicitly added. The format string can use placeholders like $0, $1, $2 etc. that will be replaced with that numbered capture group. So, $0 will take the entire region of text matched by the whole regex, while $1 matches out the first capture group. In the example below, mailto:$0 is used to prefix a protocol to the text to make it into an URL.
---@field highlight number? Specifies the range of the matched text that should be highlighted/underlined when the mouse hovers over the link. The value is a number that corresponds to a capture group in the regex. The default is 0, highlighting the entire region of text matched by the regex. 1 would be the first capture group, and so on.
---@class BatteryInfo
---@field state_of_charge number The battery level expressed as a number between 0.0 (empty) and 1.0 (full)
---@field vendor string Battery manufacturer name, or "unknown" if not known.
---@field model string The battery model string, or "unknown" if not known.
---@field serial string The battery serial number, or "unknown" if not known.
---@field time_to_full number? If charging, how long until the battery is full (in seconds). May be nil.
---@field time_to_empty number? If discharing, how long until the battery is empty (in seconds). May be nil.
---@field state "Charging" | "Discharging" | "Empty" | "Full" | "Unknown"
---@class PluginResponse
---@field apply_to_config fun(config: Config, ...: any): any Function that accepts at least a config builder parameter, but may pass other parameters, or a lua table with a `config` field that maps to a config build parameter.
---@class WeztermPlugin
---@field require fun(url: string): PluginResponse Takes a plugin repo URL (string). This plugin has to return a `apply_to_config` function that accepts at least a config builder parameter
---@field list fun(): Plugin[] -- 'list' function: returns an array of Plugin objects
---@field update_all fun(): nil -- 'update_all' function: performs updates, returns nothing
---@class Plugin -- Represents the RepoSpec struct in Lua
---@field url string -- The URL of the plugin repository
---@field component string -- The component or directory name of the plugin
---@field plugin_dir string -- The path to the plugin's directory
---@class AugmentCommandPaletteReturn
---@field brief string The brief description for the entry
---@field doc string? A long description that may be shown after the entry, or that may be used in future versions of wezterm to provide more information about the command.
---@field action KeyAssignment The action to take when the item is activated. Can be any key assignment action.
---@field icon NerdFont? optional Nerd Fonts glyph name to use for the icon for the entry. See wezterm.nerdfonts for a list of icon names.
---@alias CallbackWindowPane fun(window: Window, pane: Pane)
---@alias EventAugmentCommandPalette fun(event: "augment-command-palette", callback: fun(window: Window, pane: Window): AugmentCommandPaletteReturn): nil This event is emitted when the Command Palette is shown. It's purpose is to enable you to add additional entries to the list of commands shown in the palette. This hook is synchronous; calling asynchronous functions will not succeed.
---@alias EventBell fun(event: "augment-command-palette", callback: CallbackWindowPane) The bell event is emitted when the ASCII BEL sequence is emitted to a pane in the window. Defining an event handler doesn't alter wezterm's handling of the bell; the event supplements it and allows you to take additional action over the configured behavior.
---@alias EventFormatTabTitle fun(event: "format-tab-title", callback: fun(tab: TabInformation, tabs: TabInformation[], panes: PaneInformation[], config: Config, hover: boolean, max_width: number): string | FormatItem) When the tab bar is computed, this event is called twice for each tab; on the first pass, `hover` will be `false` and `max_width` will be set to tab_max_width. WezTerm will then compute the tab widths that will fit in the tab bar, and then call the event again for the set of tabs, this time with appropriate `hover` and `max_width` values.
---@alias EventFormatWindowTitle fun(event: "format-window-title", callback: fun(window: Window, pane: Pane, tabs: MuxTabObj[], panes: Pane[], config: Config)) TODO
---@alias EventNewTabButtonClick fun(event: "new-tab-button-click", callback: fun(window: Window, pane: Pane, button: "Left" | "Middle" | "Right", default_action: KeyAssignment): nil) TODO
---@alias EventOpenUri fun(event: "open-uri", callback: fun(window: Window, pane: Pane, uri: string): nil) TODO
---@alias EventUpdateRightStatus fun(event: "update-right-status", callback: CallbackWindowPane) TODO
---@alias EventUpdateStatus fun(event: "update-status", callback: CallbackWindowPane) TODO
---@alias EventUserVarChanged fun(event: "user-var-changed", callback: fun(window: Window, pane: Pane, name: string, value: string): nil) TODO
---@alias EventWindowConfigReloaded fun(event: "window-config-reloaded", callback: CallbackWindowPane) TODO
---@alias EventWindowFocusChanged fun(event: "window-focus-changed", callback: CallbackWindowPane) TODO
---@alias EventWindowResized fun(event: "window-resized", callback: CallbackWindowPane) TODO
---@alias EventCustom fun(event: string, callback: fun(...: any): nil) A custom declared function
---@alias CursorShape "SteadyBlock" | "BlinkingBlock" | "SteadyUnderline" | "BlinkingUnderline" | "SteadyBar" | "BlinkingBar"
---@alias CursorVisibility "Visible" | "Hidden"
---@class StableCursorPosition
---@field x number The horizontal cell index.
---@field y number the vertical stable row index.
---@field shape CursorShape The CursorShape enum value.
---@field visibility CursorVisibility The CursorVisibility enum value.
---@class LinearGradientOrientation
---@field angle number
---@class RadialGradientOrientation
---@field radius? number
---@field cx? number
---@field cy? number
---@class Gradient
---@field colors string[]
---@field orientation? 'Horizontal' | 'Vertical' | { Linear: LinearGradientOrientation } | { Radial: RadialGradientOrientation }
---@field interpolation? 'Linear' | 'Basis' | 'CatmullRom'
---@field blend? 'Rgb' | 'LinearRgb' | 'Hsv' | 'Oklab'
---@field noise? number
---@field segment_size? number
---@field segment_smoothness? number
---@class HsbTransform
---@field hue number
---@field saturation number
---@field brightness number
---@class ColorSchemeMetaData
---@field name? string
---@field author? string
---@field origin_url? string
---@field wezterm_version? string
---@field aliases? string[]
---@alias ActionCallback fun(win: Window, pane: Pane, ...: any): (nil | false)
---@alias AnsiColor 'Black' | 'Maroon' | 'Green' | 'Olive' | 'Navy' | 'Purple' | 'Teal' | 'Silver' | 'Grey' | 'Red' | 'Lime' | 'Yellow' | 'Blue' | 'Fuchsia' | 'Aqua' | 'White'
---@alias Appearance 'Light' | 'Dark' | 'LightHighContrast' | 'DarkHighContrast'
---@alias Clipboard 'Clipboard' | 'PrimarySelection' | 'ClipboardAndPrimarySelection'
---@alias CopyMode 'AcceptPattern' | 'ClearPattern' | 'ClearSelectionMode' | 'Close' | 'CycleMatchType' | 'EditPattern' | 'MoveBackwardSemanticZone' | { MoveBackwardSemanticZoneOfType: SemanticZoneType } | 'MoveBackwardWord' | 'MoveDown' | 'MoveForwardSemanticZone' | { MoveForwardSemanticZoneOfType: SemanticZoneType } | 'MoveForwardWord' | 'MoveForwardWordEnd' | 'MoveLeft' | 'MoveRight' | 'MoveToEndOfLineContent' | 'MoveToScrollbackBottom' | 'MoveToScrollbackTop' | 'MoveToSelectionOtherEnd' | 'MoveToSelectionOtherEndHoriz' | 'MoveToStartOfLine' | 'MoveToStartOfLineContent' | 'MoveToStartOfNextLine' | 'MoveToViewportBottom' | 'MoveToViewportMiddle' | 'MoveToViewportTop' | 'MoveUp' | 'NextMatch' | 'NextMatchPage' | 'PriorMatch' | 'PriorMatchPage' | { SetSelectionMode: SelectionMode | 'SemanticZone' }
---@alias CursorStyle 'BlinkingBlock' | 'SteadyBlock' | 'BlinkingUnderline' | 'SteadyUnderline' | 'BlinkingBar' | 'SteadyBar'
---@alias Direction 'Left' | 'Right' | 'Up' | 'Down' | 'Next' | 'Prev'
---@alias FreetypeLoadTarget 'Normal' | 'Light' | 'Mono' | 'HorizontalLcd'
---@alias SelectionMode 'Cell' | 'Word' | 'Line' | 'Block'
---@alias SemanticZoneType 'Prompt' | 'Input' | 'Output'
---@alias Stretch 'UltraCondensed' | 'ExtraCondensed' | 'Condensed' | 'SemiCondensed' | 'Normal' | 'SemiExpanded' | 'Expanded' | 'ExtraExpanded' | 'UltraExpanded'
---@alias Style 'Normal' | 'Italic' | 'Oblique'
---@alias Weight 'Thin' | 'ExtraLight' | 'Light' | 'DemiLight' | 'Book' | 'Regular' | 'Medium' | 'DemiBold' | 'Bold' | 'ExtraBold' | 'Black' | 'ExtraBlack'
---@class ScreenInformation
---@field name string
---@field x number
---@field y number
---@field height number
---@field width number
---@field max_fps? number
---@class KeyBindingBase
---@field key string
---@field action Action
---@class KeyBinding: KeyBindingBase
---@field mods string
---@class MouseEventInfo
---@field streak number
---@field button 'Left' | 'Right' | 'Middle' | { WheelDown: number } | { WheelUp: number }
---@class MouseDownEvent
---@field Down MouseEventInfo
---@class MouseUpEvent
---@field Up MouseEventInfo
---@class MouseDragEvent
---@field Drag MouseEventInfo
---@alias MouseEvent MouseDownEvent | MouseUpEvent | MouseDragEvent
---@class MouseBindingBase
---@field event MouseEvent
---@field action Action
---@field mouse_reporting? boolean
---@field alt_screen? boolean | 'Any'
---@class MouseBinding: MouseBindingBase
---@field mods string

View file

@ -0,0 +1,23 @@
---@meta
---@class Color
---@field adjust_hue_fixed fun(self: Color, degrees: number): Color Adjust the hue angle by the specified number of degrees.
---@field adjust_hue_fixed_ryb fun(self: Color, degrees: number): Color Adjust the hue angle by the specified number of degrees.
---@field complement fun(self: Color): Color Returns the complement of the color. The complement is computed by converting to HSL, rotating by 180 degrees and converting back to RGBA.
---@field complement_ryb fun(self: Color): Color Returns the complement of the color using the RYB color model, which more closely matches how artists think of mixing colors.
---@field contrast_ratio fun(self: Color, other: Color): number Computes the contrast ratio between the two colors.
---@field darken fun(self: Color, amount: number): Color Scales the color towards the minimum lightness by the provided factor, which should be in the range 0.0 through 1.0.
---@field darken_fixed fun(self: Color, amount: number): Color Decrease the lightness by amount, a value ranging from 0.0 to 1.0.
---@field delta_e fun(self: Color, other: Color): number Computes the CIEDE2000 DeltaE value representing the difference between the two colors.
---@field desaturate fun(self: Color, amount: number): Color Scales the color towards the minimum saturation by the provided factor, which should be in the range 0.0 through 1.0.
---@field desaturate_fixed fun(self: Color, amount: number): Color Decrease the saturation by amount, a value ranging from 0.0 to 1.0.
---@field hsla fun(self: Color): { h: number, s: number, l: number, a: number } Converts the color to the HSL colorspace and returns those values + alpha.
---@field laba fun(self: Color): { l: number, a: number, b: number, a: number } Converts the color to the LAB colorspace and returns those values + alpha.
---@field lighten fun(self: Color, amount: number): Color Scales the color towards the maximum lightness by the provided factor, which should be in the range 0.0 through 1.0.
---@field lighten_fixed fun(self: Color, amount: number): Color Increase the lightness by amount, a value ranging from 0.0 to 1.0.
---@field linear_rgba fun(self: Color): { r: number, g: number, b: number, a: number } Returns a tuple of the colors converted to linear RGBA and expressed as floating point numbers in the range 0.0-1.0.
---@field saturate fun(self: Color, amount: number): Color Scales the color towards the maximum saturation by the provided factor, which should be in the range 0.0 through 1.0.
---@field saturate_fixed fun(self: Color, amount: number): Color Increase the saturation by amount, a value ranging from 0.0 to 1.0.
---@field square fun(self: Color): { a: Color, b: Color, c: Color } Returns the other three colors that form a square. The other colors are 90 degrees apart on the HSL color wheel.
---@field srgb_u8 fun(self: Color): { r: number, g: number, b: number, a: number } Returns a tuple of the internal SRGBA colors expressed as unsigned 8-bit integers in the range 0-255.
---@field triad fun(self: Color): { a: Color, b: Color } Returns the other two colors that form a triad. The other colors are at +/- 120 degrees in the HSL color wheel.

View file

@ -0,0 +1,12 @@
---@meta
--TODO: finish? fixup_function autocomplete not work when calling
-- think it is lua language server callback function param types issue
---@class ExecDomain
local ExecDomain = {}
---@param domain_name string
---@param fixup_function function(cmd: SpawnCommand): SpawnCommand
---@param label? string
ExecDomain.exec_domain = function(domain_name, fixup_function, label) end

View file

@ -0,0 +1,15 @@
---@meta
---@alias LocalProcessStatus 'Idle' | 'Run' | 'Sleep' | 'Stop' | 'Zombie' | 'Tracing' | 'Dead' | 'Wakekill' | 'Waking' | 'Parked' | 'LockBlocked' | 'Unknown'
---@class LocalProcessInfo
---@field pid number The process identifier
---@field ppid number The parent process identifier
---@field name string The COMM name of the process. May not bear any relation to the executable image name. May be changed at runtime by the process. Many systems truncate this field to 15-16 characters.
---@field executable PathBuf Path to the executable image
---@field argv string[] The argument vector. Some systems allow changing the argv block at runtime eg: setproctitle().
---@field cwd string The current working directory for the process, or an empty path if it was not accessible for some reason.
---@field status LocalProcessStatus -- The status of the process. Not all possible values are portably supported on all systems.
---@field start_time number A clock value in unspecified system dependent units that indicates the relative age of the process.
---@field console number The console handle associated with the process, if any.
---@field children table<u32, LocalProcessInfo> -- Child processes, keyed by pid

View file

@ -0,0 +1,11 @@
---@meta
---@class MuxDomainObj
---@field attach fun(self: MuxDomainObj): nil Attempts to attach the domain. Attaching a domain will attempt to import the windows, tabs and panes from the remote system into those of the local GUI. Unlike the AttachDomain key assignment, calling domain:attach() will not implicitly spawn a new pane into the domain if the domain contains no panes. This is to provide flexibility when used in the gui-startup event. If the domain is already attached, calling this method again has no effect.
---@field detach fun(self: MuxDomainObj): nil Attempts to detach the domain. Detaching a domain causes it to disconnect and remove its set of windows, tabs and panes from the local GUI. Detaching does not cause those panes to close; if or when you later attach to the domain, they'll still be there. Not every domain supports detaching, and will log an error to the error log/debug overlay.
---@field domain_id fun(self: MuxDomainObj): number Returns the domain id.
---@field has_any_panes fun(self: MuxDomainObj): boolean Returns true if the mux has any panes that belong to this domain. This can be useful when deciding whether to spawn additional panes after attaching to a domain.
---@field is_spawnable fun(self: MuxDomainObj): boolean Returns false if this domain will never be able to spawn a new pane/tab/window, true otherwise. Serial ports are represented by a serial domain that is not spawnable.
---@field label fun(self: MuxDomainObj): string Computes a label describing the name and state of the domain. The label can change depending on the state of the domain.
---@field name fun(self: MuxDomainObj): string Returns the name of the domain. Domain names are unique; no two domains can have the same name, and the name is fixed for the lifetime of the domain.
---@field state fun(self: MuxDomainObj): "Attached" | "Detached" Returns whether the domain is attached or not.

View file

@ -0,0 +1,16 @@
---@meta
---@class MuxTabObj
---@field activate fun(self: MuxTabObj): nil Activates (focuses) the tab.
---@field active_pane fun(self): Pane A convenience accessor for returning the active pane in the tab.
---@field get_pane_direction fun(self: MuxTabObj, direction: "Left" | "Right" | "Up" | "Down" | "Prev" | "Next"): MuxTabObj Returns pane adjacent to the active pane in tab in the direction direction.
---@field get_size fun(self: MuxTabObj): {rows: number, cols: number, pixel_width: number, pixel_height: number, dpi: number} Returns the overall size of the tab, taking into account all of the contained panes.
---@field get_title fun(self: MuxTabObj): string Returns the tab title as set by `tab:set_title()`.
---@field panes fun(self: MuxTabObj): Pane[] Returns an array table containing the set of Pane objects contained by this tab.
---@field panes_with_info fun(self: MuxTabObj): {index: number, is_active: boolean, is_zoomed: boolean, left: number, top: number, width: number, height: number, pixel_width: number, pixel_height: number, pane: Pane}[] Returns an array table containing an extended info entry for each of the panes contained by this tab.
---@field rotate_clockwise fun(self: MuxTabObj): nil Rotates the panes in the clockwise direction.
---@field rotate_counter_clockwise fun(self: MuxTabObj): nil Rotates the panes in the counter-clockwise direction.
---@field set_title fun(self: MuxTabObj, title: string): nil Sets the tab title to the provided string.
---@field set_zoomed fun(self: MuxTabObj, state: boolean): boolean Sets the zoomed state for the active pane within this tab. A zoomed pane takes up all available space in the tab, hiding all other panes while it is zoomed. Switching its zoom state off will restore the prior split arrangement. Setting the zoom state to true zooms the pane if it wasn't already zoomed. Setting the zoom state to false un-zooms the pane if it was zoomed. Returns the prior zoom state.
---@field tab_id fun(self: MuxTabObj): number Returns the tab id.
---@field window fun(self: MuxTabObj): MuxWindow Returns the MuxWindow object that contains this tab.

View file

@ -0,0 +1,14 @@
---@meta
---@class MuxWindow
---@field active_pane fun(self: MuxWindow): Pane A convenience accessor for returning the active pane in the active tab of the window.
---@field active_tab fun(self: MuxWindow): MuxTabObj A convenience accessor for returning the active tab within the window.
---@field get_title fun(self: MuxWindow): string Returns the window title as set by OSC 0, OSC 2 in a contained pane, or through `window:set_title()`.
---@field get_workspace fun(self: MuxWindow) string Returns the name of the workspace to which the window belongs.
---@field gui_window fun(self: MuxWindow): Window Attempts to resolve this mux window to its corresponding Gui Window. This may not succeed for a couple of reasons: If called by the multiplexer daemon, there is no gui, so this will never succeed, If the mux window is part of a workspace that is not the active workspace.
---@field set_title fun(self: MuxWindow): nil Sets the window title to the provided string. Note that applications may subsequently change the title via escape sequences.
---@field set_workspace fun(self: MuxWindow): nil Changes the name of the workspace to which the window belongs.
---@field spawn_tab fun(self: MuxWindow): { tab: MuxTabObj, pane: Pane, window: MuxWindow } Spawns a program into a new tab within this window, returning the MuxTab, Pane and MuxWindow objects associated with it. When no arguments are passed, the default program is spawned. TODO
---@field tabs fun(self: MuxWindow): MuxTabObj[] Returns an array table holding each of the MuxTab objects contained within this window.
---@field tabs_with_info fun(self: MuxWindow): { index: number, is_active: boolean, tab: MuxTabObj }[] Returns an array table holding an extended info entry for each of the tabs contained within this window.
---@field window_id fun(self: MuxWindow): number Returns the window multiplexer id.

View file

@ -0,0 +1,20 @@
---@meta
---@class PaneInformation
---@field pane_id number The pane idenfitier number.
---@field pane_index number The logical position of the pane within its containing layout.
---@field is_active boolean Is true if the pane is the active pane within its containing tab.
---@field is_zoomed boolean Is true if the pane is in the zoomed state.
---@field left number The cell x coordinate of the left edge of the pane.
---@field top number The cell y coordinate of the top edge of the pane.
---@field width number The width of the pane in cells.
---@field height number The height of the pane in cells.
---@field pixel_width number The width of the pane in pixels.
---@field pixel_height number The height of the pane in pixels.
---@field title string The title of the pane, per `pane:get_title()` at the time the pane information was captured.
---@field user_vars table<string, string> The user variables defined for the pane, per `pane:get_user_vars()` at the time the pane information was captured.
---@field foreground_process_name string The path to the executable image per `pane:get_foreground_process_name()`, or an empty string if unavailable.
---@field current_working_dir string The current working directory, per `pane:get_current_working_dir()`.
---@field has_unseen_output boolean Is true if the there has been output in the pane since the last time it was focused.
---@field domain_name string The name of the domain with which the pane is associated.
---@field tty_name string The tty name with the same constraints as described in `pane:get_tty_name()`.

View file

@ -0,0 +1,33 @@
---@meta
---@class Pane
---@field activate fun(self: Pane): nil Activates (focuses) the pane and its containing tab.
---@field get_current_working_dir fun(self: Pane): string | Url Returns the current working directory of the pane, if known. The current directory can be specified by an application sending OSC 7. On newer versions of wezterm, it returns a `Url` object.
---@field get_cursor_position fun(self: Pane): StableCursorPosition Returns a lua representation of the StableCursorPosition struct that identifies the cursor position, visibility and shape.
---@field get_dimensions fun(self: Pane): RenderableDimensions Returns a lua representation of the RenderableDimensions struct that identifies the dimensions and position of the viewport as well as the scrollback for the pane.
---@field get_domain_name fun(self: Pane): string Returns the name of the domain with which the pane is associated.
---@field get_foreground_process_info fun(self: Pane): LocalProcessInfo Returns a LocalProcessInfo object corresponding to the current foreground process that is running in the pane.
---@field get_foreground_process_name fun(self: Pane): string Returns the path to the executable image for the pane.
---@field get_lines_as_text fun(self: Pane, lines: number?): string Returns the textual representation (not including color or other attributes) of the physical lines of text in the viewport as a string. A physical line is a possibly-wrapped line that composes a row in the terminal display matrix. If you'd rather operate on logical lines, see pane:get_logical_lines_as_text. If the optional nlines argument is specified then it is used to determine how many lines of text should be retrieved. The default (if nlines is not specified) is to retrieve the number of lines in the viewport (the height of the pane). The lines have trailing space removed from each line. The lines will be joined together in the returned string separated by a \n character. Trailing blank lines are stripped, which may result in fewer lines being returned than you might expect if the pane only had a couple of lines of output.
---@field get_logical_lines_as_text fun(self: Pane, lines: number?): string Returns the textual representation (not including color or other attributes) of the logical lines of text in the viewport as a string. A logical line is an original input line prior to being wrapped into physical lines to composes rows in the terminal display matrix. WezTerm doesn't store logical lines, but can recompute them from metadata stored in physical lines. Excessively long logical lines are force-wrapped to constrain the cost of rewrapping on resize and selection operations. If you'd rather operate on physical lines, see pane:get_lines_as_text. If the optional nlines argument is specified then it is used to determine how many lines of text should be retrieved. The default (if nlines is not specified) is to retrieve the number of lines in the viewport (the height of the pane). The lines have trailing space removed from each line. The lines will be joined together in the returned string separated by a \n character. Trailing blank lines are stripped, which may result in fewer lines being returned than you might expect if the pane only had a couple of lines of output.
---@field get_metadata fun(self: Pane): PaneMetadata? Returns metadata about a pane. The return value depends on the instance of the underlying pane. If the pane doesn't support this method, nil will be returned. Otherwise, the value is a lua table with the metadata contained in table fields.
---@field get_semantic_zone_at fun(self: Pane): any TODO
---@field get_semantic_zones fun(self: Pane): any TODO
---@field get_text_from_region fun(self: Pane, start_x: number, start_y: number, end_x: number, end_y: number): string Returns the text from the specified region.
---@field get_text_from_semantic_zone fun(self: Pane): any TODO
---@field get_title fun(self: Pane): string Returns the title of the pane. This will typically be wezterm by default but can be modified by applications that send OSC 1 (Icon/Tab title changing) and/or OSC 2 (Window title changing) escape sequences. The value returned by this method is the same as that used to display the tab title if this pane were the only pane in the tab; if OSC 1 was used to set a non-empty string then that string will be returned. Otherwise the value for OSC 2 will be returned. Note that on Microsoft Windows the default behavior of the OS level PTY is to implicitly send OSC 2 sequences to the terminal as new programs attach to the console. If the title text is wezterm and the pane is a local pane, then wezterm will attempt to resolve the executable path of the foreground process that is associated with the pane and will use that instead of wezterm.
---@field get_tty_name fun(self: Pane): string? Returns the tty device name, or nil if the name is unavailable.
---@field get_user_vars fun(self: Pane): { [string]: string } Returns a table holding the user variables that have been assigned to this pane. User variables are set using an escape sequence defined by iterm2, but also recognized by wezterm; this example sets the foo user variable to the value bar:
---@field has_unseen_output fun(self: Pane): boolean Returns true if there has been output in the pane since the last time the time the pane was focused.
---@field inject_output fun(self: Pane, text: string): nil Sends text, which may include escape sequences, to the output side of the current pane. The text will be evaluated by the terminal emulator and can thus be used to inject/force the terminal to process escape sequences that adjust the current mode, as well as sending human readable output to the terminal. Note that if you move the cursor position as a result of using this method, you should expect the display to change and for text UI programs to get confused. Not all panes support this method; at the time of writing, this works for local panes but not for multiplexer panes.
---@field is_alt_screen_active fun(self: Pane): boolean Returns whether the alternate screen is active for the pane. The alternate screen is a secondary screen that is activated by certain escape codes. The alternate screen has no scrollback, which makes it ideal for a "full-screen" terminal program like vim or less to do whatever they want on the screen without fear of destroying the user's scrollback. Those programs emit escape codes to return to the normal screen when they exit.
---@field move_to_new_tab fun(self: Pane): { tab: MuxTabObj, window: MuxWindow } Creates a new tab in the window that contains pane, and moves pane into that tab. Returns the newly created MuxTab object, and the MuxWindow object that contains it.
---@field move_to_new_window fun(self: Pane, workspace: string?): { tab: MuxTabObj, window: MuxWindow } Creates a window and moves pane into that window. The WORKSPACE parameter is optional; if specified, it will be used as the name of the workspace that should be associated with the new window. Otherwise, the current active workspace will be used. Returns the newly created MuxTab object, and the newly created MuxWindow object.
---@field mux_pane fun(self: Pane): nil **DEPRECATED**
---@field pane_id fun(self: Pane): number Returns the id number for the pane. The Id is used to identify the pane within the internal multiplexer and can be used when making API calls via wezterm cli to indicate the subject of manipulation.
---@field paste fun(self: Pane, text: string): nil Sends the supplied text string to the input of the pane as if it were pasted from the clipboard, except that the clipboard is not involved. If the terminal attached to the pane is set to bracketed paste mode then the text will be sent as a bracketed paste. Otherwise the string will be streamed into the input in chunks of approximately 1KB each.
---@field send_paste fun(self: Pane, text: string): nil Sends text to the pane as though it was pasted. If bracketed paste mode is enabled then the text will be sent as a bracketed paste. Otherwise, it will be sent as-is.
---@field send_text fun(self: Pane, text: string): nil Sends text to the pane as-is.
---@field split fun(self: Pane): Pane TODO
---@field tab fun(self: Pane): MuxTabObj? the MuxTab that contains this pane. Note that this method can return nil when pane is a GUI-managed overlay pane (such as the debug overlay), because those panes are not managed by the mux layer.
---@field window fun(self: Pane): MuxWindow Returns the MuxWindow that contains the tab that contains this pane.

View file

@ -0,0 +1,7 @@
---@meta
--TODO: finish
---@class SpawnCommand
local SpawnCommand = {}
SpawnCommand.foo = "bar"

View file

@ -0,0 +1,10 @@
---@meta
--
---@class SSHDomainObj
---@field name string The name of this specific domain. Must be unique amongst all types of domain in the configuration file.
---@field remote_address string Identifies the host:port pair of the remote server. Can be a DNS name or an IP address with an optional ":port" on the end.
---@field no_agent_auth boolean Whether agent auth should be disabled. Set to true to disable it.
---@field username string The username to use for authenticating with the remote host.
---@field connect_automatically boolean If true, connect to this domain automatically at startup
---@field timeout number Specify an alternative read timeout
---@field remote_wezterm_path string The path to the wezterm binary on the remote host. Primarily useful if it isn't installed in the $PATH that is configure for ssh.

View file

@ -0,0 +1,10 @@
---@meta
---@class TabInformation
---@field tab_id number The identifier for the tab
---@field tab_index number The logical tab position within its containing window, with 0 indicating the leftmost tab
---@field is_active boolean Is true if this tab is the active tab
---@field active_pane PaneInformation The PaneInformation for the active pane in this tab
---@field window_id number The ID of the window that contains this tab
---@field window_title string The title of the window that contains this tab
---@field tab_title string The title of the tab

View file

@ -0,0 +1,4 @@
---@class TimeObj
---@field format fun(self: TimeObj, format: string): string Formats the time object as a string, using the local date/time representation of the time.
---@field format_utc fun(self: TimeObj, format: string): string Formats the time object as a string, using the UTC date/time representation of the time.
---@field sun_times fun(self: TimeObj, lat: number, lon: number): { rise: TimeObj, set: TimeObj, progression: number, up: boolean } For the date component of the time object, compute the times of the sun rise and sun set for the given latitude and longitude.

View file

@ -0,0 +1,45 @@
---@class TlsDomainClient
---@field name String
-- The name of this specific domain. Must be unique amongst
-- all types of domain in the configuration file.
---@field bootstrap_via_ssh String
-- If set, use ssh to connect, start the server, and obtain
-- a certificate.
-- The value is "user@host:port", just like "wezterm ssh" accepts.
---@field remote_address String
-- identifies the host:port pair of the remote server.
---@field pem_private_key PathBuf
-- the path to an x509 PEM encoded private key file
---@field pem_cert PathBuf
-- the path to an x509 PEM encoded certificate file
---@field pem_ca PathBuf
-- the path to an x509 PEM encoded CA chain file
---@field pem_root_certs PathBuf[]
-- A set of paths to load additional CA certificates.
-- Each entry can be either the path to a directory or to a PEM encoded
-- CA file. If an entry is a directory, then its contents will be
-- loaded as CA certs and added to the trust store.
---@field accept_invalid_hostnames bool
-- explicitly control whether the client checks that the certificate
-- presented by the server matches the hostname portion of
-- `remote_address`. The default is true. This option is made
-- available for troubleshooting purposes and should not be used outside
-- of a controlled environment as it weakens the security of the TLS
-- channel.
---@field expected_cn String
-- the hostname string that we expect to match against the common name
-- field in the certificate presented by the server. This defaults to
-- the hostname portion of the `remote_address` configuration and you
-- should not normally need to override this value.
---@field connect_automatically bool
-- If true, connect to this domain automatically at startup
---@field read_timeout Duration
---@field write_timeout Duration
---@field local_echo_threshold_ms u64
-- The path to the wezterm binary on the remote host
---@field remote_wezterm_path String
-- Show time since last response when waiting for a response.
-- It is recommended to use
-- <https://wezfurlong.org/wezterm/config/lua/pane/get_metadata.html#since_last_response_ms>
-- instead.
---@field overlay_lag_indicator bool

View file

@ -0,0 +1,16 @@
---@class TlsDomainServer
---@field bind_address String
-- The address:port combination on which the server will listen
-- for client connections
---@field pem_private_key PathBuf
-- the path to an x509 PEM encoded private key file
---@field pem_cert PathBuf
-- the path to an x509 PEM encoded certificate file
---@field pem_ca PathBuf
-- the path to an x509 PEM encoded CA chain file
---@field pem_root_certs PathBuf[]
-- A set of paths to load additional CA certificates.
-- Each entry can be either the path to a directory
-- or to a PEM encoded CA file. If an entry is a directory
-- then its contents will be loaded as CA certs and added
-- to the trust store.

View file

@ -0,0 +1,11 @@
---@meta
---@class Url
---@field scheme string The URL scheme such as "file", or "https"
---@field file_path string Decodes the path field and interprets it as a file path
---@field username string The username portion of the URL, or an empty string if none is specified
---@field password string The password portion of the URL, or nil if none is specified
---@field host string The hostname portion of the URL, with IDNA decoded to UTF-8
---@field path string The path portion of the URL, complete with percent encoding
---@field fragment string The fragment portion of the URL
---@field query string The query portion of the URL

View file

@ -0,0 +1,32 @@
---@meta
---@class Window
---@field active_key_table fun(self: Window): string Returns a string holding the top of the current key table activation stack, or nil if the stack is empty. See [Key Tables](https://wezfurlong.org/wezterm/config/key-tables.html) for a detailed example.
---@field active_pane fun(self: Window): Pane A convenience accessor for returning the active pane in the active tab of the GUI window. This is similar to [mux_window:active_pane()](https://wezfurlong.org/wezterm/config/lua/window/active_pane.html) but, because it operates at the GUI layer, it can return *Pane* objects for special overlay panes that are not visible to the mux layer of the API.
---@field active_tab fun(self: Window): MuxTabObj A convenience accessor for returning the active tab within the window.
---@field active_workspace fun(self: Window): string Returns the name of the active workspace. This example demonstrates using the launcher menu to select and create workspaces, and how the workspace can be shown in the right status area.
---@field composition_status fun(self: Window): string? Returns a string holding the current dead key or IME composition text, or nil if the input layer is not in a composition state. This is the same text that is shown at the cursor position when composing.
---@field copy_to_clipboard fun(self: Window, text: string, target: CopyToTarget?): nil Puts text into the specified clipboard.
---@field current_event fun(self: Window): string Returns the current event. For now only implemented for mouse events. #TODO: type annotate the Event
---@field effective_config fun(self: Window): Config Returns a lua table representing the effective configuration for the Window. The table is in the same format as that used to specify the config in the wezterm.lua file, but represents the fully-populated state of the configuration, including any CLI or per-window configuration overrides. Note: changing the config table will NOT change the effective window config; it is just a copy of that information.
---@field focus fun(self: Window): nil Attempts to focus and activate the window.
---@field get_appearance fun(self: Window): "Light" | "Dark" | "LightHighContrast" | "DarkHighContrast" Returns the appearance of the window environment.
---@field get_config_overrides fun(self: Window): Config Returns a copy of the current set of configuration overrides that is in effect for the window. See `set_config_overrides` for examples!
---@field get_dimensions fun(self: Window): { pixel_width: number, pixel_height: number, dpi: number, is_full_screen: boolean } Returns a Lua table representing the dimensions for the Window.
---@field get_selection_escapes_for_pane fun(self: Window): string Returns the text that is currently selected within the specified pane within the specified window formatted with the escape sequences necessary to reproduce the same colors and styling. This is the same text that `window:get_selection_text_for_pane()` would return, except that it includes escape sequences.
---@field get_selection_text_for_pane fun(self: Window): string Returns the text that is currently selected within the specified pane within the specified window. This is the same text that would be copied to the clipboard if the CopyTo action were to be performed. Why isn't this simply a method of the `pane` object? The reason is that the selection is an attribute of the containing window, and a given pane can potentially be mapped into multiple windows.
---@field is_focused fun(self: Window): boolean Returns true if the window has focus. The update-status event is fired when the focus state changes.
---@field keyboard_modifiers fun(self: Window): { mods: string, leds: string } Returns two values; the keyboard modifiers and the key status leds. Both values are exposed to lua as strings with |-delimited values representing the various modifier keys and keyboard led states: Modifiers - is the same form as keyboard assignment modifiers Leds - possible flags are "CAPS_LOCK" and "NUM_LOCK". Note that macOS doesn't have a num lock concept.
---@field leader_is_active fun(self: Window): boolean Returns true if the Leader Key is active in the window, or false otherwise.
---@field maximize fun(self: Window): nil Puts the window into the maximized state. Use `window:restore()` to return to the normal/non-maximized state.
---@field mux_window fun(self: Window): MuxWindow Returns the MuxWindow representation of this window.
---@field perform_action fun(self: Window, key_assignment: KeyAssignment, pane: Pane): nil Performs a key assignment against the window and pane. There are a number of actions that can be performed against a pane in a window when configured via the keys and mouse configuration options. This method allows your lua script to trigger those actions for itself.
---@field restore fun(self: Window): nil Restores the window from the maximized state. See also: `window:maximize()`.
---@field set_config_overrides fun(self: Window, overrides: Config): nil Changes the set of configuration overrides for the window. The config file is re-evaluated and any CLI overrides are applied, followed by the keys and values from the overrides parameter. This can be used to override configuration on a per-window basis; this is only useful for options that apply to the GUI window, such as rendering the GUI. Each call to `window:set_config_overrides` will emit the `window-config-reloaded` event for the window. If you are calling this method from inside the handler for `window-config-reloaded` you should take care to only call `window:set_config_overrides` if the actual override values have changed to avoid a loop.
---@field set_inner_size fun(self: Window, width: number, height: number): nil Resizes the inner portion of the window (excluding any window decorations) to the specified width and height.
---@field set_left_status fun(self: Window, string: string): nil This method can be used to change the content that is displayed in the tab bar, to the left of the tabs. The content is displayed left-aligned and will take as much space as needed to display the content that you set; it will not be implicitly clipped. The parameter is a string that can contain escape sequences that change presentation. It is recommended that you use wezterm.format to compose the string.
---@field set_position fun(self: Window, x: number, y: number): nil Repositions the top-left corner of the window to the specified x, y coordinates. Note that Wayland does not allow applications to directly control their window placement, so this method has no effect on Wayland.
---@field set_right_status fun(self: Window, string: string): nil This method can be used to change the content that is displayed in the tab bar, to the right of the tabs and new tab button. The content is displayed right-aligned and will be clipped from the left edge to fit in the available space. The parameter is a string that can contain escape sequences that change presentation. It is recommended that you use wezterm.format to compose the string.
---@field toast_notification fun(self: Window, title: string, message: string, url: string?, timeout_milliseconds: number): nil Generates a desktop "toast notification" with the specified title and message. An optional url parameter can be provided; clicking on the notification will open that URL. An optional timeout parameter can be provided; if so, it specifies how long the notification will remain prominently displayed in milliseconds. To specify a timeout without specifying a url, set the url parameter to nil. The timeout you specify may not be respected by the system, particularly in X11/Wayland environments, and Windows will always use a fixed, unspecified, duration. The notification will persist on screen until dismissed or clicked, or until its timeout duration elapses.
---@field toggle_fullscreen fun(self: Window): nil Toggles full screen mode for the window.
---@field window_id fun(self: Window): number Returns the id number for the window. The Id is used to identify the window within the internal multiplexer and can be used when making API calls via wezterm cli to indicate the subject of manipulation.

View file

@ -0,0 +1,8 @@
---@meta
---@class WslDomain
---@field name String
---@field distribution String
---@field username String
---@field default_cwd PathBuf
---@field default_prog String[]

View file

@ -0,0 +1,51 @@
---@meta
--TODO: finish
---@class ColorMod
---@field parse fun(color: string): Color?
local color = {}
---@param filename string
---@param params? { fuzziness: number, num_colors: number, max_width: number, max_height: number, min_brightness: number, max_brightness: number, threshold: number, min_contrast: number }
function color.extract_colors_from_image(filename, params) end
---@param h string | number
---@param s string | number
---@param l string | number
---@param a string | number
---@return ColorMod
function color.from_hsla(h, s, l, a) end
---@return table<string, Palette>
function color.get_builtin_schemes() end
---@return Palette
function color.get_default_colors() end
---@param gradient Gradient
---@param num_colors number
---@return Color[]
function color.gradient(gradient, num_colors) end
---@param file_name string
---@return Palette, ColorSchemeMetaData
function color.load_base16_scheme(file_name) end
---@param file_name string
---@return Palette, ColorSchemeMetaData
function color.load_scheme(file_name) end
---@param file_name string
---@return Palette, ColorSchemeMetaData
function color.load_terminal_sexy_scheme(file_name) end
---@param string string
---@return Color
-- Parses the passed color and returns a Color object. Color objects evaluate as strings but have a number of methods that allow transforming and comparing colors.
function color.parse(string) end
---@param colors Palette
---@param metadata ColorSchemeMetaData
---@param file_name string
function color.save_scheme(colors, metadata, file_name) end

View file

@ -0,0 +1,12 @@
---@meta
--TODO: finish
---@class GuiMod
---@field default_key_tables any
---@field default_keys any
---@field enumerate_gpus any
---@field get_appearance any
---@field gui_window_for_mux_window any
---@field gui_windows any
---@field screens any

View file

@ -0,0 +1,77 @@
---@meta
--TODO: specify "any" types where possible
---@alias PathBuf string
---@class Wezterm :ExecDomain
---@field GLOBAL table<string, ANY>
---@field action Action
---@field add_to_config_reload_watch_list fun(path: string): nil Adds path to the list of files that are watched for config changes. If `automatically_reload_config` is enabled, then the config will be reloaded when any of the files that have been added to the watch list have changed.
---@field background_child_process fun(args: string[]): nil Accepts an argument list; it will attempt to spawn that command in the background.
---@field battery_info fun(): BatteryInfo[] Returns battery information for each of the installed batteries on the system. This is useful for example to assemble status information for the status bar.
---@field column_width fun(string): number Given a string parameter, returns the number of columns that that text occupies in the terminal, which is useful together with format-tab-title and update-right-status to compute/layout tabs and status information.
---@field config_builder fun(): Config Returns a config builder object that can be used to define your configuration.
---@field config_dir string This constant is set to the path to the directory in which your wezterm.lua configuration file was found.
---@field config_file string This constant is set to the path to the wezterm.lua that is in use.
---@field color ColorMod The `wezterm.color` module exposes functions that work with colors.
---@field default_hyperlink_rules fun(): HyperLinkRule[] Returns the compiled-in default values for hyperlink_rules.
---@field default_ssh_domains fun(): SSHDomainObj[] Computes a list of SshDomain objects based on the set of hosts discovered in your ~/.ssh/config. Each host will have both a plain SSH and a multiplexing SSH domain generated and returned in the list of domains. The former don't require wezterm to be installed on the remote host, while the latter do require it. The intended purpose of this function is to allow you the opportunity to edit/adjust the returned information before assigning it to your config.
---@field default_wsl_domains fun(): { name: string, distribution: string }[] Computes a list of WslDomain objects, each one representing an installed WSL distribution on your system. This list is the same as the default value for the wsl_domains configuration option, which is to make a WslDomain with the distribution field set to the name of WSL distro and the name field set to name of the distro but with "WSL:" prefixed to it.
---@field emit fun(event: string, ...)
---@field enumerate_ssh_hosts fun(ssh_config_file_name: string?): { [string] : { hostname: string, identityagent: string, identityfile: string, port: string, user: string, userknownhostsfile: string } } This function will parse your ssh configuration file(s) and extract from them the set of literal (non-pattern, non-negated) host names that are specified in Host and Match stanzas contained in those configuration files and return a mapping from the hostname to the effective ssh config options for that host. You may optionally pass a list of ssh configuration files that should be read, in case you have a special configuration.
---@field executable_dir string This constant is set to the directory containing the wezterm executable file.
---@field font (fun(font_attributes: FontAttributes): Fonts) | (fun(name: string, font_attributes?: FontAttributes?)): Fonts https://wezfurlong.org/wezterm/config/lua/wezterm/font.html
---@field font_with_fallback fun(fonts: string[] | FontAttributes[]): Fonts https://wezfurlong.org/wezterm/config/lua/wezterm/font_with_fallback.html
---@field format fun(...: FormatItem[]): string Can be used to produce a formatted string with terminal graphic attributes such as bold, italic and colors. The resultant string is rendered into a string with wezterm compatible escape sequences embedded.
---@field get_builtin_color_schemes any #TODO
---@field glob fun(pattern: string, relative_to: string?): string[] This function evalutes the glob pattern and returns an array containing the absolute file names of the matching results. Due to limitations in the lua bindings, all of the paths must be able to be represented as UTF-8 or this function will generate an error.
---@field gui GuiMod
---@field has_action fun(action: string): boolean
---@field mux MuxMod
---@field home_dir string This constant is set to the home directory of the user running wezterm.
---@field hostname fun(): string This function returns the current hostname of the system that is running wezterm. This can be useful to adjust configuration based on the host.
---@field json_encode fun(value: any): string Encodes the supplied lua value as json.
---@field json_parse fun(value: string): any Parses the supplied string as json and returns the equivalent lua values.
---@field log_error fun(msg: string, ...: any): nil Logs the provided message string through wezterm's logging layer at 'ERROR' level. If you started wezterm from a terminal that text will print to the stdout of that terminal. If running as a daemon for the multiplexer server then it will be logged to the daemon output path.
---@field log_info fun(msg: string, ...: any): nil Logs the provided message string through wezterm's logging layer at 'INFO' level. If you started wezterm from a terminal that text will print to the stdout of that terminal. If running as a daemon for the multiplexer server then it will be logged to the daemon output path.
---@field log_warn fun(msg: string, ...: any): nil Logs the provided message string through wezterm's logging layer at 'WARN' level. If you started wezterm from a terminal that text will print to the stdout of that terminal. If running as a daemon for the multiplexer server then it will be logged to the daemon output path.
---@field nerdfonts NerdFont
---@field open_with fun(path_or_url: string, application: string?) This function opens the specified path_or_url with either the specified application or uses the default application if application was not passed in.
---@field on EventAugmentCommandPalette | EventBell | EventFormatTabTitle | EventFormatWindowTitle | EventNewTabButtonClick | EventOpenUri | EventUpdateRightStatus | EventUpdateStatus | EventUserVarChanged | EventWindowConfigReloaded | EventWindowFocusChanged | EventWindowResized | EventCustom
---@field pad_left fun(string: string, min_width: integer): string Returns a copy of string that is at least min_width columns (as measured by wezterm.column_width)
---@field pad_right fun(string: string, min_width: integer): string Returns a copy of string that is at least min_width columns (as measured by wezterm.column_width).
---@field permute_any_or_no_mods any #TODO
---@field plugin WeztermPlugin
---@field read_dir fun(path: string): string Returns an array containing the absolute file names of the directory specified. Due to limitations in the lua bindings, all of the paths must be able to be represented as UTF-8 or this function will generate an error.
---@field reload_configuration fun(): nil Immediately causes the configuration to be reloaded and re-applied.
---@field run_child_process fun(args: string[]): { success: boolean, stdout: string, stderr: string } Will attempt to spawn that command and will return a tuple consisting of the boolean success of the invocation, the stdout data and the stderr data.
---@field running_under_wsl fun(): boolean Returns a boolean indicating whether we believe that we are running in a Windows Services for Linux (WSL) container.
---@field shell_join_args fun(args: string[]): string Joins together its array arguments by applying posix style shell quoting on each argument and then adding a space.
---@field shell_quote_arg fun(string: string): string Quotes its single argument using posix shell quoting rules.
---@field shell_split fun(line: string): string[] Splits a command line into an argument array according to posix shell rules.
---@field sleep_ms fun(milliseconds: number): nil wezterm.sleep_ms suspends execution of the script for the specified number of milliseconds. After that time period has elapsed, the script continues running at the next statement.
---@field split_by_newlines fun(string: string): string[] takes the input string and splits it by newlines (both \n and \r\n are recognized as newlines) and returns the result as an array of strings that have the newlines removed.
---@field strftime fun(format: string): string Formats the current local date/time into a string using the Rust chrono strftime syntax.
---@field strftime_utc fun(format: string): string Formats the current UTC date/time into a string using the Rust chrono strftime syntax.
---@field target_triple string This constant is set to the Rust target triple for the platform on which wezterm was built. This can be useful when you wish to conditionally adjust your configuration based on the platform.
---@field time TimeMod
---@field truncate_left fun(string: string, max_width: number): string Returns a copy of string that is no longer than max_width columns (as measured by wezterm.column_width). Truncation occurs by reemoving excess characters from the left end of the string.
---@field truncate_right fun(string: string, max_width: number): string Returns a copy of string that is no longer than max_width columns (as measured by wezterm.column_width). Truncation occurs by reemoving excess characters from the right end of the string.
---@field utf16_to_utf8 fun(string: string): string Overly specific and exists primarily to workaround this wsl.exe issue. It takes as input a string and attempts to convert it from utf16 to utf8.
---@field version string This constant is set to the wezterm version string that is also reported by running wezterm -V. This can potentially be used to adjust configuration according to the installed version.
Wezterm = {}
---@param table MouseBindingBase
---@return MouseBinding
---@overload fun(table: KeyBindingBase): KeyBinding
Wezterm.permute_any_mods = function(table) end
---@param gradient Gradient
---@param num_colors number
---@return Color[]
Wezterm.gradient_colors = function(gradient, num_colors) end
---@param callback ActionCallback
---@return Action
Wezterm.action_callback = function(callback) end

View file

@ -0,0 +1,15 @@
---@meta
---@class MuxMod
---@field all_domains fun(): MuxDomainObj[] Returns an array table holding all of the known MuxDomain objects.
---@field all_windows fun(): MuxWindow[] Returns an array table holding all of the known MuxWindow objects.
---@field get_active_workspace fun(): string Returns the name of the active workspace.
---@field get_domain fun(name_or_id: string | number): string Resolves name_or_id to a domain and returns a MuxDomain object representation of it. `name_or_id` can be: A domain name string to resolve the domain by name, A domain id to resolve the domain by id, nil or omitted to return the current default domain, other lua types will generate a lua error
---@field get_pane fun(id: number): Pane Given a pane ID, verifies that the ID is a valid pane known to the mux and returns a Pane object that can be used to operate on the pane. This is useful for situations where you have obtained a pane id from some other source and want to use the various `Pane` methods with it.
---@field get_tab fun(id: number): MuxTabObj Given a tab ID, verifies that the ID is a valid tab known to the mux and returns a MuxTab object that can be used to operate on the tab. This is useful for situations where you have obtained a tab id from some other source and want to use the various `MuxTab` methods with it.
---@field get_window fun(id: number): MuxWindow Given a window ID, verifies that the ID is a valid window known to the mux and returns a MuxWindow object that can be used to operate on the window. This is useful for situations where you have obtained a window id from some other source and want to use the various `MuxWindow` methods with it.
---@field get_workspace_names fun(): string[] Returns a table containing the names of the workspaces known to the mux.
---@field rename_workspace fun(old: string, new: string): nil Renames the workspace old to new.
---@field set_active_workspace fun(name: string): nil Sets the active workspace name. If the requested name doesn't correspond to an existing workspace, then an error is raised.
---@field set_default_domain fun(domain: MuxDomainObj): nil Assign a new default domain in the mux. The domain that you assign here will override any configured `default_domain` or the implicit assignment of the default domain that may have happened as a result of starting wezterm via `wezterm connect` or `wezterm serial`.
---@field spawn_window fun(...: any): {tab: MuxTabObj, pane: Pane, window: MuxWindow} Spawns a program into a new window, returning the MuxTab, Pane and MuxWindow objects associated with it. When no arguments are passed, the default program is spawned. TODO

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,9 @@
---@meta
--TODO: finish
---@class ProcInfoMod
---@field current_working_dir_for_pid any
---@field executable_path_for_pid any
---@field get_info_for_pid any
---@field pid any

View file

@ -0,0 +1,9 @@
---@meta
--TODO: finish
---@class TimeMod
---@field call_after fun(interval: number, function: function): nil Arranges to call your callback function after the specified number of seconds have elapsed.
---@field now fun(): TimeObj Returns a WezTermTimeObj object representing the time at which wezterm.time.now() was called.
---@field parse fun(string): TimeObj Parses a string that is formatted according to the supplied format string.
---@field parse_rfc3339 fun(string): TimeObj Parses a string that is formatted according to RFC 3339 and returns a Time object representing that time.

View file

@ -1,4 +1,5 @@
local wezterm = require("wezterm") local wezterm = require("wezterm") --[[@as Wezterm]]
local act = wezterm.action
local M = {} local M = {}
@ -11,8 +12,8 @@ M.merge_tables = function(a, b)
end end
end end
-- Only load color schemes once; store them for later use
M.get_schemes = function() M.get_schemes = function()
-- Only load color schemes once; store them for later use
local schemes = wezterm.GLOBAL.color_schemes local schemes = wezterm.GLOBAL.color_schemes
if schemes then if schemes then
return schemes return schemes
@ -21,4 +22,34 @@ M.get_schemes = function()
return wezterm.GLOBAL.color_schemes return wezterm.GLOBAL.color_schemes
end end
-- Mimicks the show_last_command_output command in Kitty
-- Spawns the pager in a new tab since Wezterm (for now) lacks overlays
-- This function is meant to be used as a keybinding callback
M.open_last_output_in_less = function(window, pane)
-- Grab the last nonempty "output" semantic zone
local zones = pane:get_semantic_zones("Output")
local last_output = ""
local idx = #zones
while true do
if idx == 0 then
break
end
last_output = pane:get_text_from_semantic_zone(zones[idx])
if last_output ~= "" then
break
end
idx = idx - 1
end
-- Ensure any quotes in output are properly escaped
-- This is because we need to use sh/echo as a hackaround for wezterm not supporting passing stdin to
-- commands spawned in a new tab/window
-- See this StackOverflow question/answer for why this particular substitution works: https://stackoverflow.com/a/1315213
last_output = last_output:gsub("'", "'\\''")
-- Spawn less in a new tab
local action = act.SpawnCommandInNewTab({ args = { "sh", "-c", "echo '" .. last_output .. "' | less -R" } })
window:perform_action(action, pane)
end
return M return M

48
.config/xplr/fzf.lua Executable file
View file

@ -0,0 +1,48 @@
-- Basic fzf search integration for xplr
-- Requires fzf (obviously), and bat for the preview
---@diagnostic disable
local xplr = xplr
---@diagnostic enable
local fzf = function()
-- xplr.util.shell_execute doesn't work here since fzf needs an actual tty
local p = io.popen("fzf --preview='bat --color=always {}'", "r")
local output = p:read("*a")
p:close()
local lines = {}
for line in output:gmatch("[^\r\n]+") do
table.insert(lines, line)
end
local count = #lines
if count == 0 then
return
else
local path = lines[1]
local msgs = { { FocusPath = path } }
local isdir = xplr.util.shell_execute("test", { "-d", path }).returncode == 0
if isdir then
table.insert(msgs, "Enter")
else
table.insert(msgs, "PrintFocusPathAndQuit")
end
return msgs
end
end
xplr.fn.custom.fzf = {}
xplr.fn.custom.fzf.search = function(_)
return fzf()
end
xplr.config.modes.builtin.default.key_bindings.on_key["f"] = {
help = "fzf search",
messages = {
"PopMode",
{ CallLua = "custom.fzf.search" }
}
}

View file

@ -1,4 +1,4 @@
version = "0.21.9" -- This needs to be global; ignore diagnostics that say otherwise version = "1.0.0" -- This needs to be global; ignore diagnostics that say otherwise
---@diagnostic disable ---@diagnostic disable
local xplr = xplr local xplr = xplr
@ -52,3 +52,6 @@ xplr.config.modes.builtin.default.key_bindings.on_key['*'] = {
}, },
}, },
} }
-- Fzf
require("fzf")

View file

@ -19,7 +19,7 @@ local function filetype(n)
local type = "other" local type = "other"
if n.is_file then if n.is_file then
local mime = mimetype(n) local mime = mimetype(n)
if (mime:match("text") or mime:match("json") or mime:match("csv") or mime:match("empty")) then if (mime:match("text") or mime:match("json") or mime:match("csv") or mime:match("empty") or mime:match("javascript")) then
type = "text" type = "text"
elseif (mime:match("zip") or mime:match("tar")) then elseif (mime:match("zip") or mime:match("tar")) then
type = "archive" type = "archive"
@ -49,6 +49,8 @@ local function render_text(n, ctx)
end end
local function render_image(n, ctx) local function render_image(n, ctx)
-- xplr doesn't support image protocols such as sixel or kitty
-- so we need to render blocks instead
local result = xplr.util.shell_execute("viu", local result = xplr.util.shell_execute("viu",
{ "--blocks", "--static", "--width", ctx.layout_size.width, n.absolute_path }) { "--blocks", "--static", "--width", ctx.layout_size.width, n.absolute_path })
return (result.returncode == 0 and result.stdout) or stats(n) return (result.returncode == 0 and result.stdout) or stats(n)

6
.vivaldi-mods/.luarc.json Executable file
View file

@ -0,0 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",
"Lua.diagnostics.globals": [
"hilbish"
]
}

6
.vivaldi-mods/after-update.lua Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env hilbish
-- Run this script after each Vivaldi update.
hilbish.run("./restore-backup.lua")
hilbish.run("./install-mods.lua")

112
.vivaldi-mods/css/dialog.css Executable file
View file

@ -0,0 +1,112 @@
/**
* Opens links in a dialog, either by key combinations, holding the middle mouse button or context menu
* Forum link: https://forum.vivaldi.net/topic/92501/open-in-dialog-mod?_=1717490394230
*/
@keyframes dialog-tab-animate-progress-bar {
0% {
left: -100%;
}
100% {
left: 100%;
}
}
.dialog-container {
z-index: 999;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, .4);
transition-property: background-color;
transition-duration: 0.1s;
transition-timing-function: ease;
transition-delay: 0s;
backdrop-filter: blur(2px);
border-radius: var(--radius);
display: flex;
justify-content: center;
align-items: center;
.dialog-tab {
position: relative;
display: flex;
flex-direction: column;
.options-container {
display: flex;
height: 35px;
text-align: center;
align-items: center;
justify-content: center;
gap: 0.5rem;
color: white;
z-index: 1160;
.options-button {
display: flex;
background: transparent;
border: unset;
cursor: pointer;
width: 35px;
height: 35px;
align-items: center;
justify-content: center;
&:hover {
background-color: var(--colorBgAlphaHeavy);
}
}
.dialog-input {
background: var(--colorAccentBgAlpha);
color: white;
border: unset;
width: 20%;
margin: 0 0.5rem;
padding: 0.25rem 0.5rem;
}
}
.progress-bar {
height: 5px;
max-width: calc(100% - var(--radius) * 1.5);
left: calc(var(--radius)* 0.75);
background-color: #0080ff;
border-radius: var(--radius);
transition: width 0.2s linear;
overflow: hidden;
position: relative;
&[style*="width: 100%"]:after {
content: "";
width: 50%;
height: 100%;
background-image: linear-gradient(
to right,
rgba(255, 255, 255, 0.5),
rgba(255, 255, 255, 0.8),
rgba(255, 255, 255, 0.5)
);
position: absolute;
top: 0;
left: -100%;
animation: dialog-tab-animate-progress-bar 1.5s linear infinite;
}
}
webview {
position: relative;
flex: 1;
overflow: hidden;
border-radius: var(--radius);
}
&:has(webview[src^="https://clearthis.page/"]) .reader-view-toggle {
background-color: var(--colorBgAlphaHeavy);
border-color: var(--colorBgDarker);
}
}
}

View file

@ -0,0 +1,33 @@
/*
* Vertical extensions drop-down menu
* Forum link: https://forum.vivaldi.net/topic/96266/vertical-extensions-drop-down-menu
*/
/* Vertical Extensions Drop-Down Menu */
.extensionIconPopupMenu {
--popupWidth: 280px !important;
}
.extensionIconPopupMenu > .toolbar {
max-height: 50vh;
overflow: hidden auto;
flex-direction: column;
flex-wrap: nowrap;
align-items: stretch;
}
.extensionIconPopupMenu .ExtensionDropdownIcon > button {
justify-content: flex-start;
padding: 8px 10px;
}
.extensionIconPopupMenu .ExtensionDropdownIcon > button::after {
content: attr(title);
overflow: hidden;
text-overflow: ellipsis;
}
.extensionIconPopupMenu .ExtensionDropdownIcon .button-badge {
top: auto;
right: 10px;
}

202
.vivaldi-mods/css/find-bar.css Executable file
View file

@ -0,0 +1,202 @@
/*
* Minimalist find bar
* Forum link: https://forum.vivaldi.net/topic/54938/minimalist-find-bar-css-mod
*/
:root {
--caribbean-green: #00cc99
}
/* Minimalist find bar */
.find-in-page {
position: fixed;
z-index: 3;
bottom: 0;
left: 118px;
right: 0;
justify-content: left;
max-width: 382px;
margin: auto;
background: transparent;
}
.find-in-page .fip-input-label {
display: none;
}
/* findbox */
.find-in-page:not(.fip-nomatches) .fip-input-container > * {
color: TURQUOISE;
font-weight: 500;
text-shadow: 0px 0px 4px black, 1px 1px 1px black;
}
.find-in-page:not(.fip-nomatches) .fip-input-container:is(:hover, :focus-within) > * {
color: var(--caribbean-green);
}
.find-in-page:not(.fip-nomatches) input[type="search"] {
box-shadow: 0 1px #ffd70099;
background: linear-gradient(55deg, rgba(0,0,0,.2), rgba(0,0,0,.05));
border-radius: var(--radius) var(--radius) 0 0;
border: none;
outline: none;
backdrop-filter: blur(2px);
}
.find-in-page:not(.fip-nomatches) input[type="search"]:focus-within {
box-shadow: 0 -1px var(--caribbean-green) inset, 0 1px #ffbe00;
}
.find-in-page:not(.fip-nomatches) .fip-input-container > input[type=search]::-webkit-search-cancel-button {
filter: sepia(100%) saturate(550%) brightness(104%) opacity(77%) drop-shadow(.7px .7px 1.4px #0008);
} /* yellow */
/.find-in-page:not(.fip-nomatches) .fip-input-container > input[type=search]::-webkit-search-cancel-button {
filter: sepia(98%) saturate(270%) hue-rotate(102deg) brightness(103%) contrast(106%) opacity(70%) drop-shadow(1px 0 1.5px #0009);
} /* optional: turquoise clear button */
/* nomatch alert */
.find-in-page.fip-nomatches .fip-input-container > input {
font-weight: 500;
color: maroon;
background-color: #ffbbffD9;
box-shadow: 0 0 4px pink inset, 0 0 0 .6px magenta inset;
border: none;
outline: none;
backdrop-filter: blur(2px);
transition-delay: .1s !important;
}
.find-in-page.fip-nomatches:not(:hover):not(:focus-within) .fip-input-container > input {
color: mediumviolet;
background: linear-gradient(55deg, #ffbbff80, #ffbbff33);
box-shadow: none;
transition-delay: .1s !important;
}
.find-in-page.fip-nomatches .fip-input-container > input[type=search]::-webkit-search-cancel-button {
filter: invert(45%) sepia(25%) saturate(5900%) hue-rotate(311deg) brightness(100%) contrast(65%) drop-shadow(.5px .5px .6px pink);
transition-delay: .1s !important;
}
.find-in-page.fip-nomatches:focus-within .fip-input-container > input {
animation: shake 1s steps(2) .15s 2 !important;
}
@keyframes shake {
9% {
transform: translateX(0);
}
1%, 5% {
transform: translateX(-4px);
}
3%, 7% {
transform: translateX(5px);
}
}
/* autohide buttons */
.find-in-page > :nth-last-child(-n+3) > * {
opacity: 0;
outline: none;
backdrop-filter: blur(2px);
transition: opacity .13s ease-out !important;
}
.find-in-page:is(:hover, :focus-within) > :nth-last-child(-n+3) > * {
opacity: 1;
}
/* arrow buttons */
.find-in-page > .toolbar-group button {
background: transparent !important;
border: none !important;
box-shadow: none !important;
filter: drop-shadow(.5px .5px maroon) drop-shadow(1px 1px 1px #000D);
}
.find-in-page > .toolbar-group button > span {
fill: TURQUOISE;
transform: rotate(90deg);
}
.find-in-page > .toolbar-group button:is(:hover, :focus-within) svg {
fill: var(--caribbean-green);
transform: scale(1.3);
}
/* close button */
.find-in-page button[title='Cancel search'] {
fill: TURQUOISE;
background: transparent !important;
border: none !important;
}
.find-in-page button[title='Cancel search']:not(:hover):not(:focus-within) > span {
filter: drop-shadow(.6px .6px maroon) drop-shadow(1px 1px 1px #000D);
}
.find-in-page button[title='Cancel search']:is(:hover, :focus-within) {
fill: red;
box-shadow: 0 0 0 1.7px red inset;
filter: drop-shadow(.5px .5px maroon) drop-shadow(.8px .8px .9px #000D);
transition: box-shadow .12s !important;
}
/.find-in-page > .toolbar-group {
display: flex;
order: 1;
} /* optional: reorder close button closer to findbox */
/* check-box */
.find-in-page label > input[type=checkbox] {
background: transparent !important;
border: none !important;
box-shadow: 0 0 0 1.7px TURQUOISE inset !important;
filter: drop-shadow(.5px .5px maroon) drop-shadow(.8px .8px 1px #000D);
}
.find-in-page label:is(:hover, :focus-within) > input[type=checkbox] {
box-shadow: 0 0 0 1.7px var(--caribbean-green) inset !important;
}
/* match text */
.find-in-page .fip-checkbox-label {
color: var(--caribbean-green);
font-size: 85%;
padding-right: 4px;
margin-left: -48px;
transform: translateX(50px);
background-color: transparent;
text-shadow: 0 0, 1px 1px 1px maroon, 1px 1px 2px #000D, 1px 1px 3px #000D, 1px 1px 4px #000D;
transition: .13s !important;
}
.find-in-page label:not(:hover) > input[type=checkbox]:not(:focus-visible) ~ .fip-checkbox-label {
font-size: 0;
}
.find-in-page:not(:hover):not(:focus-within) label > input[type=checkbox]:checked ~ .fip-checkbox-label {
opacity: 1;
font-size: 85% !important;
margin-left: -140px;
}
/* automate find box during small window */
@media only screen and (max-width: 600px) {
.find-in-page .fip-checkbox-label {
margin-left: 0;
transform: translateX(0);
}
.find-in-page:not(:hover):not(:focus-within) label > input[type=checkbox]:checked ~ .fip-checkbox-label {
margin-left: -95px;
}
}
/* enter & exit animation */
.find-in-page.find-in-page-enter {
transform: scaleX(0);
transition: transform 150ms ease-out, opacity 100ms ease-out !important;
}
.find-in-page.find-in-page-enter-active {
transform: scaleX(1);
}
.find-in-page.find-in-page-exit-active {
transform: scaleX(0);
transition: transform 150ms ease-in, opacity 150ms ease-in !important;
}

View file

@ -0,0 +1,48 @@
/*
* Autohide bookmark bar
* Forum link: https://forum.vivaldi.net/topic/95511/overlay-bookmark-bar
*/
#browser {
--bookmark-bar-hide-delay: 400ms;
--bookmark-bar-show-ctrlkey: false;
}
.bookmark-bar-top:is(.address-top, .tabs-top) {
#main:has(.bookmark-bar:hover) #webview-container {
pointer-events: none !important;
}
&.tabs-top #tabs-subcontainer {
-webkit-app-region: no-drag !important;
}
.bookmark-bar {
height: 0 !important;
border: none !important;
}
.bookmark-bar .observer {
position: absolute !important;
z-index: 4 !important;
width: 100% !important;
border-bottom: solid 1px var(--colorBorder) !important;
clip-path: inset(0 0 100% 0) !important;
transition-delay: var(--bookmark-bar-hide-delay) !important;
}
&:has(.button-disabled-preview):has(.tabbar-wrapper:hover).tabs-top .bookmark-bar .observer,
&:has(.button-disabled-preview).address-top .bookmark-bar:is(.mainbar:not(:has(.OmniDropdown, nav.menu)):hover ~ *) .observer,
.bookmark-bar:is(:focus-within, :hover) .observer {
clip-path: inset(0 0 -1px 0) !important;
transition: clip-path 150ms cubic-bezier(0, 1, 0, 0.9) 50ms !important;
}
@container not style(--bookmark-bar-show-ctrlkey: true) {
&:has(.tabbar-wrapper:hover).tabs-top .bookmark-bar .observer,
&.address-top .bookmark-bar:is(.mainbar:not(:has(.OmniDropdown, nav.menu)):hover ~ *) .observer,
.bookmark-bar:is(:focus-within, :hover) .observer {
clip-path: inset(0 0 -1px 0) !important;
transition: clip-path 150ms cubic-bezier(0, 1, 0, 0.9) 50ms !important;
}
}
&.animation-off .bookmark-bar .observer {
transition-duration: 0ms !important;
}
}

View file

@ -0,0 +1,29 @@
/*
* Autohide panels (while making it possible to use scrollbar still)
*/
:root {
--panel-transition: max-width .2s ease-out, opacity .2s ease-out;
--panel-peek-width: 12px;
--panel-peek-height: 12px;
}
/* Base hidden state for panels */
#panels-container {
position: absolute !important;
z-index: 1;
opacity: 0;
max-height: var(--panel-peek-height);
max-width: var(--panel-peek-width);
transition: var(--panel-transition) !important;
}
#panels-container.right {
right: 0;
}
/* Show panels on hover */
#panels-container:hover {
max-height: 100%;
max-width: 41px;
opacity: 1;
}

View file

@ -0,0 +1,124 @@
/*
* Autohide tab bar.
* Forum link: https://forum.vivaldi.net/topic/107399/auto-hide-vertical-tabs-arc-browser-style
*/
:root {
--tabbar-transition: transform .2s ease-out, opacity .2s ease-out;
--scrollbar-width: 10px;
--scrollbar-border-color: #9fb0cb;
--tabbar-peek-width: 3px;
}
/*----- Scrollbar Styling -----*/
#tabs-tabbar-container:is(.left, .right) .tab-strip::-webkit-scrollbar {
padding: 0 2px !important;
width: var(--scrollbar-width) !important;
border: 1px solid var(--scrollbar-border-color) !important;
border-radius: 8px !important;
}
#tabs-tabbar-container:is(.left, .right) .tab-strip::-webkit-scrollbar-button {
display: none !important;
}
#tabs-tabbar-container:is(.left, .right) .tab-strip::-webkit-scrollbar-thumb {
border: 2px solid transparent !important;
border-radius: 8px !important;
}
/*----- Vertical Tabbar Auto-Hide Behavior -----*/
/* Base hidden state for vertical tabbar */
#browser:is(.tabs-left, .tabs-right) .tabbar-wrapper {
position: absolute;
transform: translateX(calc(-100% + var(--tabbar-peek-width)));
transition: var(--tabbar-transition) !important;
opacity: 0;
z-index: 1;
}
/* Right side positioning */
#browser.tabs-right .tabbar-wrapper {
right: 0;
transform: translateX(calc(100% - var(--tabbar-peek-width)));
}
/* Tab move functionality support */
#browser.tabs-left.isblurred:where(:has(div.tab-yield-space, .tab-acceptsdrop)) .tabbar-wrapper,
#browser.tabs-left.isblurred:is(:active, :focus) .tabbar-wrapper:is(:active, :focus) {
transform: translateX(0);
opacity: 1;
}
/* Show tabbar on hover */
#browser:is(.tabs-left, .tabs-right) .tabbar-wrapper:hover {
transform: translateX(0);
transition: var(--tabbar-transition) !important;
opacity: 1;
}
/* Show when mouse approaches edge of screen */
#browser:is(.tabs-left) .mainbar:hover + .tabbar-wrapper,
#browser:is(.tabs-right) .webpage:hover + .tabbar-wrapper {
transform: translateX(0);
transition: var(--tabbar-transition) !important;
opacity: 1;
}
/* Show when workspace popups are active */
#browser:is(.tabs-left, .tabs-right):has(.WorkspacePopup:visible,
.workspace-popup:visible) .tabbar-wrapper {
transform: translateX(0);
transition: var(--tabbar-transition) !important;
opacity: 1;
}
/* Keep tab bar visible during workspace naming */
#browser:is(.tabs-left, .tabs-right):has(.quick-command-container.workspace-naming) .tabbar-wrapper,
#browser:is(.tabs-left, .tabs-right):has(.workspace-naming) .tabbar-wrapper,
#browser:is(.tabs-left, .tabs-right):has(.WorkspacePopup) .tabbar-wrapper,
#browser:is(.tabs-left, .tabs-right):has(input[placeholder*="workspace"]) .tabbar-wrapper {
transform: translateX(0) !important;
transition: none !important;
opacity: 1 !important;
}
/* Hide on click outside */
html:active:not(:has(.tabbar-wrapper:hover,
.quick-command-container.workspace-naming,
.workspace-naming,
input[placeholder="workspace"]:focus,
.WorkspacePopup:visible,
.workspace-popup:visible)) .tabbar-wrapper {
transform: translateX(calc(-100% + var(--tabbar-peek-width))) !important;
transition: var(--tabbar-transition) !important;
opacity: 0 !important;
}
/* Fix right side hiding behavior on click outside */
html:active:not(:has(.tabbar-wrapper:hover,
.quick-command-container.workspace-naming,
.workspace-naming,
input[placeholder="workspace"]:focus,
.WorkspacePopup:visible,
.workspace-popup:visible)) #browser.tabs-right .tabbar-wrapper {
transform: translateX(calc(100% - var(--tabbar-peek-width))) !important;
}
/* Additional reset mechanism for when tabs get stuck */
html:active:active .tabbar-wrapper:not(:hover):not(:has(.quick-command-container.workspace-naming,
.workspace-naming,
input[placeholder="workspace"]:focus)) {
transform: translateX(calc(-100% + var(--tabbar-peek-width))) !important;
opacity: 0 !important;
}
/* Additional reset for right side */
html:active:active #browser.tabs-right .tabbar-wrapper:not(:hover):not(:has(.quick-command-container.workspace-naming,
.workspace-naming,
input[placeholder="workspace"]:focus)) {
transform: translateX(calc(100% - var(--tabbar-peek-width))) !important;
opacity: 0 !important;
}

View file

@ -0,0 +1,7 @@
/*
* Remove new tab button on tab bar
*/
.newtab {
display: none;
}

View file

@ -0,0 +1,9 @@
/*
* Load indicator as underline
* Forum link: https://forum.vivaldi.net/post/452647
*/
.UrlBar-AddressField .pageload:not(.unstarted).progressing .pageload-indicator {
opacity: 1 !important;
background: linear-gradient(0deg, #00cc99 4px, transparent 0);
}

View file

@ -0,0 +1,43 @@
/*
* Make quick commands transparent during mouseout
* Forum link: https://forum.vivaldi.net/topic/50773/quick-commands-peekaboo-v2
*/
/* Compact QC */
#modal-bg.qc-modal.float.top:not(:hover) > div {
background: transparent;
box-shadow: none;
}
#modal-bg.qc-modal.float.top:not(:hover) .quick-command-container .quick-commands {
opacity: 0;
}
#modal-bg.qc-modal.float.top:not(:hover) .qc-entry input {
font-weight: 500;
color: #00cc99;
text-shadow: 2px 2px 6px black;
background: linear-gradient(45deg, #00000099, transparent 80%);
border-radius: 10px;
}
#modal-bg.qc-modal.float.top > div {
transition: background .4s !important;
}
.quick-command-container .quick-commands {
transition: opacity .4s !important;
}
/* expand width */
.quick-command-container, .quick-command-container .quick-commands > div {
min-width: 86vw;
cursor: auto;
}
.quick-command-container .quick-commands > div > div {
max-width: 100% !important;
}
.quick-command-container .quick-command {
cursor: pointer;
}

46
.vivaldi-mods/css/tab-stack.css Executable file
View file

@ -0,0 +1,46 @@
/*
* Automate 2 level tab stacks
* Forum link: https://forum.vivaldi.net/topic/83079/automate-2-level-tab-stack-columns-v3
*/
/* Automate 2 level vertical tabbar columns */
.substrip-tabs-on #tabs-tabbar-container:is(.left, .right) > div {
z-index: 1;
transition: background-color .15s, flex-basis .12s ease-out .05s !important;
}
/* active main column */
.substrip-tabs-on #tabs-tabbar-container:is(.left, .right) > #tabs-container:is(:focus-within, :hover):not(:has(.SlideBar--FullHeight:active)) + #tabs-subcontainer {
flex-basis: 30px !important;
z-index: 0;
}
/* active sub column */
.substrip-tabs-on #tabs-tabbar-container:is(.left, .right) > #tabs-subcontainer:is(:focus-within, :hover) {
flex-basis: calc(100% - 64px) !important;
z-index: 3;
}
/* active sub column with small width tabbar */
.substrip-tabs-on #tabs-tabbar-container:is(.left, .right):is(:focus-within, :hover):is([style^='width: 6'], [style^='width: 7'], [style^='width: 8'], [style^='width: 9']) > #tabs-subcontainer:is(:focus-within, :hover) {
flex-basis: calc(100% - 30px) !important;
z-index: 3;
}
/* inactive tabbar columns' ratio during small width (minimized sub column to favicon) */
.substrip-tabs-on #tabs-tabbar-container:is(.left, .right):not(:focus-within, :hover):is([style^='width: 6'], [style^='width: 7'], [style^='width: 8'], [style^='width: 9']) > #tabs-subcontainer:not(:focus-within, :hover) {flex-basis: 30px !important;}
/* fix small tab hover effect for title, stack counter, & close button */
#tabs-container .tab.tab-small.tab-mini .tab-header {justify-content: unset; padding-left: 5px;}
#tabs-container .tab.tab-small.tab-mini .tab-header .title {display: flex;}
#browser:not(.alt-tabs).substrip-tabs-on #tabs-tabbar-container:is(.left, .right) .tab-position .tab:hover.tab:not(.button-off, .force-hover, .tab-small) .stack-counter,
.substrip-tabs-on #tabs-tabbar-container:is(.left, .right) .tab-position .tab:not(.tab-mini) .stack-counter {display: block; margin-left: -6px;}
.substrip-tabs-on #tabs-tabbar-container:is(.left, .right) .tab-position :is(.tab:hover.tab-small, .tab.force-hover.tab-small) .close {display: flex; margin-left: -3px;}
/* autohide inactive columns' scrollbar */
#tabs-tabbar-container > div.overflow:not(:focus-within):not(:hover) .tab-strip {
overflow-y: hidden;
}
/* optional: hide tabbar columns' resizer */
.substrip-tabs-on #tabs-tabbar-container:is(.left, .right) > #tabs-container .SlideBar--FullHeight {visibility: hidden;}
/* option 2: Minimized main column to favicon + stack counter */
.substrip-tabs-on #tabs-tabbar-container:is(.left, .right):not(:focus-within, :hover):not([style^='width: 6']):not([style^='width: 7']):not([style^='width: 8']):not([style^='width: 9']) > #tabs-subcontainer.visible {flex-basis: calc(100% - 64px) !important;}

45
.vivaldi-mods/install-mods.lua Executable file
View file

@ -0,0 +1,45 @@
#!/usr/bin/env hilbish
-- Note: this script only supports 1 Vivaldi install.
local posix = require("posix")
local fs = require("fs")
local _, mod_dir = posix.pwd()
mod_dir = mod_dir:gsub("\n", "") .. "/js"
local custom_js = mod_dir .. "/custom.js"
local _, vivaldi_install = posix.find("/opt", { name = "vivaldi-bin" })
local _, dir = posix.dirname(vivaldi_install)
dir = dir:gsub("\n", "")
local resources_dir = dir .. "/resources/vivaldi"
print("Patch originating from " .. mod_dir .. " targeting " .. dir)
local backup_files = fs.glob(resources_dir .. "/window.html.bak")
if #backup_files == 0 then
print("Not patched; backing up window.html to window.html.bak...")
posix.cp(resources_dir .. "/window.html", resources_dir .. "/window.html.bak", { sudo = true })
print("Patching window.html...")
posix.sed('s/<\\/body>/<script src="custom.js"><\\/script> <\\/body>/', resources_dir .. "/window.html",
{ flags = "-i", sudo = true })
else
print("window.html has already been patched")
end
print("Combining js files into custom.js...")
local _, js_files = posix.find(mod_dir, { maxdepth = 1, type = "f", name = "*.js" })
posix.touch(custom_js)
for line in string.gmatch(js_files, "[^\r\n]*") do
if line == '' then
break
end
posix.cat(line, { append_file = custom_js })
end
print("Copying custom.js...")
posix.cp(custom_js, resources_dir .. "/custom.js", { sudo = true, force = true })
posix.rm(custom_js)

863
.vivaldi-mods/js/dialog.js Executable file
View file

@ -0,0 +1,863 @@
/**
* Opens links in a dialog, either by key combinations, holding the middle mouse button or context menu
* Forum link: https://forum.vivaldi.net/topic/92501/open-in-dialog-mod?_=1717490394230
*/
(() => {
const ICON_CONFIG = {
linkIcon: '', // if set, an icon shows up after links - example values 'fa-solid fa-up-right-from-square', 'fa-solid fa-circle-info', 'fa-regular fa-square' search for other icons: https://fontawesome.com/search?o=r&ic=free&s=solid&ip=classic
linkIconInteractionOnHover: true, // if false, you have to click the icon to show the dialog - if true, the dialog shows on mouseenter
showIconDelay: 250, // set to 0 to disable - delays showing the icon on hovering a link
showDialogOnHoverDelay: 250 // set to 0 to disable - delays showing the dialog on hovering the linkIcon
},
CONTEXT_MENU_CONFIG = {
menuPrefix: '[Dialog Tab]',
linkMenuTitle: 'Open link',
searchMenuTitle: 'Search by "%s"',
selectSearchMenuTitle: 'Search with'
};
// Wait for the browser to come to a ready state
setTimeout(function waitDialog() {
const browser = document.getElementById('browser');
if (!browser) {
return setTimeout(waitDialog, 300);
}
new DialogMod();
}, 300);
class DialogMod {
webviews = new Map();
iconUtils = new IconUtils();
searchEngineUtils = new SearchEngineUtils(
(url) => this.dialogTab(url),
(engineId, searchText) => this.dialogTabSearch(engineId, searchText),
CONTEXT_MENU_CONFIG
);
KEYBOARD_SHORTCUTS = {
'Ctrl+Alt+Period': this.searchForSelectedText.bind(this),
'Ctrl+Shift+F': this.searchForSelectedText.bind(this),
Esc: () => {
if (!this.webviews.size) return;
const webviewValues = Array.from(this.webviews.values());
let webviewData = webviewValues.at(-1);
if (!webviewData.fromPanel) {
const tabId = Number(document.querySelector('.active.visible.webpageview webview').tab_id);
webviewData = webviewValues.findLast(_data => _data.tabId === tabId);
}
webviewData && this.removeDialog(webviewData.webview.id);
}
};
constructor() {
// Setup keyboard shortcuts
vivaldi.tabsPrivate.onKeyboardShortcut.addListener(this.keyCombo.bind(this));
new WebsiteInjectionUtils(
(navigationDetails) => this.getWebviewConfig(navigationDetails),
(url, fromPanel) => this.dialogTab(url, fromPanel),
ICON_CONFIG
);
}
/**
* Finds the correct configuration for showing the dialog
*/
getWebviewConfig(navigationDetails) {
if (navigationDetails.frameType !== "outermost_frame") return {webview: null, fromPanel: false};
// first dialog from the tab
let webview = document.querySelector(`webview[tab_id="${navigationDetails.tabId}"]`);
if (webview) return {webview, fromPanel: false};
// first dialog from the webpanel
webview = document.querySelector(`.webpanel-content webview[src*="${navigationDetails.url}"]`);
if (webview) return {webview, fromPanel: true};
// follow-up dialog from the webpanel
webview = Array.from(this.webviews.values()).find(view => view.fromPanel)?.webview;
if (webview) return {webview, fromPanel: true};
// follow-up dialog from tab
const lastWebviewId = document.querySelector('.active.visible.webpageview .dialog-container:last-of-type webview')?.id;
return {webview: this.webviews.get(lastWebviewId)?.webview, fromPanel: false};
}
/**
* Open Default Search Engine in Dialog and search for the selected text
* @returns {Promise<void>}
*/
async searchForSelectedText() {
const tabs = await chrome.tabs.query({active: true});
vivaldi.utilities.getSelectedText(tabs[0].id, (text) => this.dialogTabSearch(this.searchEngineUtils.defaultSearchId, text));
};
/**
* Prepares url for search, calls dailogTab function
* @param {String} engineId engine id of the engine to be used
* @param {int} selectionText the text to search
*/
async dialogTabSearch(engineId, selectionText) {
let searchRequest = await vivaldi.searchEngines.getSearchRequest(engineId, selectionText);
this.dialogTab(searchRequest.url);
}
/**
* Handle a potential keyboard shortcut (copy from KeyboardMachine)
* @param {number} id I don't know what this does, but it's an extra argument
* @param {String} combination written in the form (CTRL+SHIFT+ALT+KEY)
*/
keyCombo(id, combination) {
const customShortcut = this.KEYBOARD_SHORTCUTS[combination];
if (customShortcut) {
customShortcut();
}
}
/**
* Removes the dialog for a giveb webview
* @param webviewId The id of the webview
*/
removeDialog(webviewId) {
const data = this.webviews.get(webviewId);
if (data) {
chrome.tabs.query({}, (tabs) => {
const tab = tabs.find(tab => tab.vivExtData && tab.vivExtData.includes(`${webviewId}tabId`));
if (tab) chrome.tabs.remove(tab.id);
});
data.divContainer.remove();
chrome.tabs.onRemoved.removeListener(data.tabCloseListener);
this.webviews.delete(webviewId);
}
}
/**
* Checks if the current window is the correct window to show the dialog and then opens the dialog
* @param {string} linkUrl the url to load
* @param {boolean} fromPanel indicates whether the dialog is opened from a panel
*/
dialogTab(linkUrl, fromPanel = undefined) {
chrome.windows.getLastFocused((window) => {
if (window.id === vivaldiWindowId && window.state !== chrome.windows.WindowState.MINIMIZED) {
this.showDialog(linkUrl, fromPanel);
}
});
}
/**
* Opens a link in a dialog like display in the current visible tab
* @param {string} linkUrl the url to load
* @param {boolean} fromPanel indicates whether the dialog is opened from a panel
*/
showDialog(linkUrl, fromPanel) {
const dialogContainer = document.createElement('div'),
dialogTab = document.createElement('div'),
webview = document.createElement('webview'),
webviewId = `dialog-${this.getWebviewId()}`,
progressBar = new ProgressBar(webviewId),
optionsContainer = document.createElement('div');
if (fromPanel === undefined && this.webviews.size !== 0) {
fromPanel = Array.from(this.webviews.values()).at(-1).fromPanel;
}
const tabId = !fromPanel ? Number(document.querySelector('.active.visible.webpageview webview').tab_id) : null;
this.webviews.set(webviewId, {
divContainer: dialogContainer,
webview: webview,
fromPanel: fromPanel,
tabId: tabId
});
// remove dialogs when tab is closed without closing dialogs
if (!fromPanel) {
const clearWebviews = (closedTabId) => {
if (tabId === closedTabId) {
this.webviews.forEach((view, key) => view.tabCloseListener === clearWebviews && this.removeDialog(key));
chrome.tabs.onRemoved.removeListener(clearWebviews);
}
};
this.webviews.get(webviewId).tabCloseListener = clearWebviews;
chrome.tabs.onRemoved.addListener(clearWebviews);
}
//#region dialogTab properties
dialogTab.setAttribute('class', 'dialog-tab');
dialogTab.style.width = 85 - 5 * this.webviews.size + '%';
dialogTab.style.height = 95 - 5 * this.webviews.size + '%';
//#endregion
//#region optionsContainer properties
optionsContainer.setAttribute('class', 'options-container');
optionsContainer.innerHTML = this.iconUtils.ellipsis;
let timeout;
optionsContainer.addEventListener('mouseover', () => {
if (optionsContainer.children.length === 1) {
optionsContainer.innerHTML = '';
this.showWebviewOptions(webviewId, optionsContainer);
}
clearTimeout(timeout);
});
optionsContainer.addEventListener('mouseleave', () => {
timeout = setTimeout(() => optionsContainer.innerHTML = this.iconUtils.ellipsis, 1500);
});
//#endregion
//#region webview properties
webview.id = webviewId;
webview.tab_id = `${webviewId}tabId`;
webview.setAttribute('src', linkUrl);
webview.addEventListener('loadstart', () => {
webview.style.backgroundColor = 'var(--colorBorder)';
progressBar.start();
const input = document.getElementById(`input-${webview.id}`);
if (input !== null) {
input.value = webview.src;
}
});
webview.addEventListener('loadstop', () => progressBar.clear(true));
fromPanel && webview.addEventListener('mousedown', (event) => event.stopPropagation());
//#endregion
//#region dialogContainer properties
dialogContainer.setAttribute('class', 'dialog-container');
let stopEvent = (event) => {
event.preventDefault();
event.stopPropagation();
if (event.target.id === `input-${webviewId}`) {
const inputElement = event.target;
// Calculate the cursor position based on the click location
const offsetX = event.clientX - inputElement.getBoundingClientRect().left;
// Create a canvas to measure text width
const context = document.createElement('canvas').getContext('2d');
context.font = window.getComputedStyle(inputElement).font;
// Measure the width of the text up to each character
let cursorPosition = 0,
textWidth = 0;
for (let i = 0; i < inputElement.value.length; i++) {
const charWidth = context.measureText(inputElement.value[i]).width;
if (textWidth + charWidth > offsetX) {
cursorPosition = i;
break;
}
textWidth += charWidth;
cursorPosition = i + 1;
}
// Manually focus the input element and set the cursor position
inputElement.focus({preventScroll: true});
inputElement.setSelectionRange(cursorPosition, cursorPosition);
}
};
fromPanel && document.body.addEventListener('pointerdown', stopEvent);
dialogContainer.addEventListener('click', (event) => {
if (event.target === dialogContainer) {
fromPanel && document.body.removeEventListener('pointerdown', stopEvent);
this.removeDialog(webviewId);
}
});
//#endregion
dialogTab.appendChild(optionsContainer);
dialogTab.appendChild(progressBar.element);
dialogTab.appendChild(webview);
dialogContainer.appendChild(dialogTab);
// Get for current tab and append divContainer
fromPanel
? document.querySelector('#browser').appendChild(dialogContainer)
: document.querySelector('.active.visible.webpageview').appendChild(dialogContainer);
}
/**
* Displays open in tab buttons and current url in input element
* @param {string} webviewId is the id of the webview
* @param {Object} thisElement the current instance divOptionContainer (div) element
*/
showWebviewOptions(webviewId, thisElement) {
let inputId = `input-${webviewId}`,
data = this.webviews.get(webviewId),
webview = data ? data.webview : undefined;
if (webview && document.getElementById(inputId) === null) {
const input = document.createElement('input', 'text'),
VALID_URL_PREFIXES = [
'http://',
'https://',
'file://',
'vivaldi://'
],
isValidUrl = (url) => VALID_URL_PREFIXES.some(prefix => url.startsWith(prefix) || url === 'about:blank');
input.value = webview.src;
input.id = inputId;
input.setAttribute('class', 'dialog-input');
input.addEventListener('keydown', async (event) => {
if (event.key === 'Enter') {
let value = input.value;
if (isValidUrl(value)) {
webview.src = value;
} else {
const searchRequest = await vivaldi.searchEngines.getSearchRequest(this.searchEngineUtils.defaultSearchId, value);
webview.src = searchRequest.url;
}
}
});
const fragment = document.createDocumentFragment(),
buttons = [
{content: this.iconUtils.back, action: () => webview.back()},
{content: this.iconUtils.forward, action: () => webview.forward()},
{content: this.iconUtils.reload, action: () => webview.reload()},
{
content: this.iconUtils.readerView,
action: this.showReaderView.bind(this, webview),
cls: 'reader-view-toggle'
},
{content: this.iconUtils.newTab, action: this.openNewTab.bind(this, inputId, true)},
{content: this.iconUtils.backgroundTab, action: this.openNewTab.bind(this, inputId, false)},
];
buttons.forEach(button => fragment.appendChild(this.createOptionsButton(button.content, button.action, button.cls || '')));
fragment.appendChild(input);
thisElement.append(fragment);
}
}
/**
* Create a button with default style for the web view options.
* @param {Node | string} content the content of the button to display
* @param {Function} clickListenerCallback the click listeners callback function
* @param {string} cls optional additional class for the button
*/
createOptionsButton(content, clickListenerCallback, cls = '') {
const button = document.createElement('button');
button.setAttribute('class', `options-button ${cls}`.trim());
button.addEventListener('click', clickListenerCallback);
if (typeof content === 'string') {
button.innerHTML = content;
} else {
button.appendChild(content);
}
return button;
}
/**
* Returns a random, verified id.
*/
getWebviewId() {
return Math.floor(Math.random() * 10000) + new Date().getTime() % 1000;
}
/**
* Sets the webviews content to a reader version
*
* @param {webview} webview the webview to update
*/
showReaderView(webview) {
if (webview.src.includes('https://clearthis.page/?u=')) {
webview.src = webview.src.replace('https://clearthis.page/?u=', '');
} else {
webview.src = `https://clearthis.page/?u=${webview.src}`;
}
}
/**
* Opens a new Chrome tab with specified active boolean value
* @param {string} inputId is the id of the input containing current url
* @param {boolean} active indicates whether the tab is active or not (background tab)
*/
openNewTab(inputId, active) {
const url = document.getElementById(inputId).value;
chrome.tabs.create({url: url, active: active});
}
}
class WebsiteInjectionUtils {
constructor(getWebviewConfig, openDialog, iconConfig) {
this.iconConfig = JSON.stringify(iconConfig);
// inject detection of click observers
chrome.webNavigation.onCompleted.addListener((navigationDetails) => {
const {webview, fromPanel} = getWebviewConfig(navigationDetails);
webview && this.injectCode(webview, fromPanel);
});
// react on demand to open a dialog
chrome.runtime.onMessage.addListener((message) => {
if (message.url) {
openDialog(message.url, message.fromPanel);
}
});
}
injectCode(webview, fromPanel) {
const handler = WebsiteLinkInteractionHandler.toString(),
instantiationCode = `
if (!this.dialogEventListenerSet){
new (${handler})(${fromPanel}, ${this.iconConfig});
this.dialogEventListenerSet = true;
}
`;
webview.executeScript({code: instantiationCode});
}
}
class WebsiteLinkInteractionHandler {
constructor(fromPanel, config) {
this.fromPanel = fromPanel;
this.config = config;
this.icon = null;
this.timers = {
showIcon: null,
showDialog: null,
hideIcon: null
}
this.#initialize();
}
/**
* Checks if a link is clicked by the middle mouse while pressing Ctrl + Alt, then fires an event with the Url
*/
#initialize() {
this.#setupMouseHandling();
if (this.config.linkIcon) {
this.#setupIconHandling();
}
}
/**
* Richtet die Maus-Event-Listener ein
*/
#setupMouseHandling() {
let holdTimerForMiddleClick;
document.addEventListener('pointerdown', (event) => {
// Check if the Ctrl key, Alt key, and mouse button were pressed
if (event.ctrlKey && event.altKey && [0, 1].includes(event.button)) {
this.#callDialog(event);
} else if (event.button === 1) {
holdTimerForMiddleClick = setTimeout(() => this.#callDialog(event), 500);
}
});
document.addEventListener('pointerup', (event) => {
if (event.button === 1) clearTimeout(holdTimerForMiddleClick);
});
}
#setupIconHandling() {
this.#createIcon();
this.#createIconStyle()
document.addEventListener('mouseover', this.debounce((event) => {
const link = this.#getLinkElement(event);
if (!link) return;
clearTimeout(this.timers.hideIcon);
requestAnimationFrame(() => {
const rect = link.getBoundingClientRect();
Object.assign(this.icon.style, {
display: 'block',
left: `${rect.right + 5}px`,
top: `${rect.top + window.scrollY}px`
});
});
this.icon.dataset.targetUrl = link.href;
link.addEventListener('mouseleave', this.#hideLinkIcon.bind(this));
}, this.config.showIconDelay));
}
#createIcon() {
const icon = document.createElement('div');
icon.className = `link-icon ${this.config.linkIcon}`;
icon.style.display = 'none';
if (this.config.linkIconInteractionOnHover) {
icon.addEventListener('mouseenter', () => {
this.timers.showDialog = setTimeout(() => this.#sendDialogMessage(this.icon.dataset.targetUrl), this.config.showDialogOnHoverDelay);
});
icon.addEventListener('mouseleave', () => clearTimeout(this.timers.showDialog));
} else {
icon.addEventListener('click', () => this.#sendDialogMessage(this.icon.dataset.targetUrl));
icon.addEventListener('mouseenter', () => clearTimeout(this.timers.hideIcon));
icon.addEventListener('mouseleave', this.#hideLinkIcon.bind(this));
}
this.icon = icon;
document.body.appendChild(this.icon);
}
#hideLinkIcon() {
this.timers.hideIcon = setTimeout(() => {
this.icon.style.display = 'none';
clearTimeout(this.timers.showIcon);
}, this.config.linkIconInteractionOnHover ? 300 : 600);
}
#getLinkElement(event) {
return event.target.closest('a[href]:not([href="#"])');
}
#sendDialogMessage(url) {
chrome.runtime.sendMessage({url, fromPanel: this.fromPanel});
}
#callDialog(event) {
let link = this.#getLinkElement(event);
if (link) {
event.preventDefault();
this.#sendDialogMessage(link.href);
}
};
#createIconStyle() {
const style = document.createElement('style');
style.textContent = `
.link-icon {
position: absolute;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
cursor: pointer;
z-index: 9999;
transition: opacity 0.2s ease;
}
.link-icon:hover {
opacity: 0.9;
}
`;
document.head.appendChild(style);
}
debounce(fn, delay) {
let timer = null;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(fn.bind(this, ...args), delay);
}
};
}
/**
* Utility class for adding and updating context menu items
*/
class SearchEngineUtils {
/**
* Constructor for SearchEngineUtils
* @param {Function} openLinkCallback - Callback for opening links
* @param {Function} searchCallback - Callback for searching
* @param {Object} [config={}] - Configuration options
* @param {string} [config.menuPrefix] - Prefix for the context menu item
* @param {string} [config.linkMenuTitle] - Titel for the link menu
* @param {string} [config.searchMenuTitle] - title for the search menu
* @param {string} [config.selectSearchMenuTitle] - title for the select search menu
*/
constructor(openLinkCallback, searchCallback, config = {}) {
this.openLinkCallback = openLinkCallback;
this.searchCallback = searchCallback;
this.menuPrefix = config.menuPrefix;
this.linkMenuTitle = config.linkMenuTitle;
this.searchMenuTitle = config.searchMenuTitle;
this.selectSearchMenuTitle = config.selectSearchMenuTitle;
this.createdContextMenuMap = new Map();
this.searchEngineCollection = [];
this.defaultSearchId = null;
this.privateSearchId = null;
// Cache static IDs for frequent access
this.LINK_ID = 'dialog-tab-link';
this.SEARCH_ID = 'search-dialog-tab';
this.SELECT_SEARCH_ID = 'select-search-dialog-tab';
this.#initialize();
}
/**
* Initializes the context menu and listeners
* @returns {Promise<void>}
*/
async #initialize() {
// Create context menu items
this.#createContextMenuOption();
// Initialize search engines and context menus
this.#updateSearchEnginesAndContextMenu();
// Update context menus when search engines change
vivaldi.searchEngines.onTemplateUrlsChanged.addListener(() => {
this.#removeContextMenuSelectSearch();
this.#updateSearchEnginesAndContextMenu();
});
}
/**
* Creates context menu items to open a dialog tab
*/
#createContextMenuOption() {
chrome.contextMenus.create({
id: this.LINK_ID,
title: `${this.menuPrefix} ${this.linkMenuTitle}`,
contexts: ['link']
});
chrome.contextMenus.create({
id: this.SEARCH_ID,
title: `${this.menuPrefix} ${this.searchMenuTitle}`,
contexts: ['selection']
});
chrome.contextMenus.create({
id: this.SELECT_SEARCH_ID,
title: `${this.menuPrefix} ${this.selectSearchMenuTitle}`,
contexts: ['selection']
});
chrome.contextMenus.onClicked.addListener((itemInfo) => {
const {menuItemId, parentMenuItemId, linkUrl, selectionText} = itemInfo;
if (menuItemId === this.LINK_ID) {
this.openLinkCallback(linkUrl);
} else if (menuItemId === this.SEARCH_ID) {
const engineId = window.incognito ? this.privateSearchId : this.defaultSearchId;
this.searchCallback(engineId, selectionText);
} else if (parentMenuItemId === this.SELECT_SEARCH_ID) {
const engineId = menuItemId.substr(parentMenuItemId.length);
this.searchCallback(engineId, selectionText);
}
});
}
/**
* Updates the search engines and context menu
*/
async #updateSearchEnginesAndContextMenu() {
const searchEngines = await vivaldi.searchEngines.getTemplateUrls();
this.searchEngineCollection = searchEngines.templateUrls;
this.defaultSearchId = searchEngines.defaultSearch;
this.privateSearchId = searchEngines.defaultPrivate;
this.#createContextMenuSelectSearch();
}
/**
* Removes sub-context menu items for select search engine menu item
*/
#removeContextMenuSelectSearch() {
this.createdContextMenuMap.forEach((_, engineId) => {
const menuId = this.SELECT_SEARCH_ID + engineId;
chrome.contextMenus.remove(menuId);
});
this.createdContextMenuMap.clear();
}
/**
* Creates sub-context menu items for select search engine menu item
*/
#createContextMenuSelectSearch() {
this.searchEngineCollection.forEach((engine) => {
if (!this.createdContextMenuMap.has(engine.guid)) {
chrome.contextMenus.create({
id: this.SELECT_SEARCH_ID + engine.guid,
parentId: this.SELECT_SEARCH_ID,
title: engine.name,
contexts: ['selection']
});
this.createdContextMenuMap.set(engine.guid, true);
}
});
}
}
class ProgressBar {
constructor(webviewId) {
this.webviewId = webviewId;
this.progress = 0;
this.interval = null;
this.element = this.#createProgressBar(webviewId);
}
#createProgressBar(webviewId) {
const progressBar = document.createElement('div');
progressBar.setAttribute('class', 'progress-bar');
progressBar.id = `progressBar-${webviewId}`;
return progressBar;
}
start() {
this.element.style.visibility = 'visible';
this.progress = 0;
if (!this.interval) {
this.interval = setInterval(() => {
if (this.progress >= 100) {
this.clear();
} else {
this.progress++;
this.element.style.width = this.progress + '%';
}
}, 10);
}
}
clear(loadStop = false) {
if (this.interval) {
clearInterval(this.interval);
this.interval = null;
}
if (loadStop) {
this.element.style.width = '100%';
setTimeout(() => {
this.progress = 0;
this.element.style.visibility = 'hidden';
this.element.style.width = this.progress + '%';
}, 250);
}
}
}
/**
* Utility class to manage SVG icons
* @class
*/
class IconUtils {
// Static icons
static SVG = {
ellipsis: '<svg xmlns="http://www.w3.org/2000/svg" height="2em" viewBox="0 0 448 512"><path d="M8 256a56 56 0 1 1 112 0A56 56 0 1 1 8 256zm160 0a56 56 0 1 1 112 0 56 56 0 1 1 -112 0zm216-56a56 56 0 1 1 0 112 56 56 0 1 1 0-112z"/></svg>',
readerView: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3 4h10v1H3zM3 6h10v1H3zM3 8h10v1H3zM3 10h6v1H3z"></path></svg>',
newTab: '<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512"><path d="M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32h82.7L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3V192c0 17.7 14.3 32 32 32s32-14.3 32-32V32c0-17.7-14.3-32-32-32H320zM80 32C35.8 32 0 67.8 0 112V432c0 44.2 35.8 80 80 80H400c44.2 0 80-35.8 80-80V320c0-17.7-14.3-32-32-32s-32 14.3-32 32V432c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V112c0-8.8 7.2-16 16-16H192c17.7 0 32-14.3 32-32s-14.3-32-32-32H80z"/></svg>',
backgroundTab: '<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 448 512"><path d="M384 32c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96C0 60.7 28.7 32 64 32H384zM160 144c-13.3 0-24 10.7-24 24s10.7 24 24 24h94.1L119 327c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l135-135V328c0 13.3 10.7 24 24 24s24-10.7 24-24V168c0-13.3-10.7-24-24-24H160z"/></svg>'
};
// Vivaldi icons
static VIVALDI_BUTTONS = [{
name: 'back',
buttonName: 'Back',
fallback: '<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 448 512"><path d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.2 288 416 288c17.7 0 32-14.3 32-32s-14.3-32-32-32l-306.7 0L214.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg>'
}, {
name: 'forward',
buttonName: 'Forward',
fallback: '<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 448 512"><path d="M438.6 278.6c12.5-12.5 12.5-32.8 0-45.3l-160-160c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L338.8 224 32 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l306.7 0L233.4 393.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l160-160z"/></svg>'
}, {
name: 'reload',
buttonName: 'Reload',
fallback: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M125.7 160H176c17.7 0 32 14.3 32 32s-14.3 32-32 32H48c-17.7 0-32-14.3-32-32V64c0-17.7 14.3-32 32-32s32 14.3 32 32v51.2L97.6 97.6c87.5-87.5 229.3-87.5 316.8 0s87.5 229.3 0 316.8s-229.3 87.5-316.8 0c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0c62.5 62.5 163.8 62.5 226.3 0s62.5-163.8 0-226.3s-163.8-62.5-226.3 0L125.7 160z"/></svg>'
}];
#initialized = false;
#iconMap = new Map();
constructor() {
this.#initializeStaticIcons();
}
/**
* Initializes static icons
*/
#initializeStaticIcons() {
Object.entries(IconUtils.SVG).forEach(([key, value]) => {
this.#iconMap.set(key, value);
});
}
/**
* Initialize Vivaldi icons from the DOM or use fallback
*/
#initializeVivaldiIcons() {
if (this.#initialized) return;
IconUtils.VIVALDI_BUTTONS.forEach(button => {
this.#iconMap.set(button.name, this.#getVivaldiButton(button.buttonName, button.fallback));
});
this.#initialized = true;
}
/**
* Gets the SVG of a Vivaldi button or returns the fallback
* @param {string} buttonName - name of the button in Vivali ui
* @param {string} fallbackSVG - fallback svg if no icon is found
* @returns {string} - the SVG as a string
*/
#getVivaldiButton(buttonName, fallbackSVG) {
const svg = document.querySelector(`.button-toolbar [name="${buttonName}"] svg`);
return svg ? svg.cloneNode(true).outerHTML : fallbackSVG;
}
/**
* Get icon by name
* @param {string} name - Name of the icon
* @returns {string} - Icon as SVG string
*/
getIcon(name) {
if (!this.#initialized && IconUtils.VIVALDI_BUTTONS.some(btn => btn.name === name)) {
this.#initializeVivaldiIcons();
}
return this.#iconMap.get(name) || '';
}
get ellipsis() {
return this.getIcon('ellipsis');
}
get back() {
return this.getIcon('back');
}
get forward() {
return this.getIcon('forward');
}
get reload() {
return this.getIcon('reload');
}
get readerView() {
return this.getIcon('readerView');
}
get newTab() {
return this.getIcon('newTab');
}
get backgroundTab() {
return this.getIcon('backgroundTab');
}
}
})
();

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,172 @@
/**
* Groups tabs by domain.
* Forum link: https://forum.vivaldi.net/topic/98184/group-tabs-by-domain?lang=en-US&page=1
*/
(async () => {
'use strict';
const config = {
// Use the base domain for tab stacks (true: enabled, false: disabled)
base_domain: false,
// Automatically change the name of the tab stack (0: disabled, 1: use hostname, 2: generate from base domain)
rename_stack: 0,
// Workspaces that allow automatic tab stacking (exact match or <default_workspace>)
// * If not set, automatic tab stacking is allowed in all workspaces
allow_workspaces: [
// "Shopping",
],
// Domains that allow automatic tab stacking (exact match or regular expression)
// * If not set, automatic tab stacking is allowed for all domains
allow_domains: [
// "www.example.com",
// /^(.+\.)?example\.net$/,
],
// Domains to exclude from automatic tab stacking (exact match or regular expression)
block_domains: [
// "www.example.com",
// /^(.+\.)?example\.net$/,
],
};
const mergeArrays = (...arrays) => [...new Set(arrays.flat())];
const getUrlFragments = (url) => vivaldi.utilities.getUrlFragments(url);
const getBaseDomain = (url) => {
const {hostForSecurityDisplay, tld} = getUrlFragments(url);
return hostForSecurityDisplay.match(`([^.]+\\.${ tld })$`)?.[1] || hostForSecurityDisplay;
};
const getHostname = (url) => {
const {hostForSecurityDisplay} = getUrlFragments(url);
return config.base_domain ? getBaseDomain(url) : hostForSecurityDisplay;
};
const matchHostRule = (url, rule) => {
const {hostForSecurityDisplay} = getUrlFragments(url);
return rule instanceof RegExp ? rule.test(hostForSecurityDisplay) : hostForSecurityDisplay === rule;
};
const getTab = async (tabId) => {
const tab = await chrome.tabs.get(tabId);
if (tab.vivExtData) {
tab.vivExtData = JSON.parse(tab.vivExtData);
return tab;
}
};
const getTabIndex = async (tabId) => (await getTab(tabId)).index;
const getWorkspaceName = async (workspaceId) => {
if (!workspaceId) {
return '<default_workspace>';
}
const workspaceList = await vivaldi.prefs.get('vivaldi.workspaces.list');
return workspaceList.find(item => item.id === workspaceId).name;
};
const getTabsByWorkspace = async () => {
const tabs = (await chrome.tabs.query({ currentWindow: true }))
.filter(tab => tab.id !== -1 && tab.vivExtData)
.map(tab => Object.assign(tab, { vivExtData: JSON.parse(tab.vivExtData) }))
.filter(tab => !tab.pinned && !tab.vivExtData.panelId)
.filter(tab => !config.allow_domains.length || config.allow_domains.find(rule => matchHostRule(tab.url, rule)))
.filter(tab => !config.block_domains.length || !config.block_domains.find(rule => matchHostRule(tab.url, rule)));
return Object.groupBy(tabs, tab => tab.vivExtData.workspaceId);
};
const getTabsByStack = (tabs) => Object.groupBy(tabs, tab => tab.vivExtData.group);
const getTabsByHost = (tabs) => Object.groupBy(tabs, tab => getHostname(tab.url));
const getMaxTabsStackId = (tabsByStack, targetHost) => {
const counts = {};
for (const [stackId, tabs] of Object.entries(tabsByStack)) {
if (stackId !== 'undefined') {
const tabsByHost = getTabsByHost(tabs);
const count = tabsByHost[targetHost]?.length || 0;
delete tabsByHost[targetHost];
counts[stackId] = Object.values(tabsByHost)
.reduce((acc, tabs) => {
return acc > tabs.length ? acc : 0;
}, count);
}
}
return Object.entries(counts)
.reduce((acc, [stackId, count]) => {
return acc[1] < count ? [stackId, count] : acc;
}, [, 0])[0];
};
const getTabStackName = (url) => {
let stackName;
switch (config.rename_stack) {
case 1:
stackName = getHostname(url);
break;
case 2:
stackName = getBaseDomain(url).split('.')[0];
stackName = stackName.charAt(0).toUpperCase() + stackName.slice(1);
break;
}
return stackName;
};
const addTabStack = async (tabId, stackId, stackName) => {
const {vivExtData} = await getTab(tabId);
if (stackName) {
vivExtData.fixedGroupTitle = stackName;
}
vivExtData.group = stackId;
chrome.tabs.update(tabId, { vivExtData: JSON.stringify(vivExtData) });
};
const stackingTabs = async (workspaceId) => {
const workspaceName = await getWorkspaceName(workspaceId);
if (!config.allow_workspaces.length || config.allow_workspaces.includes(workspaceName)) {
const tabsByWorkspace = await getTabsByWorkspace();
const tabsByStack = getTabsByStack(tabsByWorkspace[workspaceId]);
const tabsByHost = getTabsByHost(tabsByWorkspace[workspaceId]);
for (const [host, tabs] of Object.entries(tabsByHost)) {
const targetStackId = getMaxTabsStackId(tabsByStack, host) || crypto.randomUUID();
const targetStackTabs = tabsByStack[targetStackId] ? getTabsByHost(tabsByStack[targetStackId])[host] : [];
const targetTabs = mergeArrays(targetStackTabs, tabs);
const targetStackName = getTabStackName(tabs[0].pendingUrl || tabs[0].url);
let tabIndex = await getTabIndex(targetTabs[0].id);
for (const tab of targetTabs) {
addTabStack(tab.id, targetStackId, targetStackName);
chrome.tabs.move(tab.id, { index: tabIndex });
tabIndex++;
}
}
}
};
chrome.webNavigation.onCommitted.addListener(async details => {
if (details.tabId !== -1) {
const tab = await getTab(details.tabId);
if (tab && !tab.pinned && !tab.vivExtData.panelId && details.frameType === 'outermost_frame') {
const workspaceId = tab.vivExtData.workspaceId;
stackingTabs(workspaceId);
}
}
});
})();

147
.vivaldi-mods/posix.lua Executable file
View file

@ -0,0 +1,147 @@
-- This file contains wrappers for hilbish.run for common POSIX utilities.
local M = {}
M.pwd = function()
return hilbish.run("pwd", false)
end
M.touch = function(file, opts)
local cmd = "touch "
if opts then
if opts.sudo ~=nil and opts.sudo == true then
cmd = "sudo " .. cmd
end
if opts.change_mod_time ~= nil and opts.change_mod_time == true then
cmd = cmd .. "-m "
end
if opts.change_access_time ~= nil and opts.change_access_time == true then
cmd = cmd .. "-a "
end
if opts.flags ~= nil then
cmd = cmd .. opts.flags .. " "
end
end
cmd = cmd .. file
return hilbish.run(cmd, false)
end
M.cp = function(file1, file2, opts)
local cmd = "cp "
if opts then
if opts.sudo ~= nil and opts.sudo == true then
cmd = "sudo " .. cmd
end
if opts.force ~= nil and opts.force == true then
cmd = cmd .. "-f "
end
if opts.recursive ~= nil and opts.recursive == true then
cmd = cmd .. "-r "
end
if opts.flags ~= nil then
cmd = cmd .. opts.flags .. " "
end
end
cmd = cmd .. file1 .. " " .. file2
return hilbish.run(cmd, false)
end
M.rm = function(file, opts)
local cmd = "rm "
if opts then
if opts.sudo ~= nil and opts.sudo == true then
cmd = "sudo " .. cmd
end
if opts.force ~= nil and opts.force == true then
cmd = cmd .. "-f "
end
if opts.recursive ~= nil and opts.recursive == true then
cmd = cmd .. "-r "
end
if opts.flags ~= nil then
cmd = cmd .. opts.flags .. " "
end
end
cmd = cmd .. file
return hilbish.run(cmd, false)
end
M.mv = function(file1, file2, opts)
local cmd = "mv "
if opts then
if opts.sudo ~= nil and opts.sudo == true then
cmd = "sudo " .. cmd
end
if opts.flags ~= nil then
cmd = cmd .. opts.flags .. " "
end
end
cmd = cmd .. file1 .. " " .. file2
return hilbish.run(cmd, false)
end
M.find = function(dir, opts)
local cmd = "find " .. dir .. " "
if opts then
if opts.depth ~= nil then
cmd = cmd .. "-depth " .. opts.depth .. " "
end
if opts.maxdepth ~= nil then
cmd = cmd .. "-maxdepth " .. opts.maxdepth .. " "
end
if opts.type ~= nil then
cmd = cmd .. "-type " .. opts.type .. " "
end
if opts.name ~= nil then
cmd = cmd .. "-name " .. opts.name .. " "
end
if opts.flags ~= nil then
cmd = cmd .. opts.flags .. " "
end
end
return hilbish.run(cmd, false)
end
M.dirname = function(dir)
return hilbish.run("dirname " .. dir, false)
end
M.sed = function(script, file, opts)
local cmd = "sed -e '" .. script .. "' "
if opts then
if opts.sudo ~= nil and opts.sudo == true then
cmd = "sudo " .. cmd
end
if opts.script_file ~= nil then
cmd = cmd .. "-f " .. opts.script_file .. " "
end
if opts.suppress_default ~= nil and opts.suppress_default == true then
cmd = cmd .. "-n "
end
if opts.flags ~= nil then
cmd = cmd .. opts.flags .. " "
end
end
cmd = cmd .. file
return hilbish.run(cmd, false)
end
M.cat = function(files, opts)
local cmd = "cat " .. files .. " "
if opts then
if opts.sudo ~= nil and opts.sudo == true then
cmd = "sudo " .. cmd
end
-- The following two options are mutually exclusive
if opts.output_file ~= nil then
cmd = cmd .. "> " .. opts.output_file
elseif opts.append_file ~= nil then
cmd = cmd .. ">> " .. opts.append_file
end
end
return hilbish.run(cmd, false)
end
return M

View file

@ -0,0 +1,18 @@
#!/usr/bin/env hilbish
local fs = require("fs")
local posix = require("posix")
local _, vivaldi_install = posix.find("/opt", { name = "vivaldi-bin" })
local _, dir = posix.dirname(vivaldi_install)
dir = dir:gsub("\n", "")
local matches = fs.glob(dir .. "/resources/vivaldi/window.html.bak")
if #matches ~= 0 then
print("Restoring window.html backup in " .. dir)
posix.mv(matches[1], dir .. "/resources/vivaldi/window.html", {sudo = true})
else
print("No backup")
end