diff --git a/.config/btop/btop.conf b/.config/btop/btop.conf
index 9e0ee914..1db1414c 100644
--- a/.config/btop/btop.conf
+++ b/.config/btop/btop.conf
@@ -63,7 +63,7 @@ proc_sorting = "memory"
proc_reversed = False
#* Show processes as a tree.
-proc_tree = False
+proc_tree = True
#* Use the cpu graph colors in the process list.
proc_colors = True
diff --git a/.config/fish/config.fish b/.config/fish/config.fish
index 6e12a307..2dca25cf 100644
--- a/.config/fish/config.fish
+++ b/.config/fish/config.fish
@@ -1,15 +1,14 @@
-if status is-login
- if not set -q __sourced_profile
- set -x __sourced_profile 1
- exec bash -c "\
- test -e /etc/profile && source /etc/profile
- test -e $HOME/.bash_profile && source $HOME/.bash_profile
- exec fish --login
- "
- end
+# if status is-login
+# if not set -q __sourced_profile
+# set -x __sourced_profile 1
+# exec bash -c "\
+# test -e /etc/profile && source /etc/profile
+# test -e $HOME/.bash_profile && source $HOME/.bash_profile
+# exec fish --login
+# "
+# end
- set -e __sourced_profile
-end
+# end
if status is-interactive
# source ~/.config/fish/custom_cd.fish
@@ -23,5 +22,7 @@ if status is-interactive
set -gx COLORTERM truecolor
set -gx TERM xterm-256color
end
+
end
set -gx EDITOR kak
+
diff --git a/.config/fish/fish_variables b/.config/fish/fish_variables
index 56c36ec5..5190f07b 100644
--- a/.config/fish/fish_variables
+++ b/.config/fish/fish_variables
@@ -2,6 +2,7 @@
# VERSION: 3.0
SETUVAR --export AUTOYADMPUSH:1
SETUVAR --export EDITOR:kak
+SETUVAR --export IGREP_CUSTOM_EDITOR:kak\x20\x2b\x7bline_number\x7d\x20\x7bfile_name\x7d
SETUVAR --export KAKOUNE_POSIX_SHELL:/usr/bin/dash
SETUVAR --export XDG_CONFIG_HOME:/home/fic/\x2econfig
SETUVAR Z_DATA_DIR:/home/fic/\x2elocal/share/z
diff --git a/.config/fish/functions/kak-session.fish b/.config/fish/functions/kak-session.fish
index 6354a948..4fb20338 100644
--- a/.config/fish/functions/kak-session.fish
+++ b/.config/fish/functions/kak-session.fish
@@ -86,6 +86,8 @@ function kak-session -w kak --description "kakoune where sessions are derived fr
cat $fifo >/dev/null
command rm -r "$fifo_dir"
+ # echo "hook -once global BufCreate ^(?!.*\\*scratch\\*).* %{ delete-buffer *scratch* }" | kak -p "$session_id"
+ # command kak -c "$session_id" -e 'delete-buffer! *scratch*' $flags $files
command kak -c "$session_id" -e 'try %{ delete-buffer *scratch*; bar-buflist; echo }' $flags $files
else
command kak -s "$session_id" -e "cd %[$kakroot]" $flags $files
@@ -116,6 +118,8 @@ function kak-session -w kak --description "kakoune where sessions are derived fr
setsid kak -d -s "$session_id" -E "cd %[$git_dir]; echo -to-file $fifo ready" &
cat $fifo >/dev/null
command rm -r "$fifo_dir"
+ # echo "hook -once global BufCreate [*]scratch[*] %{ delete-buffer *scratch* }" | kak -p "$session_id"
+ # command kak -c "$session_id" -e 'delete-buffer! *scratch*' $flags $files
command kak -c "$session_id" -e 'try %{ delete-buffer *scratch*; bar-buflist; echo }' $flags $files
else
command kak -s "$session_id" -e "cd %[$git_dir]" $flags $files
diff --git a/.config/kak-tree-sitter/config.toml b/.config/kak-tree-sitter/config.toml
index c6283d9f..ea000905 100644
--- a/.config/kak-tree-sitter/config.toml
+++ b/.config/kak-tree-sitter/config.toml
@@ -96,3 +96,47 @@ pin = "7275b7f85014aad7e15d4987ec4f2249572eecfb"
[language.ini.queries]
path = "runtime/queries/ini"
+[language.just]
+aliases = ["justfile"]
+
+[language.just.grammar.source.git]
+url = "https://github.com/poliorcetics/tree-sitter-just"
+pin = "8d03cfdd7ab89ff76d935827de1b93450fa0ec0a"
+
+[language.just.grammar]
+path = "src"
+compile = "cc"
+compile_args = ["-c", "-fpic", "../parser.c", "-I", ".."]
+compile_flags = ["-O3"]
+link = "cc"
+link_args = ["-shared", "-fpic", "parser.o", "-o", "just.so"]
+link_flags = ["-O3"]
+
+[language.just.queries.source.git]
+url = "https://github.com/helix-editor/helix"
+pin = "f6878f62f74430cff188e7978d06c5ed143179e9"
+
+[language.just.queries]
+path = "runtime/queries/just"
+
+# typescript
+[language.typescript.grammar.source.git]
+url = "https://github.com/tree-sitter/tree-sitter-typescript"
+pin = "b1bf4825d9eaa0f3bdeb1e52f099533328acfbdf"
+
+[language.typescript.grammar]
+path = "typescript/src"
+compile = "cc"
+compile_args = ["-c", "-fpic", "../scanner.c", "../parser.c", "-I", ".."]
+compile_flags = ["-O3"]
+link = "cc"
+link_args = ["-shared", "-fpic", "scanner.o", "parser.o", "-o", "typescript.so"]
+link_flags = ["-O3"]
+
+[language.typescript.queries.source.git]
+url = "https://git.sr.ht/~ficd/kak-tree-sitter"
+pin = "d8afa2ddcf2f97d29f495eccc08ad9ccff8d9199"
+
+[language.typescript.queries]
+path = "runtime/queries/typescript"
+
diff --git a/.config/kak/autoload/clipboard.kak b/.config/kak/autoload/clipboard.kak
index c3a3cf1d..9c735a44 100644
--- a/.config/kak/autoload/clipboard.kak
+++ b/.config/kak/autoload/clipboard.kak
@@ -1,4 +1,56 @@
-map -docstring "yank the selection into the clipboard" global user y " wl-copy"
+declare-option -docstring %{
+ Command for copying to system clipboard.
+} str clipboard_copy_cmd 'wl-copy'
+
+declare-option int clip_selcount 0
+
+define-command -hidden clip-trim %{
+ try %{
+ execute-keys \n
+ execute-keys bjGjd
+ }
+}
+
+define-command -docstring %{
+ clip-copy [-split]: copy selections to system clipboard
+ Set the clipboard_copy_cmd option to change the command
+ Switches:
+ -split ensure each selection separated by newline
+} -params 0..1 clipboard-copy %{
+ # preserve registers
+ evaluate-commands -save-regs 'a|' %{
+ set-option local clip_selcount %val{selection_count}
+ # copy selections
+ execute-keys '"ay'
+ # set shell register to copy command
+ set-register | %opt{clipboard_copy_cmd}
+ # branch based on switch
+ execute-keys %sh{
+ if [ "$kak_opt_clip_selcount" -gt 1 ]; then
+ echo ': edit -scratch'
+ if [ ${#} = 1 ] && [ ${1} = '-split' ]; then
+ # paste all
+ # reduce selections to those without newline
+ # append a newline
+ # delete extra newlines
+ # select all, pipe to copy cmd
+ echo '"a\na'
+ echo 'gj: clip-trim'
+ echo '%'
+ else
+ # paste all, select all, pipe to copy cmd
+ echo '"a%'
+ fi
+ echo ": delete-buffer"
+ else
+ echo ''
+ fi
+ }
+ }
+}
+
+map -docstring "yank the selections into the clipboard" global user y ": clipboard-copy"
+map -docstring "yank the split selections into the clipboard" global user Y ": clipboard-copy -split"
map -docstring "paste the clipboard" global user p " wl-paste -n"
map -docstring "paste the clipboard before" global user P "! wl-paste -n"
diff --git a/.config/kak/autoload/detection/editorconfig.kak b/.config/kak/autoload/detection/editorconfig.kak
new file mode 100644
index 00000000..5d1b1711
--- /dev/null
+++ b/.config/kak/autoload/detection/editorconfig.kak
@@ -0,0 +1,106 @@
+# http://editorconfig.org/#file-format-details
+# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+# Patch by Daniel :
+# Support editorconfig for scratch buffers.
+# If we're in a scratch buffer, we check the filetype,
+# create a temp file with the appropriate extension, and pass
+# it to editorconfig. If there's no .editorconfig in /tmp,
+# we copy the one from $HOME. We clean up the files after.
+
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*[.](editorconfig) %{
+ set-option buffer filetype ini
+ set-option buffer static_words indent_style indent_size tab_width \
+ end_of_line charset insert_final_newline trim_trailing_whitespace root \
+ latin1 utf-8 utf-8-bom utf-16be utf-16le lf cr crlf unset space tab max_line_length
+}
+
+define-command editorconfig-load -params ..1 -docstring "editorconfig-load [file]: set formatting behavior according to editorconfig" %{
+ evaluate-commands %sh{
+ command -v editorconfig >/dev/null 2>&1 || { echo "fail editorconfig could not be found"; exit 1; }
+
+ file="${1:-$kak_buffile}"
+ filetype="$kak_opt_filetype"
+ # check if we have a real file or a scratch buffer
+ if [ ! -f "$file" ]; then
+ scratch="true"
+ # need to create .editorconfig in /tmp if it's not there
+ if [ ! -f "/tmp/.editorconfig" ]; then
+ cp "$HOME/.editorconfig" "/tmp/.editorconfig"
+ fi
+ case "$filetype" in
+ markdown)
+ file="/tmp/scratch.md"
+ touch "$file";;
+ python)
+ file="/tmp/scratch.py"
+ touch "$file";;
+ sh)
+ file="/tmp/scratch.sh"
+ touch "$file";;
+ bash)
+ file="/tmp/scratch.sh"
+ touch "$file";;
+ fish)
+ file="/tmp/scratch.fish"
+ touch "$file";;
+ json)
+ file="/tmp/scratch.json"
+ touch "$file";;
+ toml)
+ file="/tmp/scratch.toml"
+ touch "$file";;
+ *)
+ file="/tmp/scratch.txt"
+ touch "$file";;
+ esac
+ fi
+ case $file in
+ /*) # $kak_buffile is a full path that starts with a '/'
+ printf %s\\n "remove-hooks buffer editorconfig-hooks"
+ editorconfig "$file" | awk -v file="$file" -F= -- '
+ $1 == "indent_style" { indent_style = $2 }
+ $1 == "indent_size" { indent_size = $2 == "tab" ? 4 : $2 }
+ $1 == "tab_width" { tab_width = $2 }
+ $1 == "end_of_line" { end_of_line = $2 }
+ $1 == "charset" { charset = $2 }
+ $1 == "trim_trailing_whitespace" { trim_trailing_whitespace = $2 }
+ $1 == "max_line_length" { max_line_length = $2 }
+
+ END {
+ if (indent_style == "tab") {
+ print "set-option buffer indentwidth 0"
+ }
+ if (indent_style == "space") {
+ print "set-option buffer indentwidth " indent_size
+ }
+ if (indent_size || tab_width) {
+ print "set-option buffer tabstop " (tab_width ? tab_width : indent_size)
+ }
+ if (end_of_line == "lf" || end_of_line == "crlf") {
+ print "set-option buffer eolformat " end_of_line
+ }
+ if (charset == "utf-8-bom") {
+ print "set-option buffer BOM utf8"
+ }
+ if (trim_trailing_whitespace == "true") {
+ print "hook buffer BufWritePre \"" file "\" -group editorconfig-hooks %{ try %{ execute-keys -draft %{%s\\h+$d} } }"
+ }
+ if (max_line_length && max_line_length != "off") {
+ print "set window autowrap_column " max_line_length
+ print "autowrap-enable"
+ print "add-highlighter window/ column %sh{ echo $((" max_line_length "+1)) } default,bright-black"
+ }
+ }
+ ' ;;
+ esac
+ if [ -n "$scratch" ]; then
+ rm "/tmp/.editorconfig"
+ rm "$file"
+ fi
+ }
+}
+complete-command editorconfig-load file
diff --git a/.config/kak/autoload/filetype.kak b/.config/kak/autoload/filetype.kak
index b1d3093c..f177f806 100644
--- a/.config/kak/autoload/filetype.kak
+++ b/.config/kak/autoload/filetype.kak
@@ -21,19 +21,19 @@ hook global WinSetOption filetype=kak %{
hook global WinSetOption filetype=typst %{
set-option buffer formatcmd "typstyle --wrap-text"
hook -group typst-auto-format window BufWritePre .* format
- hook -once -always WinSetOption filetype=.* %{
+ hook -once -always window WinSetOption filetype=.* %{
unset-option window formatcmd
remove-hooks window typst-auto-format
}
- define-command -docstring %{
- Spawns a Zathura pdf preview and Typst watcher for the currently open Typst file
- } typst %{
- nop %sh{
- {
- "$kak_config/scripts/kak-typ-zathura.fish" -k -w "$kak_buffile" "$kak_client_pid"
- } > /dev/null 2>&1 < /dev/null &
- }
- }
+ define-command -docstring %{
+ Spawns a Zathura pdf preview and Typst watcher for the currently open Typst file
+ } typst %{
+ nop %sh{
+ {
+ "$kak_config/scripts/kak-typ-zathura.fish" -k -w "$kak_buffile" "$kak_client_pid"
+ } > /dev/null 2>&1 < /dev/null &
+ }
+ }
}
hook global WinSetOption filetype=fish %{
diff --git a/.config/kak/autoload/filetype/just.kak b/.config/kak/autoload/filetype/just.kak
new file mode 100644
index 00000000..5757aee1
--- /dev/null
+++ b/.config/kak/autoload/filetype/just.kak
@@ -0,0 +1,83 @@
+# Detection
+# ‾‾‾‾‾‾‾‾‾
+
+hook global BufCreate .*/?[jJ]ustfile %{
+ set-option buffer filetype justfile
+}
+
+hook global WinSetOption tree_sitter_lang=justfile %{
+ set-option window tree_sitter_lang just
+}
+
+hook global WinSetOption filetype=justfile %{
+ require-module justfile
+
+ hook window ModeChange pop:insert:.* -group justfile-trim-indent justfile-trim-indent
+ hook window InsertChar \n -group justfile-insert just-insert-on-new-line
+ hook window InsertChar \n -group justfile-indent just-indent-on-new-line
+ hook -once -always window WinSetOption filetype=.* %{ remove-hooks window justfile-.+ }
+}
+
+hook -group justfile-highlight global WinSetOption filetype=justfile %{
+ add-highlighter window/justfile ref justfile
+ hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/justfile }
+}
+
+
+provide-module justfile %{
+
+# Indentation
+# ‾‾‾‾‾‾‾‾‾‾‾
+
+define-command -hidden justfile-trim-indent %{
+ evaluate-commands -no-hooks -draft -itersel %{
+ execute-keys x
+ # remove trailing white spaces
+ try %{ execute-keys -draft s \h + $ d }
+ }
+}
+
+define-command -hidden just-insert-on-new-line %{
+ # copy '#' comment prefix and following white spaces
+ try %{ execute-keys -draft k x s ^\h*//\h* y jgh P }
+}
+
+define-command -hidden just-indent-on-new-line %{
+ evaluate-commands -draft -itersel %{
+ # preserve previous line indent
+ try %{ execute-keys -draft K }
+ # cleanup trailing white spaces on previous line
+ try %{ execute-keys -draft kx s \h+$ "_d }
+ }
+}
+
+# Highlighters
+# ‾‾‾‾‾‾‾‾‾‾‾‾
+
+add-highlighter shared/justfile regions
+
+add-highlighter shared/justfile/content default-region group
+add-highlighter shared/justfile/content/recipe regex '^@?([\w-]+)([^\n]*):(?!=)([^\n]*)' 1:function 2:meta 3:keyword
+add-highlighter shared/justfile/content/assignments regex ^([\w-]+\h*:=\h*[^\n]*) 1:meta
+add-highlighter shared/justfile/content/operator regex '((^@|:=|=|\+|\(|\)))' 1:operator
+add-highlighter shared/justfile/content/strings regions
+add-highlighter shared/justfile/content/strings/double region '"' (? ': trigger-user-hook donehop'
map window normal , ': trigger-user-hook donehop,'
hook -once window User donehop %{
+ hop-clear-cursor
eval "ui-scrolloff-enable"
try %{ ui-wrap-enable }
unmap window normal
@@ -37,3 +76,4 @@ map -docstring %{
map -docstring %{
Hop mode
} global normal ': enter-user-mode hop'
+~
diff --git a/.config/kak/autoload/lsp.kak b/.config/kak/autoload/lsp.kak
index fd17d343..07156284 100644
--- a/.config/kak/autoload/lsp.kak
+++ b/.config/kak/autoload/lsp.kak
@@ -1,5 +1,6 @@
# load plugin
eval %sh{kak-lsp}
+# eval %sh{kak-lsp-diags}
# mappings
map global user l ': enter-user-mode lsp' -docstring 'LSP mode'
@@ -24,7 +25,7 @@ define-command -hidden -override lsp-hide-code-actions %{
set-option global lsp_debug false
# list of filetypes for which LSP will be activated in the window scope
-declare-option str-list lsp_filetypes python go rust bash fish c cpp typst markdown yaml json jsonc bash sh
+declare-option str-list lsp_filetypes python go rust bash fish c cpp typst markdown yaml json jsonc bash sh typescript javascript latex
declare-option -hidden bool inlay_enabled false
@@ -48,21 +49,40 @@ define-command -hidden inlay-toggle %{
}
}
-declare-option -hidden bool diagnostics_enabled false
-define-command -hidden diagnostics-on %{
+declare-option -hidden bool inlay_diagnostics_enabled false
+define-command -hidden inlay-diagnostics-on %{
lsp-inlay-diagnostics-enable window
- set-option window diagnostics_enabled true
+ set-option window inlay_diagnostics_enabled true
}
-define-command -hidden diagnostics-off %{
+define-command -hidden inlay-diagnostics-off %{
lsp-inlay-diagnostics-disable window
- set-option window diagnostics_enabled false
+ set-option window inlay_diagnostics_enabled false
}
-define-command -hidden diagnostics-toggle %{
+define-command -hidden inlay-diagnostics-toggle %{
evaluate-commands %sh{
- if [ "$kak_opt_diagnostics_enabled" = "true" ]; then
- echo "diagnostics-off"
+ if [ "$kak_opt_inlay_diagnostics_enabled" = "true" ]; then
+ echo "inlay-diagnostics-off"
else
- echo "diagnostics-on"
+ echo "inlay-diagnostics-on"
+ fi
+ }
+}
+
+declare-option -hidden bool inline_diagnostics_enabled true
+define-command -hidden inline-diagnostics-on %{
+ lsp-inline-diagnostics-enable window
+ set-option window inline_diagnostics_enabled true
+}
+define-command -hidden inline-diagnostics-off %{
+ lsp-inline-diagnostics-disable window
+ set-option window inline_diagnostics_enabled false
+}
+define-command inline-diagnostics-toggle %{
+ evaluate-commands %sh{
+ if [ "$kak_opt_inline_diagnostics_enabled" = "true" ]; then
+ echo "inline-diagnostics-off"
+ else
+ echo "inline-diagnostics-on"
fi
}
}
@@ -76,14 +96,11 @@ define-command -hidden lsp-filetype-hooks-update %{
# commands to execute for lsp window settings
lsp-enable-window
inlay-on
- try %{
- # only map to UI mode if that module is available
- map -docstring 'toggle inlay hints' window ui h ': inlay-toggle'
- map -docstring 'toggle inlay diagnostics' window ui d ': diagnostics-toggle'
- } catch %{
- map -docstring 'toggle inlay hints' window lsp ': inlay-toggle'
- map -docstring 'toggle inlay diagnostics' window lsp ': diagnostics-toggle'
- }
+ # only map to UI mode if that module is available
+ map -docstring 'toggle inlay hints' window ui h ': inlay-toggle'
+ map -docstring 'toggle inlay diagnostics' window ui d ': inlay-diagnostics-toggle'
+ map -docstring 'toggle inline diagnostics' window ui e ': inline-diagnostics-toggle'
+ trigger-user-hook lsp-enabled
}
}
lsp-filetype-hooks-update
@@ -102,7 +119,51 @@ hook -group lsp-filetype-python global BufSetOption filetype=python %{
[basedpyright-langserver.settings.basedpyright.analysis]
typeCheckingMode = "standard"
inlayHints.genericTypes = true
+ }
+}
+remove-hooks global lsp-filetype-latex
+hook -group lsp-filetype-latex global BufSetOption filetype=latex %{
+ set-option buffer lsp_servers %{
+ [texlab]
+ root_globs = [".git", ".hg"]
+ [texlab.settings.texlab]
+ # See https://github.com/latex-lsp/texlab/wiki/Configuration
+ #
+ # Preview configuration for zathura with SyncTeX search.
+ # For other PDF viewers see https://github.com/latex-lsp/texlab/wiki/Previewing
+ build.onSave = true
+ forwardSearch.executable = "zathura"
+ forwardSearch.args = [
+ "%p",
+ "--synctex-forward", # Support texlab-forward-search
+ "%l:1:%f",
+ "--synctex-editor-command", # Inverse search: use Control+Left-Mouse-Button to jump to source.
+ """
+ sh -c '
+ echo "
+ evaluate-commands -client %%opt{texlab_client} %%{
+ evaluate-commands -try-client %%opt{jumpclient} %%{
+ edit -- %%{input} %%{line}
+ }
+ }
+ " | kak -p $kak_session
+ '
+ """,
+ ]
+ }
+}
+
+remove-hooks global lsp-filetype-javascript
+hook -group lsp-filetype-javascript global BufSetOption filetype=(?:javascript|typescript) %{
+ set-option buffer lsp_servers %{
+ [typescript-language-server]
+ root_globs = ["package.json", "tsconfig.json", "jsconfig.json", ".git", ".hg"]
+ args = ["--stdio"]
+ settings_section = "_"
+ [typescript-language-server.settings._]
+ # quotePreference = "double"
+ # typescript.format.semicolons = "insert"
}
}
@@ -115,3 +176,69 @@ hook -group lsp-filetype-fish global BufSetOption filetype=fish %{
command = "/home/fic/.config/kak/scripts/fish-lsp.fish"
}
}
+
+remove-hooks global lsp-filetype-markdown
+hook -group lsp-filetype-markdown global BufSetOption filetype=markdown %{
+ set-option buffer lsp_servers %{
+ [marksman]
+ root_globs = [".marksman.toml", ".git"]
+ args = ["server"]
+
+ [harper-ls]
+ root_globs = ["*"]
+ args = ["--stdio"]
+ command = "harper-ls"
+ [harper-ls.settings.harper-ls.linters]
+ LongSentences = false
+ }
+}
+
+remove-hooks global lsp-filetype-typst
+hook -group lsp-filetype-typst global BufSetOption filetype=typst %{
+ set-option buffer lsp_servers %{
+ [tinymist]
+ root_globs = [".git", ".hg"]
+ args = ["lsp"]
+ settings_section = "_"
+ [tinymist.settings._]
+ # See https://myriad-dreamin.github.io/tinymist/configurations.html
+ exportPdf = "never"
+ # exportPdf = "onDocumentHasTitle"
+ formatterMode = "typstyle"
+ previewFeature = "disable"
+
+ [harper-ls]
+ root_globs = ["*"]
+ args = ["--stdio"]
+ command = "harper-ls"
+ [harper-ls.settings.harper-ls.linters]
+ LongSentences = false
+ }
+ set-option -add buffer lsp_servers "formatterPrintWidth = %opt{autowrap_column}"
+}
+
+# # can be empty, global, or file
+# declare-option -hidden str harper_add ""
+# define-command -hidden harper-add -params 1 %{
+# set-option window harper_add %arg{1}
+# lsp-code-actions -auto-single
+# }
+
+# # can override this to customize what's rendered in the menu
+# # Each code action is two args: its name, and the corresponding command
+# define-command -override -hidden lsp-perform-code-action -params 1.. -docstring "Called on :lsp-code-actions" %{
+# evaluate-commands %sh{
+# # harper specific filtering
+# if printf '%s' "$kak_opt_lsp_servers" | grep -q 'harper-ls'; then
+# if [ "$kak_opt_harper_add" = "global" ]; then
+# # filter and keep only
+# echo "echo -debug 'harper adding global'"
+# fi
+# fi
+# echo "echo -debug dumping $# code actions args:"
+# echo "echo -debug %arg{@}"
+
+# }
+# lsp-menu %arg{@}
+# }
+
diff --git a/.config/kak/autoload/notes.kak b/.config/kak/autoload/notes.kak
new file mode 100644
index 00000000..4469adac
--- /dev/null
+++ b/.config/kak/autoload/notes.kak
@@ -0,0 +1,287 @@
+provide-module notes %~
+# Global directory for notes.
+declare-option str notes_root_dir "%sh{ echo $HOME/notes/kak }"
+
+# Active directory.
+#
+# Global directory (`notes_root_dir`) or a local override.
+declare-option str notes_active_dir "%opt{notes_root_dir}"
+
+declare-option str notes_sym_todo 'TODO'
+declare-option str notes_sym_wip 'WIP'
+declare-option str notes_sym_done 'DONE'
+declare-option str notes_sym_wontdo 'WONTDO'
+declare-option str notes_sym_idea 'IDEA'
+declare-option str notes_sym_question 'QUESTION'
+declare-option str notes_sym_hold 'HOLD'
+declare-option str notes_sym_review 'REVIEW'
+declare-option str notes_find 'fd -t file .md'
+declare-option -hidden str notes_tasks_list_current_line
+declare-option -hidden str notes_journal_now
+
+# Main notes mode.
+declare-user-mode notes
+
+# Mode to edit tasks.
+declare-user-mode notes-tasks
+
+# Mode to list tasks.
+declare-user-mode notes-tasks-list
+
+# Mode to navigate journal.
+declare-user-mode notes-journal-nav
+
+# Mode to navigate journal (last journals).
+declare-user-mode notes-journal-nav-last
+
+set-face global notes_todo green
+set-face global notes_wip blue
+set-face global notes_done black
+set-face global notes_wontdo black
+set-face global notes_idea green
+set-face global notes_question cyan
+set-face global notes_hold red
+set-face global notes_review yellow
+
+set-face global notes_issue cyan+u
+set-face global notes_subtask_uncheck green
+set-face global notes_subtask_check black
+set-face global notes_tag blue+i
+
+# Open the daily journal.
+define-command notes-journal-open -docstring 'open daily journal' %{
+ nop %sh{
+ mkdir -p "$kak_opt_notes_active_dir/journal/$(date +%Y/%b)"
+ }
+
+ evaluate-commands %{
+ edit "%opt{notes_active_dir}/journal/%sh{ date '+%Y/%b/%a %d' }.md"
+ set-option buffer notes_journal_now %sh{ date }
+ }
+}
+
+# Open a journal relative to today.
+define-command -hidden notes-journal-open-rel -params -1 %{
+ nop %sh{
+ mkdir -p "$kak_opt_notes_active_dir/journal/$(date -d ""$kak_opt_notes_journal_now $1"" +%Y/%b)"
+ }
+
+ evaluate-commands %{
+ edit -existing "%opt{notes_active_dir}/journal/%sh{ date -d ""$kak_opt_notes_journal_now $1"" ""+%Y/%b/%a %d"" }.md"
+ set-option buffer notes_journal_now %sh{ date -d """$kak_opt_notes_journal_now $1""" }
+ }
+}
+
+# Open a note by prompting the user with a menu.
+define-command notes-open -docstring 'open note' %{
+ prompt -menu -shell-script-candidates "$kak_opt_notes_find $kak_opt_notes_active_dir/notes" 'open note:' %{
+ edit %sh{
+ echo "${kak_text%.md}.md"
+ }
+ }
+}
+
+# Create a new note by prompting the user for its text.
+define-command notes-new-note -docstring 'new note' %{
+ prompt note: %{
+ edit %sh{
+ echo "$kak_opt_notes_active_dir/notes/${kak_text%.md}.md"
+ }
+ }
+}
+
+# Archive a note by prompting the user for which note to operate on.
+define-command notes-archive-note -docstring 'archive note' %{
+ prompt -menu -shell-script-candidates "$kak_opt_notes_find $kak_opt_notes_active_dir/notes" archive: %{
+ nop %sh{
+ mkdir -p "$kak_opt_notes_active_dir/archives"
+ mv "$kak_text" "$kak_opt_notes_active_dir/archives/"
+ }
+ }
+}
+
+# Prompt the user to pick and open an archived note.
+define-command notes-archive-open -docstring 'open archive' %{
+ prompt -menu -shell-script-candidates "$kak_opt_notes_find $kak_opt_notes_active_dir/archives" 'open archive:' %{
+ edit %sh{
+ echo "${kak_text%.md}.md"
+ }
+ }
+}
+
+# Capture a new note.
+define-command notes-capture -docstring 'capture' %{
+ prompt capture: %{
+ nop %sh{
+ echo -e "> $(date '+%a %b %d %Y, %H:%M:%S')\n$kak_text\n" >> "$kak_opt_notes_active_dir/capture.md"
+ }
+ }
+}
+
+# Open the capture file.
+define-command notes-open-capture -docstring 'open capture' %{
+ edit "%opt{notes_active_dir}/capture.md"
+}
+
+# Switch the status of a note to the input parameter.
+define-command notes-task-switch-status -params 1 -docstring 'switch task' %{
+ execute-keys -draft "gife_c%arg{1}"
+}
+
+# Open a GitHub issue. This requires a specific formatting of the file.
+define-command notes-task-gh-open-issue -docstring 'open GitHub issue' %{
+ evaluate-commands -save-regs 'il' %{
+ try %{
+ execute-keys -draft 'w"iy'
+ execute-keys -draft '%sgithub_project: ;_"ly'
+ nop %sh{
+ open "https://github.com/$kak_reg_l/issues/$kak_reg_i"
+ }
+ }
+ }
+}
+
+define-command -hidden notes-tasks-list-by-regex -params 1 -docstring 'list tasks by status' %{
+ edit -scratch *notes-tasks-list*
+ unset-option buffer notes_tasks_list_current_line
+ execute-keys "%%d|rg -n --column -e '%arg{1}' '%opt{notes_active_dir}/notes' '%opt{notes_active_dir}/journal' '%opt{notes_active_dir}/capture.md'|sortgg"
+}
+
+# List all tasks.
+define-command notes-tasks-list-all -docstring 'list all tasks' %{
+ notes-tasks-list-by-regex "%opt{notes_sym_todo}|%opt{notes_sym_wip}|%opt{notes_sym_done}|%opt{notes_sym_wontdo}|%opt{notes_sym_idea}|%opt{notes_sym_question}|%opt{notes_sym_hold}"
+}
+
+# Command executed when pressing in a *notes-tasks-list* buffer.
+define-command -hidden notes-tasks-list-open %{
+ set-option buffer notes_tasks_list_current_line %val{cursor_line}
+ execute-keys -with-hooks -save-regs 'flc' 'giT:"fyllT:"lyllT:"cy:edit "%reg{f}" %reg{l} %reg{c}'
+}
+
+# Run a grepper with the provided arguments as search query.
+define-command -hidden notes-grepcmd -params 2 %{
+ # Initial implementation based on rg .
+ execute-keys ":grep %arg{2} %arg{1}"
+}
+
+# Prompt the user for terms to search in notes, journals, archives and the
+# capture file.
+define-command notes-search -docstring 'search notes' %{
+ prompt 'search notes:' %{
+ notes-grepcmd "%opt{notes_active_dir}" "%val{text}"
+ }
+}
+
+# Synchronize notes remotely.
+define-command notes-sync -docstring 'synchronize notes' %{
+ # First, we always check-in new modifications; then, we check whether we have anything else to send
+ info -title 'notes' 'starting synchronizing…'
+
+ nop %sh{
+ cd $kak_opt_notes_active_dir
+ git fetch --prune origin
+ git rebase --autostash origin/master
+ git add -A .
+ git commit -m "$(date +'Sync update %a %b %d %Y')"
+ git push origin
+ }
+
+ info -title 'notes' 'finished synchronizing'
+}
+
+# Toggle overriding the active directory with pwd and vice versa.
+define-command notes-override-active-dir -docstring 'override the active directory with PWD' %{
+ set-option global notes_active_dir %sh{
+ dir=$(pwd)
+ if [ "$kak_opt_notes_active_dir" == "$dir" ]; then
+ echo "$kak_opt_notes_root_dir"
+ else
+ echo "$dir"
+ fi
+ }
+
+ info -title notes "active dir: %opt{notes_active_dir}"
+}
+
+add-highlighter shared/notes-tasks group
+add-highlighter shared/notes-tasks/todo regex "(%opt{notes_sym_todo})" 1:notes_todo
+add-highlighter shared/notes-tasks/wip regex "(%opt{notes_sym_wip})" 1:notes_wip
+add-highlighter shared/notes-tasks/done regex "(%opt{notes_sym_done})" 1:notes_done
+add-highlighter shared/notes-tasks/wontdo regex "(%opt{notes_sym_wontdo})" 1:notes_wontdo
+add-highlighter shared/notes-tasks/idea regex "(%opt{notes_sym_idea})" 1:notes_idea
+add-highlighter shared/notes-tasks/question regex "(%opt{notes_sym_question})" 1:notes_question
+add-highlighter shared/notes-tasks/hold regex "(%opt{notes_sym_hold})" 1:notes_hold
+add-highlighter shared/notes-tasks/review regex "(%opt{notes_sym_review})" 1:notes_review
+add-highlighter shared/notes-tasks/issue regex " (#[0-9]+)" 1:notes_issue
+add-highlighter shared/notes-tasks/subtask-uncheck regex "-\s* (\[ \])[^\n]*" 1:notes_subtask_uncheck
+add-highlighter shared/notes-tasks/subtask-check regex "-\s* (\[x\])\s*([^\n]*)"\
+ 1:notes_subtask_check
+
+add-highlighter shared/notes-tasks-list group
+add-highlighter shared/notes-tasks-list/path regex "^((?:\w:)?[^:\n]+):(\d+):(\d+)?" 1:green 2:blue 3:blue
+add-highlighter shared/notes-tasks-list/current-line line %{%opt{notes_tasks_list_current_line}} default+b
+
+map global user o ':enter-user-mode notes' -docstring 'notes'
+
+map global notes A ':notes-archive-note' -docstring 'archive note'
+map global notes a ':notes-archive-open' -docstring 'open archived note'
+map global notes C ':notes-capture' -docstring 'capture'
+map global notes c ':notes-open-capture' -docstring 'open capture'
+map global notes j ':notes-journal-open' -docstring 'open journal'
+map global notes J ':enter-user-mode notes-journal-nav' -docstring 'navigate journals'
+map global notes l ':enter-user-mode notes-tasks-list' -docstring 'tasks list'
+map global notes N ':notes-new-note' -docstring 'new note'
+map global notes n ':notes-open' -docstring 'open note'
+map global notes / ':notes-search' -docstring 'search in notes'
+map global notes S ':notes-sync' -docstring 'synchronize notes'
+map global notes t ':enter-user-mode notes-tasks' -docstring 'tasks'
+map global notes z ':notes-override-active-dir' -docstring 'switch notes dir with PWD'
+
+map global notes-journal-nav l ':enter-user-mode notes-journal-nav-last' -docstring 'last…'
+map global notes-journal-nav d ':notes-journal-open-rel "-1 day"' -docstring 'day before'
+map global notes-journal-nav D ':notes-journal-open-rel "+1 day"' -docstring 'day after'
+map global notes-journal-nav w ':notes-journal-open-rel "-1 week"' -docstring 'week before'
+map global notes-journal-nav W ':notes-journal-open-rel "+1 week"' -docstring 'week after'
+map global notes-journal-nav m ':notes-journal-open-rel "-1 month"' -docstring 'month before'
+map global notes-journal-nav M ':notes-journal-open-rel "+1 month"' -docstring 'month after'
+
+map global notes-journal-nav-last m ':notes-journal-open-rel "last monday"' -docstring 'monday'
+map global notes-journal-nav-last t ':notes-journal-open-rel "last tuesday"' -docstring 'tuesday'
+map global notes-journal-nav-last w ':notes-journal-open-rel "last wednesday"' -docstring 'wednesday'
+map global notes-journal-nav-last h ':notes-journal-open-rel "last thursday"' -docstring 'thursday'
+map global notes-journal-nav-last f ':notes-journal-open-rel "last friday"' -docstring 'friday'
+map global notes-journal-nav-last T ':notes-journal-open-rel "last saturday"' -docstring 'saturday'
+map global notes-journal-nav-last S ':notes-journal-open-rel "last sunday"' -docstring 'sunday'
+
+map global notes-tasks-list a ":notes-tasks-list-all" -docstring 'list all tasks'
+map global notes-tasks-list d ":notes-tasks-list-by-regex %opt{notes_sym_done}" -docstring 'list done tasks'
+map global notes-tasks-list h ":notes-tasks-list-by-regex %opt{notes_sym_hold}" -docstring 'list hold tasks'
+map global notes-tasks-list i ":notes-tasks-list-by-regex %opt{notes_sym_idea}" -docstring 'list ideas'
+map global notes-tasks-list l ":notes-tasks-list-by-regex '\ :[^:]+:'" -docstring 'list tasks by labels'
+map global notes-tasks-list n ":notes-tasks-list-by-regex %opt{notes_sym_wontdo}" -docstring 'list wontdo tasks'
+map global notes-tasks-list q ":notes-tasks-list-by-regex %opt{notes_sym_question}" -docstring 'list questions'
+map global notes-tasks-list r ":notes-tasks-list-by-regex %opt{notes_sym_review}" -docstring 'list reviews'
+map global notes-tasks-list t ":notes-tasks-list-by-regex %opt{notes_sym_todo}" -docstring 'list todo tasks'
+map global notes-tasks-list w ":notes-tasks-list-by-regex %opt{notes_sym_wip}" -docstring 'list wip tasks'
+
+hook -group notes-tasks global WinCreate \*notes-tasks-list\* %{
+ map buffer normal '' ':notes-tasks-list-open'
+ add-highlighter window/ ref notes-tasks
+ add-highlighter window/ ref notes-tasks-list
+}
+
+hook -group notes-tasks global WinCreate .*\.md %{
+ add-highlighter window/ ref notes-tasks
+
+ map window notes-tasks d ":notes-task-switch-status %opt{notes_sym_done}" -docstring 'switch task to done'
+ map window notes-tasks h ":notes-task-switch-status %opt{notes_sym_hold}" -docstring 'switch task to hold'
+ map window notes-tasks i ":notes-task-switch-status %opt{notes_sym_idea}" -docstring 'switch task to idea'
+ map window notes-tasks n ":notes-task-switch-status %opt{notes_sym_wontdo}" -docstring 'switch task to wontdo'
+ map window notes-tasks q ":notes-task-switch-status %opt{notes_sym_question}" -docstring 'switch task to question'
+ map window notes-tasks ":notes-task-gh-open-issue" -docstring 'open GitHub issue'
+ map window notes-tasks r ":notes-task-switch-status %opt{notes_sym_review}" -docstring 'switch task to review'
+ map window notes-tasks t ":notes-task-switch-status %opt{notes_sym_todo}" -docstring 'switch task to todo'
+ map window notes-tasks w ":notes-task-switch-status %opt{notes_sym_wip}" -docstring 'switch task to wip'
+}
+
+~
diff --git a/.config/kak/autoload/plugins.kak b/.config/kak/autoload/plugins.kak
index 4fd24c62..399bae9d 100644
--- a/.config/kak/autoload/plugins.kak
+++ b/.config/kak/autoload/plugins.kak
@@ -95,7 +95,7 @@ bundle-noload kakoune-text-objects https://github.com/Delapouite/kakoune-text-ob
bundle smarttab.kak https://github.com/andreyorst/smarttab.kak %{
require-module smarttab
set-option global softtabstop 2
- hook global BufCreate .* %{
+ hook global WinSetOption filetype=.* %{
editorconfig-load
autoconfigtab
}
diff --git a/.config/kak/autoload/stdlib/detection/editorconfig.kak b/.config/kak/autoload/stdlib/detection/editorconfig.kak
deleted file mode 120000
index cebb754c..00000000
--- a/.config/kak/autoload/stdlib/detection/editorconfig.kak
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/kak/rc/detection/editorconfig.kak
\ No newline at end of file
diff --git a/.config/kak/autoload/stdlib/filetype/just.kak b/.config/kak/autoload/stdlib/filetype/just.kak
deleted file mode 120000
index 60c8fa04..00000000
--- a/.config/kak/autoload/stdlib/filetype/just.kak
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/kak/rc/filetype/just.kak
\ No newline at end of file
diff --git a/.config/kak/kakrc b/.config/kak/kakrc
index 68dcb779..f673bb65 100644
--- a/.config/kak/kakrc
+++ b/.config/kak/kakrc
@@ -1,12 +1,14 @@
evaluate-commands %sh{ kak-tree-sitter -dks --init $kak_session }
evaluate-commands %sh{kak-popup init}
colorscheme ashen
+require-module hop-kak
require-module fishr
require-module surround
require-module ficgrep
require-module byline
require-module spell
require-module title-bar
+require-module notes
set-option global scrolloff 3,3
require-module ui-mode
@@ -93,25 +95,16 @@ map -docstring 'case insensitive backward extend-search' global user '' L"
map -docstring 'Extend to file end' global user n "gjl"
-# Zathura pdf preview only for Typst files
-
-hook global WinSetOption filetype=typst %{
- define-command -docstring %{
- Spawns a Zathura pdf preview and Typst watcher for the currently open Typst file
- } typst %{
- nop %sh{
- {
- "$kak_config/scripts/kak-typ-zathura.fish" -k -w "$kak_buffile" "$kak_client_pid"
- } > /dev/null 2>&1 < /dev/null &
- }
- }
-}
-
define-command -docstring "Create a scratch buffer" scratch %{
edit -scratch
}
+
alias global s scratch
+define-command -params 1 -docstring "Set buffer filetype" filetype %{
+ set-option buffer filetype %arg{1}
+}
+
define-command -docstring "New terminal in cwd" cwd-terminal %{
terminal fish
}
@@ -156,12 +149,21 @@ define-command -override -hidden consume %{
}
}
+define-command terminal-consume %{
+ terminal dash -c 'niri msg action consume-or-expel-window-left; exec fish'
+}
+
+alias global tc terminal-consume
+
define-command -docstring %{
Create a new client in vertial split
-} newv %{
+} new-consume %{
new consume
}
+alias global nc new-consume
+alias global n new
+
# jumplist
map -docstring 'jump forward' global normal
@@ -169,3 +171,22 @@ map -docstring 'save to jumplist' global normal
# selection saving
map -docstring 'add selection' global normal Y a
+
+define-command -docstring 'open popup shell' popup-shell %{
+ popup fish
+}
+alias global pp popup-shell
+
+map -docstring 'popup shell' global user . ': popup-shell'
+
+# hook -once global ClientCreate .* %{
+# evaluate-commands %sh{
+# if [ "$kak_buflist" != "*debug* *scratch*" ]; then
+# echo "delete-buffer *scratch*"
+# else
+# echo "echo -debug dumping buffers"
+# echo "echo -debug %val{buflist}"
+# fi
+# }
+# }
+
diff --git a/.config/kak/scripts/lsp-diags.py b/.config/kak/scripts/lsp-diags.py
new file mode 120000
index 00000000..732dc5e5
--- /dev/null
+++ b/.config/kak/scripts/lsp-diags.py
@@ -0,0 +1 @@
+/home/fic/dev/kak-lsp-diags/lsp-diags.py
\ No newline at end of file
diff --git a/.config/kak/scripts/lsp-diags_.py b/.config/kak/scripts/lsp-diags_.py
new file mode 100755
index 00000000..dd548ed2
--- /dev/null
+++ b/.config/kak/scripts/lsp-diags_.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+
+# pyright: basic, reportUnusedCallResult=false
+
+import atexit
+import sys
+import os
+import tempfile
+import signal
+
+Position = tuple[int, int]
+SpecList = list[tuple[Position, Position]]
+
+diagnostics: SpecList = []
+
+
+def parse_specs(data: str):
+ parsed: SpecList = []
+ for entry in data.strip().split():
+ if not entry or len(entry) < 9:
+ continue
+ range_part, _ = entry.split("|", 1)
+ start_str, end_str = range_part.split(",")
+ sl, sc = map(int, start_str.split("."))
+ el, ec = map(int, end_str.split("."))
+ parsed.append(((sl, sc), (el, ec)))
+ return parsed
+
+
+def is_cursor_in_any(cursor: Position, diagnostics: SpecList) -> bool:
+ cl, cc = cursor
+ for (sl, sc), (el, ec) in diagnostics:
+ if cl < sl or cl > el:
+ continue
+ if sl == el:
+ if cl == sl and sc <= cc <= ec:
+ return True
+ elif cl == sl:
+ if cc >= sc:
+ return True
+ elif cl == el:
+ if cc <= ec:
+ return True
+ elif sl < cl < el:
+ return True
+ return False
+
+
+def cleanup(inp: str, outp: str, dir: str):
+ # subprocess.run(["notify-send", "cleanup runs"])
+ try:
+ os.remove(inp)
+ os.remove(outp)
+ os.rmdir(dir)
+ except FileNotFoundError:
+ pass
+
+
+def gen_kakoune_output(inp: str, outp: str) -> str:
+ return f"declare-option -hidden str diagpipe_in {inp}\ndeclare-option -hidden str diagpipe_out {outp}"
+
+
+def daemonize(inp: str, outp: str, dir: str):
+ # fork and exit parent
+ if os.fork() > 0:
+ sys.exit(0)
+ # new session
+ os.setsid()
+ if os.fork() > 0:
+ # exit first child
+ sys.exit(0)
+
+ # redirect IO to /dev/null
+ with open("/dev/null", "rb", 0) as dn:
+ os.dup2(dn.fileno(), sys.stdin.fileno())
+ with open("/dev/null", "ab", 0) as dn:
+ os.dup2(dn.fileno(), sys.stdout.fileno())
+ os.dup2(dn.fileno(), sys.stderr.fileno())
+ _ = atexit.register(lambda: cleanup(inp, outp, dir))
+
+ def on_exit(*_):
+ # cleanup(inp, outp, dir)
+ sys.exit(0)
+
+ signal.signal(signal.SIGTERM, on_exit)
+ signal.signal(signal.SIGINT, on_exit)
+
+
+def main():
+ # subprocess.run(["notify-send", "begin loop"])
+ # create unique directory and names
+ fifo_dir = tempfile.mkdtemp(prefix="diagpipe-")
+ in_path = os.path.join(fifo_dir, "in")
+ out_path = os.path.join(fifo_dir, "out")
+
+ # create fifos
+ os.mkfifo(in_path)
+ os.mkfifo(out_path)
+
+ output = gen_kakoune_output(in_path, out_path)
+ print(output)
+ sys.stdout.flush()
+ daemonize(in_path, out_path, fifo_dir)
+
+ with open(in_path, "r") as infile, open(out_path, "w") as outfile:
+ diagnostics: SpecList = []
+ while True:
+ line = infile.readline()
+ if not line:
+ continue
+ line = line.strip()
+ assert isinstance(line, str)
+ # # subprocess.run(["notify-send", f"Received command: {line}"])
+ if line.startswith("set "):
+ # subprocess.run(["notify-send", f"Received set: {line}"])
+ _, payload = line.split(" ", 1)
+ diagnostics = parse_specs(payload)
+ _ = outfile.write("ok\n")
+ outfile.flush()
+ elif line.startswith("query "):
+ _, pos = line.split(" ", 1)
+ l, c = map(int, pos.strip().split())
+ result = is_cursor_in_any((l, c), diagnostics)
+ _ = outfile.write("true\n" if result else "false\n")
+ outfile.flush()
+ elif line.startswith("exit"):
+ # subprocess.run(["notify-send", "exit received"])
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/.config/nvchecker/new_ver.json b/.config/nvchecker/new_ver.json
index 4998ee2f..7d4ca670 100644
--- a/.config/nvchecker/new_ver.json
+++ b/.config/nvchecker/new_ver.json
@@ -2,14 +2,14 @@
"version": 2,
"data": {
"codebook": {
- "version": "0.3.0",
- "gitref": "refs/tags/v0.3.0",
- "url": "https://github.com/blopker/codebook/releases/tag/v0.3.0"
+ "version": "0.3.2",
+ "gitref": "refs/tags/v0.3.2",
+ "url": "https://github.com/blopker/codebook/releases/tag/v0.3.2"
},
"iwe": {
- "version": "iwe-v0.0.32",
- "gitref": "refs/tags/iwe-v0.0.32",
- "url": "https://github.com/iwe-org/iwe/releases/tag/iwe-v0.0.32"
+ "version": "iwe-v0.0.33",
+ "gitref": "refs/tags/iwe-v0.0.33",
+ "url": "https://github.com/iwe-org/iwe/releases/tag/iwe-v0.0.33"
},
"kak-tree-sitter": {
"version": "2.0.0",
diff --git a/.config/nvchecker/old_ver.json b/.config/nvchecker/old_ver.json
index 4998ee2f..7d4ca670 100644
--- a/.config/nvchecker/old_ver.json
+++ b/.config/nvchecker/old_ver.json
@@ -2,14 +2,14 @@
"version": 2,
"data": {
"codebook": {
- "version": "0.3.0",
- "gitref": "refs/tags/v0.3.0",
- "url": "https://github.com/blopker/codebook/releases/tag/v0.3.0"
+ "version": "0.3.2",
+ "gitref": "refs/tags/v0.3.2",
+ "url": "https://github.com/blopker/codebook/releases/tag/v0.3.2"
},
"iwe": {
- "version": "iwe-v0.0.32",
- "gitref": "refs/tags/iwe-v0.0.32",
- "url": "https://github.com/iwe-org/iwe/releases/tag/iwe-v0.0.32"
+ "version": "iwe-v0.0.33",
+ "gitref": "refs/tags/iwe-v0.0.33",
+ "url": "https://github.com/iwe-org/iwe/releases/tag/iwe-v0.0.33"
},
"kak-tree-sitter": {
"version": "2.0.0",
diff --git a/.config/nvchecker/old_ver.json~ b/.config/nvchecker/old_ver.json~
index 9b029329..95f09db9 100644
--- a/.config/nvchecker/old_ver.json~
+++ b/.config/nvchecker/old_ver.json~
@@ -7,9 +7,9 @@
"url": "https://github.com/blopker/codebook/releases/tag/v0.3.0"
},
"iwe": {
- "version": "iwe-v0.0.31",
- "gitref": "refs/tags/iwe-v0.0.31",
- "url": "https://github.com/iwe-org/iwe/releases/tag/iwe-v0.0.31"
+ "version": "iwe-v0.0.33",
+ "gitref": "refs/tags/iwe-v0.0.33",
+ "url": "https://github.com/iwe-org/iwe/releases/tag/iwe-v0.0.33"
},
"kak-tree-sitter": {
"version": "2.0.0",
diff --git a/.config/qutebrowser/autoconfig.yml b/.config/qutebrowser/autoconfig.yml
index da8df7b7..4a216103 100644
--- a/.config/qutebrowser/autoconfig.yml
+++ b/.config/qutebrowser/autoconfig.yml
@@ -8,3 +8,7 @@ config_version: 2
settings:
content.javascript.clipboard:
https://github.com: access-paste
+ statusbar.show:
+ global: always
+ tabs.position:
+ global: top
diff --git a/.config/qutebrowser/config.py b/.config/qutebrowser/config.py
index 0771ed53..1b337b5d 100644
--- a/.config/qutebrowser/config.py
+++ b/.config/qutebrowser/config.py
@@ -22,8 +22,6 @@ c.completion.open_categories = [
"filesystem",
]
-# c.hints.chars = "tnserigm"
-# c.hints.chars = "tnseripldh"
c.hints.chars = "tnserigmao"
# dark mode
@@ -36,14 +34,15 @@ c.colors.webpage.preferred_color_scheme = "dark"
# searches
c.url.searchengines["DEFAULT"] = "https://www.startpage.com/sp/search?query={}"
-c.url.searchengines["!d"] = "https://duckduckgo.com/?q={}"
-c.url.searchengines["!aw"] = "https://wiki.archlinux.org/?search={}"
-c.url.searchengines["!g"] = (
+c.url.searchengines["d"] = "https://duckduckgo.com/?q={}"
+c.url.searchengines["aw"] = "https://wiki.archlinux.org/?search={}"
+c.url.searchengines["g"] = (
"http://www.google.com/search?hl=en&source=hp&ie=ISO-8859-l&q={}"
)
c.url.searchengines["ap"] = "https://www.archlinux.org/packages/?sort=&q={}"
-# with config.pattern("chatgpt.com") as p:
-# p.bindings.commands["normal"][""] = "click-element css main"
+c.url.searchengines["w"] = (
+ "https://en.wikipedia.org/w/index.php?title=Special:Search&search={}"
+)
config.bind(
"",
"mode-leave ;; jseval -q document.activeElement.blur()",
@@ -58,6 +57,9 @@ config.bind(
sets = {
"normal": [
+ ["tT", "config-cycle tabs.position top left"],
+ ["sH", "config-cycle statusbar.show always never"],
+ ["\\", "mode-enter passthrough"],
["m", "scroll left"],
["n", "scroll down"],
["e", "scroll up"],
@@ -72,7 +74,12 @@ sets = {
["k", "quickmark-save"],
["J", "search-prev"],
["j", "search-next"],
- ["", "hint links spawn --detach mpv {hint-url}"],
+ [
+ ";/",
+ "hint links spawn --detach mpv --force-window --quiet --keep-open=yes --ytdl {hint-url}",
+ ],
+ ["", "spawn --userscript view_in_mpv"],
+ # ["", "hint links spawn --userscript view_in_mpv"],
["gm", "tab-focus 1"],
["gi", "tab-focus -1"],
["gN", "tab-move +"],
@@ -140,6 +147,14 @@ ashen = {
"g_12": "#151515",
}
+c.tabs.padding = {"top": 5, "bottom": 5, "left": 9, "right": 9}
+
+# c.colors.statusbar.normal.bg = "#00000000"
+# c.colors.statusbar.command.bg = "#00000000"
+# c.colors.tabs.even.bg = "#00000000" # transparent tabs!!
+# c.colors.tabs.odd.bg = "#00000000"
+# c.colors.tabs.bar.bg = "#00000000"
+
# # colors
# c.colors.completion.fg = ashen["text"]
# c.colors.completion.category.fg = "#F2F2F2"
diff --git a/.config/qutebrowser/userscripts/code_select.py b/.config/qutebrowser/userscripts/code_select.py
new file mode 100644
index 00000000..8f7fc312
--- /dev/null
+++ b/.config/qutebrowser/userscripts/code_select.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+
+import os
+import html
+import re
+import sys
+import xml.etree.ElementTree as ET
+try:
+ import pyperclip
+except ImportError:
+ try:
+ import pyclip as pyperclip
+ except ImportError:
+ PYPERCLIP = False
+ else:
+ PYPERCLIP = True
+else:
+ PYPERCLIP = True
+
+
+def parse_text_content(element):
+ # https://stackoverflow.com/a/35591507/15245191
+ magic = '''
+ ]>'''
+ root = ET.fromstring(magic + element)
+ text = ET.tostring(root, encoding="unicode", method="text")
+ text = html.unescape(text)
+ return text
+
+
+def send_command_to_qute(command):
+ with open(os.environ.get("QUTE_FIFO"), "w") as f:
+ f.write(command)
+
+
+def main():
+ delimiter = sys.argv[1] if len(sys.argv) > 1 else ";"
+ # For info on qute environment vairables, see
+ # https://github.com/qutebrowser/qutebrowser/blob/master/doc/userscripts.asciidoc
+ element = os.environ.get("QUTE_SELECTED_HTML")
+ code_text = parse_text_content(element)
+ re_remove_dollars = re.compile(r"^(\$ )", re.MULTILINE)
+ code_text = re.sub(re_remove_dollars, '', code_text)
+ if PYPERCLIP:
+ pyperclip.copy(code_text)
+ send_command_to_qute(
+ "message-info 'copied to clipboard: {info}{suffix}'".format(
+ info=code_text.splitlines()[0].replace("'", "\""),
+ suffix="..." if len(code_text.splitlines()) > 1 else ""
+ )
+ )
+ else:
+ # Qute's yank command won't copy accross multiple lines so we
+ # compromise by placing lines on a single line seperated by the
+ # specified delimiter
+ code_text = re.sub("(\n)+", delimiter, code_text)
+ code_text = code_text.replace("'", "\"")
+ send_command_to_qute("yank inline '{code}'\n".format(code=code_text))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/.config/qutebrowser/userscripts/getbib b/.config/qutebrowser/userscripts/getbib
new file mode 100644
index 00000000..0ab0ba54
--- /dev/null
+++ b/.config/qutebrowser/userscripts/getbib
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+"""Qutebrowser userscript scraping the current web page for DOIs and downloading
+corresponding bibtex information.
+
+Set the environment variable 'QUTE_BIB_FILEPATH' to indicate the path to
+download to. Otherwise, bibtex information is downloaded to '/tmp' and hence
+deleted at reboot.
+
+Installation: see qute://help/userscripts.html
+
+Inspired by
+https://ocefpaf.github.io/python4oceanographers/blog/2014/05/19/doi2bibtex/
+"""
+
+import os
+import sys
+import re
+from collections import Counter
+from urllib import parse as url_parse
+from urllib import request as url_request
+
+
+FIFO_PATH = os.getenv("QUTE_FIFO")
+
+def message_fifo(message, level="warning"):
+ """Send message to qutebrowser FIFO. The level must be one of 'info',
+ 'warning' (default) or 'error'."""
+ with open(FIFO_PATH, "w") as fifo:
+ fifo.write("message-{} '{}'".format(level, message))
+
+
+source = os.getenv("QUTE_TEXT")
+with open(source) as f:
+ text = f.read()
+
+# find DOIs on page using regex
+dval = re.compile(r'(10\.(\d)+/([^(\s\>\"\<)])+)')
+# https://stackoverflow.com/a/10324802/3865876, too strict
+# dval = re.compile(r'\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])\S)+)\b')
+dois = dval.findall(text)
+dois = Counter(e[0] for e in dois)
+try:
+ doi = dois.most_common(1)[0][0]
+except IndexError:
+ message_fifo("No DOIs found on page")
+ sys.exit()
+message_fifo("Found {} DOIs on page, selecting {}".format(len(dois), doi),
+ level="info")
+
+# get bibtex data corresponding to DOI
+url = "https://dx.doi.org/" + url_parse.quote(doi)
+headers = dict(Accept='text/bibliography; style=bibtex')
+request = url_request.Request(url, headers=headers)
+response = url_request.urlopen(request)
+status_code = response.getcode()
+if status_code >= 400:
+ message_fifo("Request returned {}".format(status_code))
+ sys.exit()
+
+# obtain content and format it
+bibtex = response.read().decode("utf-8").strip()
+bibtex = bibtex.replace(" ", "\n ", 1).\
+ replace("}, ", "},\n ").replace("}}", "}\n}")
+
+# append to file
+bib_filepath = os.getenv("QUTE_BIB_FILEPATH", "/tmp/qute.bib")
+with open(bib_filepath, "a") as f:
+ f.write(bibtex + "\n\n")
diff --git a/.config/qutebrowser/userscripts/localhost b/.config/qutebrowser/userscripts/localhost
new file mode 100644
index 00000000..1715c10a
--- /dev/null
+++ b/.config/qutebrowser/userscripts/localhost
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+if [[ $1 -eq 'list' ]] && [[ -z $QUTE_COUNT ]];
+then
+ PORTS="$(ss -nltp | tail -n +2 | awk '{print $4}' | awk -F: '{print $2}')"
+ QUTE_COUNT=$(echo "$PORTS" | dmenu )
+fi
+
+echo open -t localhost:${QUTE_COUNT:-8080} > $QUTE_FIFO
diff --git a/.config/qutebrowser/userscripts/qute-bitwarden b/.config/qutebrowser/userscripts/qute-bitwarden
new file mode 100644
index 00000000..4e755772
--- /dev/null
+++ b/.config/qutebrowser/userscripts/qute-bitwarden
@@ -0,0 +1,308 @@
+#!/usr/bin/env python3
+
+# SPDX-FileCopyrightText: Chris Braun (cryzed)
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+"""
+Insert login information using Bitwarden CLI and a dmenu-compatible application
+(e.g. dmenu, rofi -dmenu, ...).
+"""
+
+USAGE = """The domain of the site has to be in the name of the Bitwarden entry, for example: "github.com/cryzed" or
+"websites/github.com". The login information is inserted by emulating key events using qutebrowser's fake-key command in this manner:
+[USERNAME][PASSWORD], which is compatible with almost all login forms.
+
+If enabled, with the `--totp` flag, it will also move the TOTP code to the
+clipboard, much like the Firefox add-on.
+
+You must log into Bitwarden CLI using `bw login` prior to use of this script.
+The session key will be stored using keyctl for the number of seconds passed to
+the --auto-lock option.
+
+To use in qutebrowser, run: `spawn --userscript qute-bitwarden`
+"""
+
+EPILOG = """Dependencies: tldextract (Python 3 module), pyperclip (optional
+Python module, used for TOTP codes), Bitwarden CLI (1.7.4 is known to work
+but older versions may well also work)
+
+WARNING: The login details are viewable as plaintext in qutebrowser's debug log
+(qute://log) and might be shared if you decide to submit a crash report!"""
+
+import argparse
+import enum
+import functools
+import os
+import shlex
+import subprocess
+import sys
+import json
+import tldextract
+
+argument_parser = argparse.ArgumentParser(
+ description=__doc__,
+ usage=USAGE,
+ epilog=EPILOG,
+)
+argument_parser.add_argument('url', nargs='?', default=os.getenv('QUTE_URL'))
+argument_parser.add_argument('--dmenu-invocation', '-d', default='rofi -dmenu -i -p Bitwarden',
+ help='Invocation used to execute a dmenu-provider')
+argument_parser.add_argument('--password-prompt-invocation', '-p', default='rofi -dmenu -p "Master Password" -password -lines 0',
+ help='Invocation used to prompt the user for their Bitwarden password')
+argument_parser.add_argument('--no-insert-mode', '-n', dest='insert_mode', action='store_false',
+ help="Don't automatically enter insert mode")
+argument_parser.add_argument('--totp', '-t', action='store_true',
+ help="Copy TOTP key to clipboard")
+argument_parser.add_argument('--io-encoding', '-i', default='UTF-8',
+ help='Encoding used to communicate with subprocesses')
+argument_parser.add_argument('--merge-candidates', '-m', action='store_true',
+ help='Merge pass candidates for fully-qualified and registered domain name')
+argument_parser.add_argument('--auto-lock', type=int, default=900,
+ help='Automatically lock the vault after this many seconds')
+group = argument_parser.add_mutually_exclusive_group()
+group.add_argument('--username-only', '-e',
+ action='store_true', help='Only insert username')
+group.add_argument('--password-only', '-w',
+ action='store_true', help='Only insert password')
+group.add_argument('--totp-only', '-T',
+ action='store_true', help='Only insert totp code')
+
+stderr = functools.partial(print, file=sys.stderr)
+
+
+class ExitCodes(enum.IntEnum):
+ SUCCESS = 0
+ FAILURE = 1
+ # 1 is automatically used if Python throws an exception
+ NO_PASS_CANDIDATES = 2
+ COULD_NOT_MATCH_USERNAME = 3
+ COULD_NOT_MATCH_PASSWORD = 4
+
+
+def qute_command(command):
+ with open(os.environ['QUTE_FIFO'], 'w') as fifo:
+ fifo.write(command + '\n')
+ fifo.flush()
+
+
+def ask_password(password_prompt_invocation):
+ process = subprocess.run(
+ shlex.split(password_prompt_invocation),
+ text=True,
+ stdout=subprocess.PIPE,
+ )
+ if process.returncode > 0:
+ raise Exception('Could not unlock vault')
+ master_pass = process.stdout.strip()
+ return subprocess.check_output(
+ ['bw', 'unlock', '--raw', '--passwordenv', 'BW_MASTERPASS'],
+ env={**os.environ, 'BW_MASTERPASS': master_pass},
+ text=True,
+ ).strip()
+
+
+def get_session_key(auto_lock, password_prompt_invocation):
+ if auto_lock == 0:
+ subprocess.call(['keyctl', 'purge', 'user', 'bw_session'])
+ return ask_password(password_prompt_invocation)
+ else:
+ process = subprocess.run(
+ ['keyctl', 'request', 'user', 'bw_session'],
+ text=True,
+ stdout=subprocess.PIPE,
+ )
+ key_id = process.stdout.strip()
+ if process.returncode > 0:
+ session = ask_password(password_prompt_invocation)
+ if not session:
+ raise Exception('Could not unlock vault')
+ key_id = subprocess.check_output(
+ ['keyctl', 'add', 'user', 'bw_session', session, '@u'],
+ text=True,
+ ).strip()
+
+ if auto_lock > 0:
+ subprocess.call(['keyctl', 'timeout', str(key_id), str(auto_lock)])
+ return subprocess.check_output(
+ ['keyctl', 'pipe', str(key_id)],
+ text=True,
+ ).strip()
+
+
+def pass_(domain, encoding, auto_lock, password_prompt_invocation):
+ session_key = get_session_key(auto_lock, password_prompt_invocation)
+ process = subprocess.run(
+ ['bw', 'list', 'items', '--nointeraction', '--session', session_key, '--url', domain],
+ capture_output=True,
+ )
+
+ err = process.stderr.decode(encoding).strip()
+ if err:
+ msg = 'Bitwarden CLI returned for {:s} - {:s}'.format(domain, err)
+ stderr(msg)
+
+ if "Vault is locked" in err:
+ stderr("Bitwarden Vault got locked, trying again with clean session")
+ return pass_(domain, encoding, 0, password_prompt_invocation)
+
+ if process.returncode:
+ return '[]'
+
+ out = process.stdout.decode(encoding).strip()
+
+ return out
+
+
+def get_totp_code(selection_id, domain_name, encoding, auto_lock, password_prompt_invocation):
+ session_key = get_session_key(auto_lock, password_prompt_invocation)
+ process = subprocess.run(
+ ['bw', 'get', 'totp', '--nointeraction', '--session', session_key, selection_id],
+ capture_output=True,
+ )
+
+ err = process.stderr.decode(encoding).strip()
+ if err:
+ # domain_name instead of selection_id to make it more user-friendly
+ msg = 'Bitwarden CLI returned for {:s} - {:s}'.format(domain_name, err)
+ stderr(msg)
+
+ if "Vault is locked" in err:
+ stderr("Bitwarden Vault got locked, trying again with clean session")
+ return get_totp_code(selection_id, domain_name, encoding, 0, password_prompt_invocation)
+
+ if process.returncode:
+ return '[]'
+
+ out = process.stdout.decode(encoding).strip()
+
+ return out
+
+
+def dmenu(items, invocation, encoding):
+ command = shlex.split(invocation)
+ process = subprocess.run(command, input='\n'.join(
+ items).encode(encoding), stdout=subprocess.PIPE)
+ return process.stdout.decode(encoding).strip()
+
+
+def fake_key_raw(text):
+ for character in text:
+ # Escape all characters by default, space requires special handling
+ sequence = '" "' if character == ' ' else r'\{}'.format(character)
+ qute_command('fake-key {}'.format(sequence))
+
+
+def main(arguments):
+ if not arguments.url:
+ argument_parser.print_help()
+ return ExitCodes.FAILURE
+
+ extract_result = tldextract.extract(arguments.url)
+
+ # Try to find candidates using targets in the following order: fully-qualified domain name (includes subdomains),
+ # the registered domain name and finally: the IPv4 address if that's what
+ # the URL represents
+ candidates = []
+ for target in filter(
+ None,
+ [
+ extract_result.fqdn,
+ (
+ extract_result.top_domain_under_public_suffix
+ if hasattr(extract_result, "top_domain_under_public_suffix")
+ else extract_result.registered_domain
+ ),
+ extract_result.subdomain + "." + extract_result.domain,
+ extract_result.domain,
+ extract_result.ipv4,
+ ],
+ ):
+ target_candidates = json.loads(
+ pass_(
+ target,
+ arguments.io_encoding,
+ arguments.auto_lock,
+ arguments.password_prompt_invocation,
+ )
+ )
+ if not target_candidates:
+ continue
+
+ candidates = candidates + target_candidates
+ if not arguments.merge_candidates:
+ break
+ else:
+ if not candidates:
+ stderr('No pass candidates for URL {!r} found!'.format(
+ arguments.url))
+ return ExitCodes.NO_PASS_CANDIDATES
+
+ if len(candidates) == 1:
+ selection = candidates.pop()
+ else:
+ choices = ['{:s} | {:s}'.format(c['name'], c['login']['username']) for c in candidates]
+ choice = dmenu(choices, arguments.dmenu_invocation, arguments.io_encoding)
+ choice_tokens = choice.split('|')
+ choice_name = choice_tokens[0].strip()
+ choice_username = choice_tokens[1].strip()
+ selection = next((c for (i, c) in enumerate(candidates)
+ if c['name'] == choice_name
+ and c['login']['username'] == choice_username),
+ None)
+
+ # Nothing was selected, simply return
+ if not selection:
+ return ExitCodes.SUCCESS
+
+ username = selection['login']['username']
+ password = selection['login']['password']
+ totp = selection['login']['totp']
+
+ if arguments.username_only:
+ fake_key_raw(username)
+ elif arguments.password_only:
+ fake_key_raw(password)
+ elif arguments.totp_only:
+ # No point in moving it to the clipboard in this case
+ fake_key_raw(
+ get_totp_code(
+ selection['id'],
+ selection['name'],
+ arguments.io_encoding,
+ arguments.auto_lock,
+ arguments.password_prompt_invocation,
+ )
+ )
+ else:
+ # Enter username and password using fake-key and (which seems to work almost universally), then switch
+ # back into insert-mode, so the form can be directly submitted by
+ # hitting enter afterwards
+ fake_key_raw(username)
+ qute_command('fake-key ')
+ fake_key_raw(password)
+
+ if arguments.insert_mode:
+ qute_command('mode-enter insert')
+
+ # If it finds a TOTP code, it copies it to the clipboard,
+ # which is the same behavior as the Firefox add-on.
+ if not arguments.totp_only and totp and arguments.totp:
+ # The import is done here, to make pyperclip an optional dependency
+ import pyperclip
+ pyperclip.copy(
+ get_totp_code(
+ selection['id'],
+ selection['name'],
+ arguments.io_encoding,
+ arguments.auto_lock,
+ arguments.password_prompt_invocation,
+ )
+ )
+
+ return ExitCodes.SUCCESS
+
+
+if __name__ == '__main__':
+ arguments = argument_parser.parse_args()
+ sys.exit(main(arguments))
diff --git a/.config/qutebrowser/userscripts/readability b/.config/qutebrowser/userscripts/readability
new file mode 100644
index 00000000..07095a5b
--- /dev/null
+++ b/.config/qutebrowser/userscripts/readability
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+#
+# Executes python-readability on current page and opens the summary as new tab.
+#
+# Depends on the python-readability package, or its fork:
+#
+# - https://github.com/buriy/python-readability
+# - https://github.com/bookieio/breadability
+#
+# Usage:
+# :spawn --userscript readability
+#
+import codecs, os
+
+tmpfile = os.path.join(
+ os.environ.get('QUTE_DATA_DIR',
+ os.path.expanduser('~/.local/share/qutebrowser')),
+ 'userscripts/readability.html')
+
+if not os.path.exists(os.path.dirname(tmpfile)):
+ os.makedirs(os.path.dirname(tmpfile))
+
+# Styling for dynamic window margin scaling and line height
+HEADER = """
+
+
+
+
+ %s
+
+
+
+"""
+
+with codecs.open(os.environ['QUTE_HTML'], 'r', 'utf-8') as source:
+ data = source.read()
+
+ try:
+ from breadability.readable import Article as reader
+ doc = reader(data, os.environ['QUTE_URL'])
+ title = doc._original_document.title
+ content = HEADER % title + doc.readable + ""
+ except ImportError:
+ from readability import Document
+ doc = Document(data)
+ title = doc.title()
+ content = doc.summary().replace('', HEADER % title)
+
+ # add a class to make styling the page easier
+ content = content.replace('', '')
+
+ with codecs.open(tmpfile, 'w', 'utf-8') as target:
+ target.write(content.lstrip())
+
+ with open(os.environ['QUTE_FIFO'], 'w') as fifo:
+ fifo.write('open -t %s' % tmpfile)
diff --git a/.config/qutebrowser/userscripts/view_in_mpv b/.config/qutebrowser/userscripts/view_in_mpv
new file mode 100644
index 00000000..4f371c6b
--- /dev/null
+++ b/.config/qutebrowser/userscripts/view_in_mpv
@@ -0,0 +1,142 @@
+#!/usr/bin/env bash
+#
+# Behavior:
+# Userscript for qutebrowser which views the current web page in mpv using
+# sensible mpv-flags. While viewing the page in MPV, all
+
+ In order to restore this particular video
+ click here.
+
+ ";
+ replacement.style.position = "relative";
+ replacement.style.zIndex = "100003000000";
+ replacement.style.fontSize = "1rem";
+ replacement.style.textAlign = "center";
+ replacement.style.verticalAlign = "middle";
+ replacement.style.height = "100%";
+ replacement.style.background = "#101010";
+ replacement.style.color = "white";
+ replacement.style.border = "4px dashed #545454";
+ replacement.style.padding = "2em";
+ replacement.style.margin = "auto";
+ App.all_replacements[i] = replacement;
+ App.backup_videos[i] = video;
+ video.parentNode.replaceChild(replacement, video);
+ }
+
+ function restore_video(obj, index) {
+ obj = App.all_replacements[index];
+ video = App.backup_videos[index];
+ obj.parentNode.replaceChild(video, obj);
+ }
+
+ /** force repainting the video, thanks to:
+ * http://web.archive.org/web/20151029064649/https://martinwolf.org/2014/06/10/force-repaint-of-an-element-with-javascript/
+ */
+ var siteHeader = document.getElementById('header');
+ siteHeader.style.display='none';
+ siteHeader.offsetHeight; // no need to store this anywhere, the reference is enough
+ siteHeader.style.display='block';
+
+EOF
+}
+
+printjs() {
+ js | sed 's,//.*$,,' | tr '\n' ' '
+}
+echo "jseval -q -w main $(printjs)" >> "$QUTE_FIFO"
+
+msg info "Opening $QUTE_URL with mpv"
+"${video_command[@]}" "$@" "$QUTE_URL"
diff --git a/.config/zathura/zathurarc b/.config/zathura/zathurarc
index 77b7da72..5ff6f7d1 100644
--- a/.config/zathura/zathurarc
+++ b/.config/zathura/zathurarc
@@ -1,4 +1,6 @@
set selection-clipboard clipboard
+set synctex true
+set synctex-editor-command "texlab inverse-search -i %{input} -l %{line}"
map zoom in
map zoom out
map N navigate next
diff --git a/.editorconfig b/.editorconfig
index 472d81ce..5907a1c9 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -15,18 +15,18 @@ indent_size = 4
[*.go]
indent_style = tab
-[*md]
+[*.md]
trim_trailing_whitespace = false
insert_final_newline = true
indent_style = space
indent_size = 2
-[*yml]
+[*.yml]
indent_style = space
indent_size = 2
-[*typ]
+[*.typ]
indent_style = space
indent_size = 2
-[*fish]
+[*.fish]
indent_style = space
indent_size = 4