resolved merge conflict
This commit is contained in:
commit
110b65e396
31 changed files with 1662 additions and 87 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -1,4 +1,56 @@
|
|||
map -docstring "yank the selection into the clipboard" global user y "<a-|> wl-copy<ret>"
|
||||
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 <a-k>\n<ret>
|
||||
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<ret>'
|
||||
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<a-P><a-K>\n<ret>a<ret><esc>'
|
||||
echo 'gj: clip-trim<ret>'
|
||||
echo '%<a-|><ret>'
|
||||
else
|
||||
# paste all, select all, pipe to copy cmd
|
||||
echo '"a<a-P>%<a-|><ret>'
|
||||
fi
|
||||
echo ": delete-buffer<ret>"
|
||||
else
|
||||
echo '<a-|><ret>'
|
||||
fi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map -docstring "yank the selections into the clipboard" global user y ": clipboard-copy<ret>"
|
||||
map -docstring "yank the split selections into the clipboard" global user Y ": clipboard-copy -split<ret>"
|
||||
|
||||
map -docstring "paste the clipboard" global user p "<a-!> wl-paste -n<ret>"
|
||||
map -docstring "paste the clipboard before" global user P "! wl-paste -n<ret>"
|
||||
|
|
106
.config/kak/autoload/detection/editorconfig.kak
Normal file
106
.config/kak/autoload/detection/editorconfig.kak
Normal file
|
@ -0,0 +1,106 @@
|
|||
# http://editorconfig.org/#file-format-details
|
||||
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
|
||||
|
||||
# Patch by Daniel <daniel@ficd.ca>:
|
||||
# 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+$<ret>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
|
|
@ -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 %{
|
||||
|
|
83
.config/kak/autoload/filetype/just.kak
Normal file
83
.config/kak/autoload/filetype/just.kak
Normal file
|
@ -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 + $ <ret> 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* <ret> y jgh P }
|
||||
}
|
||||
|
||||
define-command -hidden just-indent-on-new-line %{
|
||||
evaluate-commands -draft -itersel %{
|
||||
# preserve previous line indent
|
||||
try %{ execute-keys -draft <semicolon>K<a-&> }
|
||||
# cleanup trailing white spaces on previous line
|
||||
try %{ execute-keys -draft kx s \h+$ <ret>"_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 '"' (?<!\\)(\\\\)*" fill string
|
||||
add-highlighter shared/justfile/content/strings/single region "'" (?<!\\)(\\\\)*' fill string
|
||||
|
||||
add-highlighter shared/justfile/comment region '#' '$' fill comment
|
||||
|
||||
add-highlighter shared/justfile/inline region '`' '`' ref sh
|
||||
|
||||
add-highlighter shared/justfile/body region '^\h+' '^[^\h]' group
|
||||
add-highlighter shared/justfile/body/interpreters regions
|
||||
add-highlighter shared/justfile/body/interpreters/defaultshell default-region group
|
||||
add-highlighter shared/justfile/body/interpreters/defaultshell/ ref sh
|
||||
add-highlighter shared/justfile/body/interpreters/defaultshell/ regex '^\h+(@)' 1:operator
|
||||
|
||||
add-highlighter shared/justfile/body/interpreters/bash region '^\h+#!\h?/usr/bin/env bash' '^[^\h]' ref sh
|
||||
add-highlighter shared/justfile/body/interpreters/sh region '^\h+#!\h?/usr/bin/env sh' '^[^\h]' ref sh
|
||||
|
||||
add-highlighter shared/justfile/body/ regex '(\{{2})([\w-]+(?:\(\))?)(\}{2})' 1:operator 2:variable 3:operator
|
||||
|
||||
|
||||
}
|
|
@ -1,5 +1,42 @@
|
|||
# https://git.sr.ht/~hadronized/hop.kak
|
||||
evaluate-commands %sh{ hop-kak --init }
|
||||
# evaluate-commands %sh{ hop-kak --init }
|
||||
provide-module hop-kak %~
|
||||
declare-option range-specs hop_ranges
|
||||
|
||||
set-face global hop_label_head %exp{%opt{background},%opt{orange_golden}+Fbua}
|
||||
set-face global hop_label_tail %exp{%opt{background},%opt{orange_golden}+Fbua}
|
||||
|
||||
# needed so the cursor face doesn't override what hop sets
|
||||
# but only temporary because otherwise we want cursor face to
|
||||
# override others
|
||||
define-command -hidden hop-set-cursor %{
|
||||
set-face window PrimaryCursorNormal "%opt{background},%opt{orange_blaze}+b"
|
||||
set-face window SecondaryCursorNormal "%opt{background},%opt{orange_muted}"
|
||||
set-face window PrimaryCursorInsert "%opt{background},%opt{g_3}+b"
|
||||
set-face window SecondaryCursorInsert "%opt{background},%opt{g_7}"
|
||||
set-face window PrimaryCursorNormalEol "%opt{background},%opt{orange_smolder}+b"
|
||||
set-face window SecondaryCursorNormalEol "%opt{background},%opt{golden_muted}"
|
||||
set-face window PrimaryCursorInsertEol "%opt{background},%opt{g_1}+b"
|
||||
set-face window SecondaryCursorInsertEol "%opt{background},%opt{g_5}"
|
||||
set-face window PrimarySelection ",%opt{brown_dark}"
|
||||
set-face window SecondarySelection ",%opt{brown_darker}"
|
||||
|
||||
}
|
||||
|
||||
define-command -hidden hop-clear-cursor %{
|
||||
set-face window PrimaryCursorNormal "%opt{background},%opt{orange_blaze}+gfb"
|
||||
set-face window SecondaryCursorNormal "%opt{background},%opt{orange_muted}+gf"
|
||||
set-face window PrimaryCursorInsert "%opt{background},%opt{g_3}+gfb"
|
||||
set-face window SecondaryCursorInsert "%opt{background},%opt{g_7}+gf"
|
||||
set-face window PrimaryCursorNormalEol "%opt{background},%opt{orange_smolder}+gfb"
|
||||
set-face window SecondaryCursorNormalEol "%opt{background},%opt{golden_muted}+gf"
|
||||
set-face window PrimaryCursorInsertEol "%opt{background},%opt{g_1}+gfb"
|
||||
set-face window SecondaryCursorInsertEol "%opt{background},%opt{g_5}+gf"
|
||||
set-face window PrimarySelection ",%opt{brown_dark}+g"
|
||||
set-face window SecondarySelection ",%opt{brown_darker}+g"
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare-option str hop_kak_keyset 'tnserigmaodhcxplfuwyqz'
|
||||
|
||||
|
@ -14,11 +51,13 @@ define-command hop-kak %{
|
|||
|
||||
|
||||
define-command -override hop-kak-words %{
|
||||
hop-set-cursor
|
||||
eval "ui-scrolloff-disable"
|
||||
try %{ ui-wrap-disable }
|
||||
map window normal <esc> ': trigger-user-hook donehop<ret><esc>'
|
||||
map window normal , ': trigger-user-hook donehop<ret>,'
|
||||
hook -once window User donehop %{
|
||||
hop-clear-cursor
|
||||
eval "ui-scrolloff-enable"
|
||||
try %{ ui-wrap-enable }
|
||||
unmap window normal <esc>
|
||||
|
@ -37,3 +76,4 @@ map -docstring %{
|
|||
map -docstring %{
|
||||
Hop mode
|
||||
} global normal <ret> ': enter-user-mode hop<ret>'
|
||||
~
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# load plugin
|
||||
eval %sh{kak-lsp}
|
||||
# eval %sh{kak-lsp-diags}
|
||||
|
||||
# mappings
|
||||
map global user l ': enter-user-mode lsp<ret>' -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<ret>'
|
||||
map -docstring 'toggle inlay diagnostics' window ui d ': diagnostics-toggle<ret>'
|
||||
} catch %{
|
||||
map -docstring 'toggle inlay hints' window lsp <a-h> ': inlay-toggle<ret>'
|
||||
map -docstring 'toggle inlay diagnostics' window lsp <a-d> ': diagnostics-toggle<ret>'
|
||||
}
|
||||
# only map to UI mode if that module is available
|
||||
map -docstring 'toggle inlay hints' window ui h ': inlay-toggle<ret>'
|
||||
map -docstring 'toggle inlay diagnostics' window ui d ': inlay-diagnostics-toggle<ret>'
|
||||
map -docstring 'toggle inline diagnostics' window ui e ': inline-diagnostics-toggle<ret>'
|
||||
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{@}
|
||||
# }
|
||||
|
||||
|
|
287
.config/kak/autoload/notes.kak
Normal file
287
.config/kak/autoload/notes.kak
Normal file
|
@ -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 "gif<space>e_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 '<a-i>w"iy'
|
||||
execute-keys -draft '%sgithub_project: <ret>;<a-W>_"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'<ret>|sort<ret>gg"
|
||||
}
|
||||
|
||||
# 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 <ret> 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}<ret>'
|
||||
}
|
||||
|
||||
# Run a grepper with the provided arguments as search query.
|
||||
define-command -hidden notes-grepcmd -params 2 %{
|
||||
# Initial implementation based on rg <pattern> <path>.
|
||||
execute-keys ":grep %arg{2} %arg{1}<ret>"
|
||||
}
|
||||
|
||||
# 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<ret>' -docstring 'notes'
|
||||
|
||||
map global notes A ':notes-archive-note<ret>' -docstring 'archive note'
|
||||
map global notes a ':notes-archive-open<ret>' -docstring 'open archived note'
|
||||
map global notes C ':notes-capture<ret>' -docstring 'capture'
|
||||
map global notes c ':notes-open-capture<ret>' -docstring 'open capture'
|
||||
map global notes j ':notes-journal-open<ret>' -docstring 'open journal'
|
||||
map global notes J ':enter-user-mode notes-journal-nav<ret>' -docstring 'navigate journals'
|
||||
map global notes l ':enter-user-mode notes-tasks-list<ret>' -docstring 'tasks list'
|
||||
map global notes N ':notes-new-note<ret>' -docstring 'new note'
|
||||
map global notes n ':notes-open<ret>' -docstring 'open note'
|
||||
map global notes / ':notes-search<ret>' -docstring 'search in notes'
|
||||
map global notes S ':notes-sync<ret>' -docstring 'synchronize notes'
|
||||
map global notes t ':enter-user-mode notes-tasks<ret>' -docstring 'tasks'
|
||||
map global notes z ':notes-override-active-dir<ret>' -docstring 'switch notes dir with PWD'
|
||||
|
||||
map global notes-journal-nav l ':enter-user-mode notes-journal-nav-last<ret>' -docstring 'last…'
|
||||
map global notes-journal-nav d ':notes-journal-open-rel "-1 day"<ret>' -docstring 'day before'
|
||||
map global notes-journal-nav D ':notes-journal-open-rel "+1 day"<ret>' -docstring 'day after'
|
||||
map global notes-journal-nav w ':notes-journal-open-rel "-1 week"<ret>' -docstring 'week before'
|
||||
map global notes-journal-nav W ':notes-journal-open-rel "+1 week"<ret>' -docstring 'week after'
|
||||
map global notes-journal-nav m ':notes-journal-open-rel "-1 month"<ret>' -docstring 'month before'
|
||||
map global notes-journal-nav M ':notes-journal-open-rel "+1 month"<ret>' -docstring 'month after'
|
||||
|
||||
map global notes-journal-nav-last m ':notes-journal-open-rel "last monday"<ret>' -docstring 'monday'
|
||||
map global notes-journal-nav-last t ':notes-journal-open-rel "last tuesday"<ret>' -docstring 'tuesday'
|
||||
map global notes-journal-nav-last w ':notes-journal-open-rel "last wednesday"<ret>' -docstring 'wednesday'
|
||||
map global notes-journal-nav-last h ':notes-journal-open-rel "last thursday"<ret>' -docstring 'thursday'
|
||||
map global notes-journal-nav-last f ':notes-journal-open-rel "last friday"<ret>' -docstring 'friday'
|
||||
map global notes-journal-nav-last T ':notes-journal-open-rel "last saturday"<ret>' -docstring 'saturday'
|
||||
map global notes-journal-nav-last S ':notes-journal-open-rel "last sunday"<ret>' -docstring 'sunday'
|
||||
|
||||
map global notes-tasks-list a ":notes-tasks-list-all<ret>" -docstring 'list all tasks'
|
||||
map global notes-tasks-list d ":notes-tasks-list-by-regex %opt{notes_sym_done}<ret>" -docstring 'list done tasks'
|
||||
map global notes-tasks-list h ":notes-tasks-list-by-regex %opt{notes_sym_hold}<ret>" -docstring 'list hold tasks'
|
||||
map global notes-tasks-list i ":notes-tasks-list-by-regex %opt{notes_sym_idea}<ret>" -docstring 'list ideas'
|
||||
map global notes-tasks-list l ":notes-tasks-list-by-regex '\ :[^:]+:'<ret>" -docstring 'list tasks by labels'
|
||||
map global notes-tasks-list n ":notes-tasks-list-by-regex %opt{notes_sym_wontdo}<ret>" -docstring 'list wontdo tasks'
|
||||
map global notes-tasks-list q ":notes-tasks-list-by-regex %opt{notes_sym_question}<ret>" -docstring 'list questions'
|
||||
map global notes-tasks-list r ":notes-tasks-list-by-regex %opt{notes_sym_review}<ret>" -docstring 'list reviews'
|
||||
map global notes-tasks-list t ":notes-tasks-list-by-regex %opt{notes_sym_todo}<ret>" -docstring 'list todo tasks'
|
||||
map global notes-tasks-list w ":notes-tasks-list-by-regex %opt{notes_sym_wip}<ret>" -docstring 'list wip tasks'
|
||||
|
||||
hook -group notes-tasks global WinCreate \*notes-tasks-list\* %{
|
||||
map buffer normal '<ret>' ':notes-tasks-list-open<ret>'
|
||||
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}<ret>" -docstring 'switch task to done'
|
||||
map window notes-tasks h ":notes-task-switch-status %opt{notes_sym_hold}<ret>" -docstring 'switch task to hold'
|
||||
map window notes-tasks i ":notes-task-switch-status %opt{notes_sym_idea}<ret>" -docstring 'switch task to idea'
|
||||
map window notes-tasks n ":notes-task-switch-status %opt{notes_sym_wontdo}<ret>" -docstring 'switch task to wontdo'
|
||||
map window notes-tasks q ":notes-task-switch-status %opt{notes_sym_question}<ret>" -docstring 'switch task to question'
|
||||
map window notes-tasks <ret> ":notes-task-gh-open-issue<ret>" -docstring 'open GitHub issue'
|
||||
map window notes-tasks r ":notes-task-switch-status %opt{notes_sym_review}<ret>" -docstring 'switch task to review'
|
||||
map window notes-tasks t ":notes-task-switch-status %opt{notes_sym_todo}<ret>" -docstring 'switch task to todo'
|
||||
map window notes-tasks w ":notes-task-switch-status %opt{notes_sym_wip}<ret>" -docstring 'switch task to wip'
|
||||
}
|
||||
|
||||
~
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/usr/share/kak/rc/detection/editorconfig.kak
|
|
@ -1 +0,0 @@
|
|||
/usr/share/kak/rc/filetype/just.kak
|
|
@ -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 '<a-?>' <a-
|
|||
map -docstring 'Select to file end' global user N "Gj<a-L>L"
|
||||
map -docstring 'Extend to file end' global user n "gj<a-l>l"
|
||||
|
||||
# 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 <c-f> <c-i>
|
||||
|
@ -169,3 +171,22 @@ map -docstring 'save to jumplist' global normal <c-v> <c-s>
|
|||
|
||||
# selection saving
|
||||
map -docstring 'add selection' global normal Y <a-Z>a
|
||||
|
||||
define-command -docstring 'open popup shell' popup-shell %{
|
||||
popup fish
|
||||
}
|
||||
alias global pp popup-shell
|
||||
|
||||
map -docstring 'popup shell' global user . ': popup-shell<ret>'
|
||||
|
||||
# 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
|
||||
# }
|
||||
# }
|
||||
|
||||
|
|
1
.config/kak/scripts/lsp-diags.py
Symbolic link
1
.config/kak/scripts/lsp-diags.py
Symbolic link
|
@ -0,0 +1 @@
|
|||
/home/fic/dev/kak-lsp-diags/lsp-diags.py
|
132
.config/kak/scripts/lsp-diags_.py
Executable file
132
.config/kak/scripts/lsp-diags_.py
Executable file
|
@ -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()
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -8,3 +8,7 @@ config_version: 2
|
|||
settings:
|
||||
content.javascript.clipboard:
|
||||
https://github.com: access-paste
|
||||
statusbar.show:
|
||||
global: always
|
||||
tabs.position:
|
||||
global: top
|
||||
|
|
|
@ -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"]["<Escape>"] = "click-element css main"
|
||||
c.url.searchengines["w"] = (
|
||||
"https://en.wikipedia.org/w/index.php?title=Special:Search&search={}"
|
||||
)
|
||||
config.bind(
|
||||
"<Shift-Escape>",
|
||||
"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"],
|
||||
["<Ctrl-/>", "hint links spawn --detach mpv {hint-url}"],
|
||||
[
|
||||
";/",
|
||||
"hint links spawn --detach mpv --force-window --quiet --keep-open=yes --ytdl {hint-url}",
|
||||
],
|
||||
["<Ctrl-/>", "spawn --userscript view_in_mpv"],
|
||||
# ["<Ctrl-?>", "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"
|
||||
|
|
64
.config/qutebrowser/userscripts/code_select.py
Normal file
64
.config/qutebrowser/userscripts/code_select.py
Normal file
|
@ -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 = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
|
||||
<!ENTITY nbsp ' '>
|
||||
]>'''
|
||||
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()
|
68
.config/qutebrowser/userscripts/getbib
Normal file
68
.config/qutebrowser/userscripts/getbib
Normal file
|
@ -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")
|
9
.config/qutebrowser/userscripts/localhost
Normal file
9
.config/qutebrowser/userscripts/localhost
Normal file
|
@ -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
|
308
.config/qutebrowser/userscripts/qute-bitwarden
Normal file
308
.config/qutebrowser/userscripts/qute-bitwarden
Normal file
|
@ -0,0 +1,308 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# SPDX-FileCopyrightText: Chris Braun (cryzed) <cryzed@googlemail.com>
|
||||
#
|
||||
# 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]<Tab>[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 <Tab> (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 <Tab>')
|
||||
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))
|
66
.config/qutebrowser/userscripts/readability
Normal file
66
.config/qutebrowser/userscripts/readability
Normal file
|
@ -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 = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>%s</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 40px auto;
|
||||
max-width: 650px;
|
||||
line-height: 1.4;
|
||||
padding: 0 10px;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
line-height: 1.2;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
"""
|
||||
|
||||
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 + "</html>"
|
||||
except ImportError:
|
||||
from readability import Document
|
||||
doc = Document(data)
|
||||
title = doc.title()
|
||||
content = doc.summary().replace('<html>', HEADER % title)
|
||||
|
||||
# add a class to make styling the page easier
|
||||
content = content.replace('<body>', '<body class="qute-readability">')
|
||||
|
||||
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)
|
142
.config/qutebrowser/userscripts/view_in_mpv
Normal file
142
.config/qutebrowser/userscripts/view_in_mpv
Normal file
|
@ -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 <video>, <embed>,
|
||||
# and <object> tags in the original page are temporarily removed. Clicking on
|
||||
# such a removed video restores the respective video.
|
||||
#
|
||||
# In order to use this script, just start it using `spawn --userscript` from
|
||||
# qutebrowser. I recommend using an alias, e.g. put this in the
|
||||
# [alias]-section of qutebrowser.conf:
|
||||
#
|
||||
# mpv = spawn --userscript /path/to/view_in_mpv
|
||||
#
|
||||
# Background:
|
||||
# Most of my machines are too slow to play youtube videos using html5, but
|
||||
# they work fine in mpv (and mpv has further advantages like video scaling,
|
||||
# etc). Of course, I don't want the video to be played (or even to be
|
||||
# downloaded) twice — in MPV and in qwebkit. So I often close the tab after
|
||||
# opening it in mpv. However, I actually want to keep the rest of the page
|
||||
# (comments and video suggestions), i.e. only the videos should disappear
|
||||
# when mpv is started. And that's precisely what the present script does.
|
||||
#
|
||||
# Thorsten Wißmann, 2015 (thorsten` on Libera Chat)
|
||||
# Any feedback is welcome!
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$QUTE_FIFO" ] ; then
|
||||
cat 1>&2 <<EOF
|
||||
Error: $0 can not be run as a standalone script.
|
||||
|
||||
It is a qutebrowser userscript. In order to use it, call it using
|
||||
'spawn --userscript' as described in qute://help/userscripts.html
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
msg() {
|
||||
local cmd="$1"
|
||||
shift
|
||||
local msg="$*"
|
||||
if [ -z "$QUTE_FIFO" ] ; then
|
||||
echo "$cmd: $msg" >&2
|
||||
else
|
||||
echo "message-$cmd '${msg//\'/\\\'}'" >> "$QUTE_FIFO"
|
||||
fi
|
||||
}
|
||||
|
||||
MPV_COMMAND=${MPV_COMMAND:-mpv}
|
||||
# Warning: spaces in single flags are not supported
|
||||
MPV_FLAGS=${MPV_FLAGS:- --force-window --quiet --keep-open=yes --ytdl}
|
||||
IFS=" " read -r -a video_command <<< "$MPV_COMMAND $MPV_FLAGS"
|
||||
|
||||
js() {
|
||||
cat <<EOF
|
||||
|
||||
function descendantOfTagName(child, ancestorTagName) {
|
||||
// tells whether child has some (proper) ancestor
|
||||
// with the tag name ancestorTagName
|
||||
while (child.parentNode != null) {
|
||||
child = child.parentNode;
|
||||
if (typeof child.tagName === 'undefined') break;
|
||||
if (child.tagName.toUpperCase() == ancestorTagName.toUpperCase()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var App = {};
|
||||
|
||||
var all_videos = [];
|
||||
all_videos.push.apply(all_videos, document.getElementsByTagName("video"));
|
||||
all_videos.push.apply(all_videos, document.getElementsByTagName("object"));
|
||||
all_videos.push.apply(all_videos, document.getElementsByTagName("embed"));
|
||||
App.backup_videos = Array();
|
||||
App.all_replacements = Array();
|
||||
for (i = 0; i < all_videos.length; i++) {
|
||||
var video = all_videos[i];
|
||||
if (descendantOfTagName(video, "object")) {
|
||||
// skip tags that are contained in an object, because we hide
|
||||
// the object anyway.
|
||||
continue;
|
||||
}
|
||||
var replacement = document.createElement("div");
|
||||
replacement.innerHTML = "
|
||||
<p style=\\"margin-bottom: 0.5em\\">
|
||||
Opening page with:
|
||||
<span style=\\"font-family: monospace;\\">${video_command[*]}</span>
|
||||
</p>
|
||||
<p>
|
||||
In order to restore this particular video
|
||||
<a style=\\"font-weight: bold;
|
||||
color: white;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
\\"
|
||||
onClick=\\"restore_video(this, " + i + ");\\"
|
||||
>click here</a>.
|
||||
</p>
|
||||
";
|
||||
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"
|
|
@ -1,4 +1,6 @@
|
|||
set selection-clipboard clipboard
|
||||
set synctex true
|
||||
set synctex-editor-command "texlab inverse-search -i %{input} -l %{line}"
|
||||
map <C-i> zoom in
|
||||
map <C-o> zoom out
|
||||
map N navigate next
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue