diff options
Diffstat (limited to 'tw/services/files')
35 files changed, 5143 insertions, 0 deletions
diff --git a/tw/services/files/XCompose b/tw/services/files/XCompose new file mode 100644 index 00000000..cb73e833 --- /dev/null +++ b/tw/services/files/XCompose @@ -0,0 +1,161 @@ +# -*- mode: conf-colon -*- +## Locale defaults +include "%S/en_US.UTF-8/Compose" +# This file apparently doesn't exist for all locales, including en_GB. +# Most useful things live in en_US, included above. +include "%L" + +## Dashes +<Multi_key> <minus> <minus> <period> : "–" U2013 # EN DASH +<Multi_key> <minus> <minus> <space> : "–" U2013 # EN DASH +<Multi_key> <minus> <n> : "–" U2013 # EN DASH +<Multi_key> <minus> <minus> <minus> : "—" U2014 # EM DASH +<Multi_key> <minus> <m> : "—" U2014 # EM DASH +<Multi_key> <minus> <1> : "—" U2014 # EM DASH +<Multi_key> <minus> <2> : "⸺" U2E3A # TWO-EM DASH +<Multi_key> <minus> <3> : "⸻" U2E3B # THREE-EM DASH +<Multi_key> <minus> <b> : "―" U2015 # HORIZONTAL BAR +<Multi_key> <minus> <h> <b> : "―" U2015 # HORIZONTAL BAR + +## Mathematical operators +<Multi_key> <minus> <x> : "−" U2212 # MINUS SIGN +<Multi_key> <minus> <plus> : "−" U2212 # MINUS SIGN +<Multi_key> <minus> <equal> <equal> : "≡" U2261 # IDENTICAL TO +<Multi_key> <minus> <equal> <slash> : "≢" U2262 # NOT IDENTICAL TO +<Multi_key> <asciitilde> <asciitilde> : "≈" U2248 # ALMOST EQUAL TO +<Multi_key> <asciitilde> <equal> : "≃" similarequal # ASYMPTOTICALLY EQUAL TO +<Multi_key> <equal> <asciitilde> : "≃" similarequal # ASYMPTOTICALLY EQUAL TO +<Multi_key> <asciitilde> <less> : "≲" U2272 # LESS-THAN OR EQUIVALENT TO +<Multi_key> <less> <asciitilde> : "≲" U2272 # LESS-THAN OR EQUIVALENT TO +<Multi_key> <asciitilde> <greater> : "≳" U2273 # GREATER-THAN OR EQUIVALENT TO +<Multi_key> <greater> <asciitilde> : "≳" U2273 # GREATER-THAN OR EQUIVALENT TO +<Multi_key> <less> <slash> <minus> : "↚" U219A # LEFTWARDS ARROW WITH STROKE +<Multi_key> <minus> <slash> <greater> : "↛" U219B # RIGHTWARDS ARROW WITH STROKE +<Multi_key> <less> <slash> <greater> : "↮" U21AE # LEFT RIGHT ARROW WITH STROKE +<Multi_key> <slash> <E> : "∄" U2204 # THERE DOES NOT EXIST +<Multi_key> <e> <slash> : "∉" U2209 # NOT AN ELEMENT OF +<Multi_key> <slash> <e> : "∌" U220C # DOES NOT CONTAIN AS MEMBER +<Multi_key> <slash> <bar> : "∤" U2224 # DOES NOT DIVIDE +<Multi_key> <bar> <slash> : "∤" U2224 # DOES NOT DIVIDE +<Multi_key> <backslash> <slash> <slash> : "∦" U2226 # NOT PARALLEL TO +<Multi_key> <slash> <backslash> <slash> : "∦" U2226 # NOT PARALLEL TO +<Multi_key> <asciitilde> <slash> : "≁" U2241 # NOT TILDE +<Multi_key> <slash> <asciitilde> : "≁" U2241 # NOT TILDE + +## Symbols +<Multi_key> <d> <i> : "⌀" U2300 # DIAMETER SIGN +# Note: also defined as <Multi_key> <N> <o>, but that's hard to remember! +<Multi_key> <n> <o> : "№" numerosign # NUMERO SIGN +# <Multi_key> <minus> <O> is already reserved for Ō +<Multi_key> <O> <minus> : "⊖" U2296 # ○ - CIRCLED MINUS +# <Multi_key> <period> <O> is already reserved for Ȯ +<Multi_key> <O> <period> : "⊙" U2299 # ○ - CIRCLED DOT + +## Whitespace +<Multi_key> <space> <b> : " " U00A0 # NO-BREAK SPACE (~) +<Multi_key> <space> <n> : " " U2002 # EN SPACE (\enspace) +<Multi_key> <space> <m> : " " U2003 # EM SPACE (\quad) +<Multi_key> <space> <3> : " " U2004 # THREE-PER-EM SPACE +<Multi_key> <space> <4> : " " U2005 # FOUR-PER-EM SPACE +<Multi_key> <space> <6> : " " U2006 # SIX-PER-EM SPACE +<Multi_key> <space> <f> : " " U2007 # FIGURE SPACE +<Multi_key> <space> <p> : " " U2008 # PUNCTUATION SPACE +<Multi_key> <space> <t> : " " U2009 # THIN SPACE (\,) +<Multi_key> <space> <h> : " " U200A # HAIR SPACE +<Multi_key> <space> <x> : " " U205F # MEDIUM MATHEMATICAL SPACE (may be used around operators) + +## Greek uppercase +<Multi_key> <g> <A> : "Α" U0391 +<Multi_key> <g> <B> : "Β" U0392 +<Multi_key> <g> <G> : "Γ" U0393 +<Multi_key> <g> <D> : "Δ" U0394 +<Multi_key> <g> <E> : "Ε" U0395 +<Multi_key> <g> <Z> : "Ζ" U0396 +<Multi_key> <g> <H> : "Η" U0397 +<Multi_key> <G> <T> : "Θ" U0398 +<Multi_key> <g> <I> : "Ι" U0399 +<Multi_key> <g> <K> : "Κ" U039A +<Multi_key> <g> <L> : "Λ" U039B +<Multi_key> <g> <M> : "Μ" U039C +<Multi_key> <g> <N> : "Ν" U039D +<Multi_key> <g> <C> : "Ξ" U039E +<Multi_key> <g> <O> : "Ο" U039F +<Multi_key> <g> <P> : "Π" U03A0 +<Multi_key> <g> <R> : "Ρ" U03A1 +<Multi_key> <g> <S> : "Σ" U03A3 +<Multi_key> <g> <T> : "Τ" U03A4 +<Multi_key> <g> <Y> : "Υ" U03A5 +<Multi_key> <g> <F> : "Φ" U03A6 +<Multi_key> <g> <X> : "Χ" U03A7 +<Multi_key> <g> <U> : "Ψ" U03A8 +<Multi_key> <g> <W> : "Ω" U03A9 + +## Greek lowercase +<Multi_key> <g> <a> : "α" U03B1 +<Multi_key> <g> <b> : "β" U03B2 +<Multi_key> <g> <g> : "γ" U03B3 +<Multi_key> <g> <d> : "δ" U03B4 +<Multi_key> <g> <e> : "ε" U03B5 +<Multi_key> <g> <z> : "ζ" U03B6 +<Multi_key> <g> <h> : "η" U03B7 +<Multi_key> <G> <t> : "θ" U03B8 +<Multi_key> <g> <i> : "ι" U03B9 +<Multi_key> <g> <k> : "κ" U03BA +<Multi_key> <g> <l> : "λ" U03BB +<Multi_key> <g> <m> : "μ" U03BC +<Multi_key> <g> <n> : "ν" U03BD +<Multi_key> <g> <c> : "ξ" U03BE +<Multi_key> <g> <o> : "ο" U03BF +<Multi_key> <g> <p> : "π" U03C0 +<Multi_key> <g> <r> : "ρ" U03C1 +<Multi_key> <G> <s> : "ς" U03C2 +<Multi_key> <g> <s> : "σ" U03C3 +<Multi_key> <g> <t> : "τ" U03C4 +<Multi_key> <g> <y> : "υ" U03C5 +<Multi_key> <g> <f> : "φ" U03C6 +<Multi_key> <G> <f> : "ɸ" U03D5 +<Multi_key> <g> <x> : "χ" U03C7 +<Multi_key> <g> <u> : "ψ" U03C8 +<Multi_key> <g> <w> : "ω" U03C9 + +## Weird symbols +# TODO: give these typeable names! +<Multi_key> <U2243> <U0338> : "≄" U2244 # NOT ASYMPTOTICALLY EQUAL TO +<Multi_key> <approximate> <U0338> : "≇" U2247 # NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO +<Multi_key> <U2248> <U0338> : "≉" U2249 # NOT ALMOST EQUAL TO +<Multi_key> <U224D> <U0338> : "≭" U226D # NOT EQUIVALENT TO +<Multi_key> <less> <U0338> : "≮" U226E # NOT LESS-THAN +<Multi_key> <leftcaret> <U0338> : "≮" U226E # NOT LESS-THAN +<Multi_key> <greater> <U0338> : "≯" U226F # NOT GREATER-THAN +<Multi_key> <rightcaret> <U0338> : "≯" U226F # NOT GREATER-THAN +<Multi_key> <lessthanequal> <U0338> : "≰" U2270 # NEITHER LESS-THAN NOR EQUAL TO +<Multi_key> <greaterthanequal> <U0338> : "≱" U2271 # NEITHER GREATER-THAN NOR EQUAL TO +<Multi_key> <U2272> <U0338> : "≴" U2274 # NEITHER LESS-THAN NOR EQUIVALENT TO +<Multi_key> <U2273> <U0338> : "≵" U2275 # NEITHER GREATER-THAN NOR EQUIVALENT TO +<Multi_key> <U2276> <U0338> : "≸" U2278 # NEITHER LESS-THAN NOR GREATER-THAN +<Multi_key> <U2277> <U0338> : "≹" U2279 # NEITHER GREATER-THAN NOR LESS-THAN +<Multi_key> <U227A> <U0338> : "⊀" U2280 # DOES NOT PRECEDE +<Multi_key> <U227B> <U0338> : "⊁" U2281 # DOES NOT SUCCEED +<Multi_key> <includedin> <U0338> : "⊄" U2284 # NOT A SUBSET OF +<Multi_key> <leftshoe> <U0338> : "⊄" U2284 # NOT A SUBSET OF +<Multi_key> <includes> <U0338> : "⊅" U2285 # NOT A SUPERSET OF +<Multi_key> <rightshoe> <U0338> : "⊅" U2285 # NOT A SUPERSET OF +<Multi_key> <U2286> <U0338> : "⊈" U2288 # NEITHER A SUBSET OF NOR EQUAL TO +<Multi_key> <U2287> <U0338> : "⊉" U2289 # NEITHER A SUPERSET OF NOR EQUAL TO +<Multi_key> <righttack> <U0338> : "⊬" U22AC # DOES NOT PROVE +<Multi_key> <U22A8> <U0338> : "⊭" U22AD # NOT TRUE +<Multi_key> <U22A9> <U0338> : "⊮" U22AE # DOES NOT FORCE +<Multi_key> <U22AB> <U0338> : "⊯" U22AF # NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE +<Multi_key> <U227C> <U0338> : "⋠" U22E0 # DOES NOT PRECEDE OR EQUAL +<Multi_key> <U227D> <U0338> : "⋡" U22E1 # DOES NOT SUCCEED OR EQUAL +<Multi_key> <U2291> <U0338> : "⋢" U22E2 # NOT SQUARE IMAGE OF OR EQUAL TO +<Multi_key> <U2292> <U0338> : "⋣" U22E3 # NOT SQUARE ORIGINAL OF OR EQUAL TO +<Multi_key> <U22B2> <U0338> : "⋪" U22EA # NOT NORMAL SUBGROUP OF +<Multi_key> <U22B3> <U0338> : "⋫" U22EB # DOES NOT CONTAIN AS NORMAL SUBGROUP +<Multi_key> <U22B4> <U0338> : "⋬" U22EC # NOT NORMAL SUBGROUP OF OR EQUAL TO +<Multi_key> <U22B5> <U0338> : "⋭" U22ED # DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL +<Multi_key> <U2ADD> <U0338> : "⫝̸" U2ADC # FORKING +<Multi_key> <underscore> <U2282> : "⊆" U2286 # _ ⊂ SUBSET OF OR EQUAL TO +<Multi_key> <U2282> <underscore> : "⊆" U2286 # ⊂ _ SUBSET OF OR EQUAL TO +<Multi_key> <underscore> <U2283> : "⊇" U2287 # _ ⊃ SUPERSET OF OR EQUAL TO +<Multi_key> <U2283> <underscore> : "⊇" U2287 # ⊃ _ SUPERSET OF OR EQUAL TO diff --git a/tw/services/files/Xresources b/tw/services/files/Xresources new file mode 100644 index 00000000..ba534392 --- /dev/null +++ b/tw/services/files/Xresources @@ -0,0 +1,13 @@ +!! ~/.Xresources: X resources and settings + +*TkTheme: clam + +Xft.antialias: true +Xft.dpi: 96 +Xft.hinting: true +Xft.hintstyle: hintfull +Xft.lcdfilter: lcddefault +Xft.rgba: rgb + +Xcursor.theme: Catppuccin-Mocha-Dark-Cursors +Xcursor.size: 16 diff --git a/tw/services/files/aerc/accounts.conf b/tw/services/files/aerc/accounts.conf new file mode 100644 index 00000000..5325ee03 --- /dev/null +++ b/tw/services/files/aerc/accounts.conf @@ -0,0 +1,97 @@ +# Note: when adding/removing/editing an account name here, edit +# [messages:account=] and [messages:folder=] sections in binds.conf to match! + +[Mythic] +source = imaps://timo%40twilken.net@oncilla.mythic-beasts.com +outgoing = smtps+plain://timo%40twilken.net@smtp-auth.mythic-beasts.com +source-cred-cmd = pass www/mythic-beasts/email/timo | head -1 +outgoing-cred-cmd = pass www/mythic-beasts/email/timo | head -1 +default = INBOX +from = Timo Wilken <timo@twilken.net> +archive = Archive +copy-to = Sent +postpone = Drafts +folders-sort = INBOX,Archive,Sent,Drafts +cache-headers = true +pgp-auto-sign = true +pgp-key-id = 53EC3C06856883DD92355BC22FC78504681F69B0 +pgp-opportunistic-encrypt = true + +[CERN] +# https://man.sr.ht/~rjarry/aerc/providers/microsoft.md#office365-with-xoauth2 +source = imaps+xoauth2://timo.wilken%40cern.ch@outlook.office365.com?client_id=9e5f94bc-e8a4-4e73-b8be-63364c29d753&token_endpoint=https://login.microsoftonline.com/common/oauth2/v2.0/token&scope=https://outlook.office.com/SMTP.Send https://outlook.office.com/IMAP.AccessAsUser.All offline_access +outgoing = smtp+xoauth2://timo.wilken%40cern.ch@smtp.office365.com:587?client_id=9e5f94bc-e8a4-4e73-b8be-63364c29d753&token_endpoint=https://login.microsoftonline.com/common/oauth2/v2.0/token&scope=https://outlook.office.com/SMTP.Send https://outlook.office.com/IMAP.AccessAsUser.All offline_access +# To authorize for the first time (to get refresh token): +# mutt_oauth2.py ~/.local/share/aerc/cern.tokens --authorize --authflow authcode --provider microsoft \ +# --email timo.wilken@cern.ch --client-id 9e5f94bc-e8a4-4e73-b8be-63364c29d753 --client-secret '' \ +# --encryption-pipe 'gpg --encrypt --recipient timo@twilken.net' +# Confirm empty client secret. When done, copy-paste ?code= value from final URL to the command-line. +# Then, to store the refresh token: +# gpg --decrypt ~/.local/share/aerc/cern.tokens | jq -r .refresh_token | pass insert -e -f cern/exol/refresh-token +source-cred-cmd = pass cern/exol/refresh-token +outgoing-cred-cmd = pass cern/exol/refresh-token +default = INBOX +from = Timo Wilken <timo.wilken@cern.ch> +aliases = twilken@cern.ch +archive = Archive +copy-to = Sent Items +postpone = Drafts +folders-sort = INBOX,Archive,Sent Items,Drafts +folders-exclude = Calendar,~Calendar/.*,Contacts,Conversation History,Journal,Notes,Tasks +cache-headers = true +pgp-auto-sign = true +pgp-key-id = C2249BBE5E8761C943A0CFA1B7B3914BF63ACD7C +# Don't auto-encrypt mail, even if we have the keys of all recipients. +pgp-opportunistic-encrypt = false + +[Gmail] +source = imaps://timo.21.wilken%40gmail.com@imap.gmail.com +outgoing = smtps+login://timo.21.wilken%40gmail.com@smtp.gmail.com +source-cred-cmd = pass www/google/app-passwords/mutt | head -1 +outgoing-cred-cmd = pass www/google/app-passwords/mutt | head -1 +default = INBOX +from = Timo Wilken <timo.21.wilken@gmail.com> +archive = [Gmail]/All Mail +copy-to = [Gmail]/Sent Mail +postpone = [Gmail]/Drafts +folders-sort = INBOX,[Gmail]/All Mail,[Gmail]/Sent Mail,[Gmail]/Drafts +folders-exclude = [Gmail],[Gmail]/Chats,[Gmail]/Important +cache-headers = true +trusted-authres = mx.google.com +pgp-auto-sign = true +pgp-key-id = 53EC3C06856883DD92355BC22FC78504681F69B0 +pgp-opportunistic-encrypt = true + +[Cantab] +source = imaps+xoauth2://tw466%40cantab.ac.uk@outlook.office365.com?client_id=9e5f94bc-e8a4-4e73-b8be-63364c29d753&token_endpoint=https://login.microsoftonline.com/common/oauth2/v2.0/token&scope=https://outlook.office.com/SMTP.Send https://outlook.office.com/IMAP.AccessAsUser.All offline_access +outgoing = smtp+xoauth2://tw466%40cantab.ac.uk@smtp-mail.outlook.com:587?client_id=9e5f94bc-e8a4-4e73-b8be-63364c29d753&token_endpoint=https://login.microsoftonline.com/common/oauth2/v2.0/token&scope=https://outlook.office.com/SMTP.Send https://outlook.office.com/IMAP.AccessAsUser.All offline_access +source-cred-cmd = pass cambridge/exol-refresh-token +outgoing-cred-cmd = pass cambridge/exol-refresh-token +default = INBOX +from = Timo Wilken <tw466@cantab.ac.uk> +archive = Archive +copy-to = Sent Items +postpone = Drafts +folders-sort = INBOX,Archive,Sent Items,Drafts +folders-exclude = Calendar,~Calendar/.*,Contacts,Conversation History,Journal,Notes,Tasks +cache-headers = true +pgp-auto-sign = true +pgp-key-id = 53EC3C06856883DD92355BC22FC78504681F69B0 +pgp-opportunistic-encrypt = true + +[Outlook] +source = imaps+xoauth2://timo_wilken%40live.co.uk@outlook.office365.com?client_id=9e5f94bc-e8a4-4e73-b8be-63364c29d753&token_endpoint=https://login.microsoftonline.com/common/oauth2/v2.0/token&scope=https://outlook.office.com/SMTP.Send https://outlook.office.com/IMAP.AccessAsUser.All offline_access +outgoing = smtp+xoauth2://timo_wilken%40live.co.uk@smtp-mail.outlook.com:587?client_id=9e5f94bc-e8a4-4e73-b8be-63364c29d753&token_endpoint=https://login.microsoftonline.com/common/oauth2/v2.0/token&scope=https://outlook.office.com/SMTP.Send https://outlook.office.com/IMAP.AccessAsUser.All offline_access +source-cred-cmd = pass www/microsoft/exol-refresh-token +outgoing-cred-cmd = pass www/microsoft/exol-refresh-token +default = INBOX +from = Timo Wilken <timo_wilken@live.co.uk> +archive = Archive +copy-to = Sent +postpone = Drafts +folders-sort = INBOX,Archive,Sent,Drafts +folders-exclude = Notes +cache-headers = true +pgp-auto-sign = true +pgp-key-id = 53EC3C06856883DD92355BC22FC78504681F69B0 +pgp-opportunistic-encrypt = true diff --git a/tw/services/files/aerc/accounts.work.conf b/tw/services/files/aerc/accounts.work.conf new file mode 100644 index 00000000..5d2fa7c7 --- /dev/null +++ b/tw/services/files/aerc/accounts.work.conf @@ -0,0 +1,26 @@ +[CERN] +# https://man.sr.ht/~rjarry/aerc/providers/microsoft.md#office365-with-xoauth2 +source = imaps+xoauth2://timo.wilken%40cern.ch@outlook.office365.com?client_id=9e5f94bc-e8a4-4e73-b8be-63364c29d753&token_endpoint=https://login.microsoftonline.com/common/oauth2/v2.0/token&scope=https://outlook.office.com/SMTP.Send https://outlook.office.com/IMAP.AccessAsUser.All offline_access +outgoing = smtp+xoauth2://timo.wilken%40cern.ch@smtp.office365.com:587?client_id=9e5f94bc-e8a4-4e73-b8be-63364c29d753&token_endpoint=https://login.microsoftonline.com/common/oauth2/v2.0/token&scope=https://outlook.office.com/SMTP.Send https://outlook.office.com/IMAP.AccessAsUser.All offline_access +# To authorize for the first time (to get refresh token): +# mutt_oauth2.py ~/.local/share/aerc/twilken.tokens --authorize --authflow authcode --provider microsoft \ +# --email timo.wilken@cern.ch --client-id 9e5f94bc-e8a4-4e73-b8be-63364c29d753 --client-secret '' \ +# --encryption-pipe 'gpg --encrypt --recipient C2249BBE5E8761C943A0CFA1B7B3914BF63ACD7C' +# Confirm empty client secret. When done, copy-paste ?code= value from final URL to the command-line. +# Then, to store the refresh token: +# gpg --decrypt ~/.local/share/aerc/twilken.tokens | jq -r .refresh_token | pass insert -e -f cern/exol/refresh-token +source-cred-cmd = pass cern/exol/refresh-token +outgoing-cred-cmd = pass cern/exol/refresh-token +default = INBOX +from = Timo Wilken <timo.wilken@cern.ch> +aliases = twilken@cern.ch +archive = Archive +copy-to = Sent Items +postpone = Drafts +folders-sort = INBOX,Archive,Sent Items,Drafts +folders-exclude = Calendar,~Calendar/.*,Contacts,Conversation History,Journal,Notes,Tasks +cache-headers = true +pgp-auto-sign = true +pgp-key-id = C2249BBE5E8761C943A0CFA1B7B3914BF63ACD7C +# Don't auto-encrypt mail, even if we have the keys of all recipients. +pgp-opportunistic-encrypt = false diff --git a/tw/services/files/aerc/aerc.conf b/tw/services/files/aerc/aerc.conf new file mode 100644 index 00000000..7473bc8b --- /dev/null +++ b/tw/services/files/aerc/aerc.conf @@ -0,0 +1,157 @@ +# aerc main configuration + +[general] +#default-save-path= +# Allow world-readable accounts.conf. This is fine as I don't store any +# passwords there, only "pass" commands. +unsafe-accounts-conf=true + +[ui] +# Describes the format for each row in a mailbox view. This field is compatible +# with mutt's printf-like syntax. +index-columns=num>4,flags>4,date<21,peers<17,subject<* +column-num={{.Number}} +column-flags={{.Flags | join ""}} +column-date={{.DateAutoFormat .Date.Local}} +column-peers={{.Peer | names | join ", "}} +column-subject={{.ThreadPrefix}}{{.Subject}} + +# See time.Time#Format at https://godoc.org/time#Time.Format +timestamp-format=Mon _2 Jan 2006 15:04 + +# List of space-separated criteria to sort the messages by, see *sort* +# command in *aerc*(1) for reference. Prefixing a criterion with "-r " +# reverses that criterion. +sort=-r date + +threading-enabled=true + +next-message-on-delete=false + +sidebar-width=24 + +styleset-name=catppuccin +pinned-tab-marker='📌' +# Use box-drawing characters for vertical and horizontal borders. +border-char-vertical=│ +border-char-horizontal=─ +# Use UTF-8 symbols to indicate PGP status of messages +icon-unencrypted= +icon-encrypted=🔒 +icon-signed=✔ +icon-signed-encrypted=✔🔒 +icon-unknown=✘ +icon-invalid=⚠ + +# Activates fuzzy search in commands and their arguments: the typed string is +# searched in the command or option in any position, and need not be +# consecutive characters in the command or option. +#fuzzy-complete=false + +[statusline] +status-columns=left<*,centre>=,right>* +column-left=[{{.Account}}] {{.StatusInfo}} +column-centre={{.PendingKeys}} +column-right={{.ContentInfo}} {{.TrayInfo}} + +# Defines the mode for displaying the status elements. +# Options: text, icon +display-mode=icon + +[viewer] +# Specifies the pager to use when displaying emails. Note that some filters +# may add ANSI codes to add color to rendered emails, so you may want to use a +# pager which supports ANSI codes. +pager='env LESSKEYIN=/dev/null less -iRM' + +# If an email offers several versions (multipart), you can configure which +# mimetype to prefer. For example, this can be used to prefer plaintext over +# html emails. +alternatives=text/plain,text/html + +# Layout of headers when viewing a message. To display multiple headers in the +# same row, separate them with a pipe, e.g. "From|To". Rows will be hidden if +# none of their specified headers are present in the message. +#header-layout=From|To,Cc|Bcc,Date,Subject + +[compose] +# Default header fields to display when composing a message. To display +# multiple headers in the same row, separate them with a pipe, e.g. "To|From". +#header-layout=To|From,Subject + +# Specifies the command to be used to tab-complete email addresses. Any +# occurrence of "%s" in the address-book-cmd will be replaced with what the +# user has typed so far. +# +# The command must output the completions to standard output, one completion +# per line. Each line must be tab-delimited, with an email address occurring as +# the first field. Only the email address field is required. The second field, +# if present, will be treated as the contact name. Additional fields are +# ignored. +# +# This parameter can also be set per account in accounts.conf. +address-book-cmd=khard email --parsable %s + +# Allow to address yourself when replying +reply-to-self=false + +# Warn before sending an email that matches the specified regexp but does not +# have any attachments. Leave empty to disable this feature. +# Uses Go's regexp syntax, documented at https://golang.org/s/re2syntax. The +# "(?im)" flags are set by default (case-insensitive and multi-line). +no-attachment-warning=^[^>]*(attach|Anhang|angehängt) + +[filters] +# Filters allow you to pipe an email body through a shell command to render +# certain emails differently, e.g. highlighting them with ANSI escape codes. +# +# The commands are invoked with sh -c. The following folders are appended to +# the system $PATH to allow referencing filters from their name only: +# +# ${XDG_CONFIG_HOME:-~/.config}/aerc/filters +# ${XDG_DATA_HOME:-~/.local/share}/aerc/filters +# $PREFIX/share/aerc/filters +# /usr/share/aerc/filters +# +# The following variables are defined in the filter command environment: +# +# AERC_MIME_TYPE the part MIME type/subtype +# AERC_FILENAME the attachment filename (if any) +# +# The first filter which matches the email's mimetype will be used, so order +# them from most to least specific. +# +# You can also match on non-mimetypes, by prefixing with the header to match +# against (non-case-sensitive) and a comma, e.g. subject,text will match a +# subject which contains "text". Use header,~regex to match against a regex. +text/plain=colorize.ansi +text/calendar=calendar +message/delivery-status=colorize.ansi +message/rfc822=colorize.ansi +#text/html=pandoc -f html -t plain | colorize +#text/html=html | colorize +text/html=lynx -display_charset=UTF-8 -force_html -dump -stdin +#text/*=bat -fP --file-name="$AERC_FILENAME" +#application/x-sh=bat -fP -l sh +#image/*=catimg -w $(tput cols) - +#subject,~Git(hub|lab)=lolcat -f +#from,thatguywhodoesnothardwraphismessages=fmt -w 72 | colorize + +[openers] +# Openers allow you to specify the command to use for the :open action on a +# per-MIME-type basis. +# +# {} is expanded as the temporary filename to be opened. If it is not +# encountered in the command, the temporary filename will be appened to the end +# of the command. +# +# Examples: +# text/html=surf -dfgms +# text/plain=gvim {} +125 +# message/rfc822=thunderbird +application/pdf=zathura +image/*=imv + +[hooks] +# Executed when a new email arrives in the selected folder +new-email=dunstify -a aerc -i mail-unread "New mail from $AERC_FROM_NAME" "$AERC_SUBJECT" diff --git a/tw/services/files/aerc/binds.conf b/tw/services/files/aerc/binds.conf new file mode 100644 index 00000000..0e88b571 --- /dev/null +++ b/tw/services/files/aerc/binds.conf @@ -0,0 +1,194 @@ +# Binds are of the form <key sequence> = <command to run> +# To use '=' in a key sequence, substitute it with "Eq": "<Ctrl+Eq>" +# If you wish to bind #, you can wrap the key sequence in quotes: "#" = quit +<C-p> = :prev-tab<Enter> +<C-n> = :next-tab<Enter> +<C-t> = :term<Enter> +? = :help keys<Enter> + +[messages] +q = :quit<Enter> + +j = :next<Enter> +<Down> = :next<Enter> +<C-d> = :next 50%<Enter> +<C-f> = :next 100%<Enter> +<PgDn> = :next 100%<Enter> + +k = :prev<Enter> +<Up> = :prev<Enter> +<C-u> = :prev 50%<Enter> +<C-b> = :prev 100%<Enter> +<PgUp> = :prev 100%<Enter> +g = :select 0<Enter> +G = :select -1<Enter> +"#" = :select<space> + +J = :next-folder<Enter> +K = :prev-folder<Enter> +H = :collapse-folder<Enter> +L = :expand-folder<Enter> + +"*" = :mark -a<Enter> +v = :mark -t<Enter> +V = :mark -T<Enter> +F = :flag -tx Flagged<Enter> +<C-r> = :read -t<Enter> +<semicolon> = :remark<Enter> + +T = :toggle-threads<Enter> + +<Enter> = :view<Enter> +A = :archive flat<Enter> +p = :split 25<Enter> +e = :envelope<Enter> + +m = :compose<Enter> +M = :mkdir<space> + +f = :forward -F<Enter> +a = :reply -aq<Enter> +r = :reply -q<Enter> + +C = :copy<space> +S = :save<space> +s = :move<space> +E = :export-mbox<space> +I = :import-mbox<space> + +c = :cf<space> +$ = :check-mail<Enter> +! = :term<space> +| = :pipe<space> + +/ = :search<space> +l = :filter<space> +n = :next-result<Enter> +N = :prev-result<Enter> +<Esc> = :clear<Enter>:unmark -a<Enter> + +[messages:folder=Drafts] +<Enter> = :recall<Enter> + +[view:account=Mythic] +D = :move Rubbish<Enter> +[messages:account=Mythic] +d = :move Rubbish<Enter> +D = :move Rubbish<Enter> +# We can't use both :account= and :folder= at the same time, unfortunately. +[messages:folder=Rubbish] +d = :delete<Enter> +D = :delete<Enter> + +[view:account=Wilken] +D = :move Rubbish<Enter> +[messages:account=Wilken] +d = :move Rubbish<Enter> +D = :move Rubbish<Enter> +[messages:folder=Rubbish] +d = :delete<Enter> +D = :delete<Enter> + +[view:account=CERN] +D = :move Deleted Items<Enter> +[messages:account=CERN] +d = :move Deleted Items<Enter> +D = :move Deleted Items<Enter> +[messages:folder=Deleted Items] +d = :delete<Enter> +D = :delete<Enter> + +[view:account=Gmail] +D = :move [Gmail]/Bin<Enter> +[messages:account=Gmail] +d = :move [Gmail]/Bin<Enter> +D = :move [Gmail]/Bin<Enter> +[messages:folder=[Gmail]/Bin] +d = :delete<Enter> +D = :delete<Enter> +[messages:folder=[Gmail]/Drafts] +<Enter> = :recall<Enter> + +[view:account=Cantab] +D = :move Deleted Items<Enter> +[messages:account=Cantab] +d = :move Deleted Items<Enter> +D = :move Deleted Items<Enter> +[messages:folder=Deleted Items] +d = :delete<Enter> +D = :delete<Enter> + +[view:account=Outlook] +D = :move Deleted<Enter> +[messages:account=Outlook] +d = :move Deleted<Enter> +D = :move Deleted<Enter> +[messages:folder=Deleted] +d = :delete<Enter> +D = :delete<Enter> + +[view] +/ = :toggle-key-passthrough<Enter>/ +q = :close<Enter> +O = :open<Enter> +S = :save<space> +| = :pipe<space> +A = :archive flat<Enter> + +<C-l> = :open-link <space> +<C-v> = :toggle-key-passthrough<Enter> + +f = :forward -F<Enter> +a = :reply -aq<Enter> +r = :reply -q<Enter> + +H = :toggle-headers<Enter> +<C-k> = :prev-part<Enter> +<C-j> = :next-part<Enter> +J = :next<Enter> +K = :prev<Enter> + +[view::passthrough] +$noinherit = true +$ex = <C-x> +<Esc> = :toggle-key-passthrough<Enter> + +[compose] +# Keybindings used when the embedded terminal is not selected in the compose view. +$noinherit = true +$ex = <C-x> +<C-k> = :prev-field<Enter> +<C-j> = :next-field<Enter> +<A-p> = :switch-account -p<Enter> +<A-n> = :switch-account -n<Enter> +<tab> = :next-field<Enter> +<C-p> = :prev-tab<Enter> +<C-n> = :next-tab<Enter> + +[compose::editor] +# Keybindings used when the embedded terminal is selected in the compose view. +$noinherit = true +$ex = <C-x> +<C-k> = :prev-field<Enter> +<C-j> = :next-field<Enter> +<C-p> = :prev-tab<Enter> +<C-n> = :next-tab<Enter> + +[compose::review] +# Keybindings used when reviewing a message to be sent +y = :send<Enter> +n = :abort<Enter> +p = :postpone<Enter> +q = :choose -o d discard abort -o p postpone postpone<Enter> +e = :edit<Enter> +a = :attach<space> +d = :detach<space> +v = :preview<Enter> +s = :sign<Enter> +c = :encrypt<Enter> + +[terminal] +$noinherit = true +$ex = <C-x> +<C-p> = :prev-tab<Enter> +<C-n> = :next-tab<Enter> diff --git a/tw/services/files/aerc/filters/colorize.ansi b/tw/services/files/aerc/filters/colorize.ansi new file mode 100755 index 00000000..c21fd804 --- /dev/null +++ b/tw/services/files/aerc/filters/colorize.ansi @@ -0,0 +1,134 @@ +#!/usr/bin/env -S awk -f +# Copyright (c) 2022 Robin Jarry +# Adapted for standard ANSI colors (for catppuccin theme) by Timo Wilken. + +BEGIN { + url = "\033[32m" # green + header = "\033[35m" # pink + signature = "\033[38m" # Surface 2 + diff_meta = "\033[1;37m" # bold white + diff_chunk = "\033[36m" # teal + diff_add = "\033[32m" # green + diff_del = "\033[31m" # red + quote_1 = "\033[38;5;15m" # Subtext 0 + quote_2 = "\033[37m" # Subtext 1 + quote_3 = "\033[38m" # Surface 2 + quote_4 = "\033[30m" # Surface 1 + quote_x = "\033[30m" # Surface 1 + bold = "\033[1m" + reset = "\033[0m" + # state + in_diff = 0 + in_signature = 0 + in_headers = 0 + in_body = 0 + # patterns + header_pattern = @/^[A-Z][[:alnum:]-]+:/ + url_pattern = @/[a-z]{2,6}:\/\/[[:graph:]]+|(mailto:)?[[:alnum:]_\+\.~\/-]*[[:alnum:]_]@[[:lower:]][[:alnum:]\.-]*[[:lower:]]/ + meta_pattern = @/^(diff --git|(new|deleted) file|similarity index|(rename|copy) (to|from)|index|---|\+\+\+) / +} +function color_quote(line) { + level = 0 + quotes = "" + while (line ~ /^>/) { + level += 1 + quotes = quotes ">" + line = substr(line, 2) + while (line ~ /^ /) { + quotes = quotes " " + line = substr(line, 2) + } + } + if (level == 1) { + color = quote_1 + } else if (level == 2) { + color = quote_2 + } else if (level == 3) { + color = quote_3 + } else if (level == 4) { + color = quote_4 + } else { + color = quote_x + } + if (line ~ meta_pattern) { + return color quotes bold line reset + } else if (line ~ /^\+/) { + return color quotes diff_add line reset + } else if (line ~ /^-/) { + return color quotes diff_del line reset + } + gsub(url_pattern, url "&" color, line) + return color quotes line reset +} +{ + # Strip carriage returns from line + sub(/\r$/, "") + + if (in_diff) { + if ($0 ~ /^-- ?$/) { + in_diff = 0 + in_signature = 1 + $0 = signature $0 reset + } else if ($0 ~ /^@@ /) { + gsub(/^@@[^@]+@@/, diff_chunk "&" reset) + } else if ($0 ~ meta_pattern) { + $0 = diff_meta $0 reset + } else if ($0 ~ /^\+/) { + $0 = diff_add $0 reset + } else if ($0 ~ /^-/) { + $0 = diff_del $0 reset + } else if ($0 !~ /^ / && $0 !~ /^$/) { + in_diff = 0 + in_body = 1 + if ($0 ~ /^>/) { + $0 = color_quote($0) + } else { + gsub(url_pattern, url "&" reset) + } + } + } else if (in_signature) { + gsub(url_pattern, url "&" signature) + $0 = signature $0 reset + } else if (in_headers) { + if ($0 ~ /^$/) { + in_headers = 0 + in_body = 1 + } else { + sub(header_pattern, header "&" reset) + gsub(url_pattern, url "&" reset) + } + } else if (in_body) { + if ($0 ~ /^>/) { + $0 = color_quote($0) + } else if ($0 ~ /^diff --git /) { + in_body = 0 + in_diff = 1 + $0 = diff_meta $0 reset + } else if ($0 ~ /^-- ?$/) { + in_body = 0 + in_signature = 1 + $0 = signature $0 reset + } else { + gsub(url_pattern, url "&" reset) + } + } else if ($0 ~ /^diff --git /) { + in_diff = 1 + $0 = diff_meta $0 reset + } else if ($0 ~ /^-- ?$/) { + in_signature = 1 + $0 = signature $0 reset + } else if ($0 ~ header_pattern) { + in_headers = 1 + sub(header_pattern, header "&" reset) + gsub(url_pattern, url "&" reset) + } else { + in_body = 1 + if ($0 ~ /^>/) { + $0 = color_quote($0) + } else { + gsub(url_pattern, url "&" reset) + } + } + + print +} diff --git a/tw/services/files/cursors.ini b/tw/services/files/cursors.ini new file mode 100644 index 00000000..c4eb9cdb --- /dev/null +++ b/tw/services/files/cursors.ini @@ -0,0 +1,4 @@ +[Icon Theme] +Name=Default +Comment=Default Cursor Theme +Inherits=Catppuccin-Mocha-Dark-Cursors diff --git a/tw/services/files/dunstrc b/tw/services/files/dunstrc new file mode 100644 index 00000000..c64d374f --- /dev/null +++ b/tw/services/files/dunstrc @@ -0,0 +1,98 @@ +# See dunst(5) for all configuration options -*- mode: conf -*- + +[global] + ### Display ### + + # Display notification on focused monitor. Possible modes are: + # mouse: follow mouse pointer + # keyboard: follow window with keyboard focus + # none: don't follow anything + # + # "keyboard" needs a window manager that exports the + # _NET_ACTIVE_WINDOW property. + # This should be the case for almost all modern window managers. + # + # If this option is set to mouse or keyboard, the monitor option + # will be ignored. + follow = mouse + + ### Geometry ### + + # dynamic width from 0 to 300 + # width = (0, 300) + # constant width of 300 + width = 300 + + # The maximum height of a single notification, excluding the frame. + height = 300 + + # Offset from the origin + # Leave 24pt space for polybar. + offset = 16x40 + + # Don't remove messages, if the user is idle (no mouse or keyboard input) + # for longer than idle_threshold seconds. + # Set to 0 to disable. + # A client can set the 'transient' hint to bypass this. See the rules + # section for how to disable this if necessary + idle_threshold = 120 + + ### Text ### + + font = Fira Sans 12 + + # The format of the message. Possible variables are: + # %a appname + # %s summary + # %b body + # %i iconname (including its path) + # %I iconname (without its path) + # %p progress value if set ([ 0%] to [100%]) or nothing + # %n progress value if set without any extra characters + # %% Literal % + # Markup is allowed + # format = "<b>%s</b>\n%b" + format = "<span size='x-small'>%a %p</span>\n<b>%s</b>\n%b" + + ### Icons ### + + # Recursive icon lookup. You can set a single theme, instead of having to + # define all lookup paths. + enable_recursive_icon_lookup = true + + # Set icon theme (only used for recursive icon lookup) + # You can also set multiple icon themes, with the leftmost one being used first. + # icon_theme = "Adwaita, breeze" + icon_theme = "Papirus-Dark, hicolor" + + ### History ### + + # Maximum amount of notifications kept in history + history_length = 100 + + ### Misc/Advanced ### + + # dmenu path. + dmenu = /usr/bin/env rofi -dmenu -p dunst: + + # Browser for opening urls in context menu. + browser = /usr/bin/env xdg-open + + ### mouse + + # Defines list of actions for each mouse event + # Possible values are: + # * none: Don't do anything. + # * do_action: Invoke the action determined by the action_name rule. If there is no + # such action, open the context menu. + # * open_url: If the notification has exactly one url, open it. If there are multiple + # ones, open the context menu. + # * close_current: Close current notification. + # * close_all: Close all notifications. + # * context: Open context menu for the notification. + # * context_all: Open context menu for all notifications. + # These values can be strung together for each mouse event, and + # will be executed in sequence. + mouse_left_click = close_current + mouse_middle_click = do_action, close_current + mouse_right_click = close_all diff --git a/tw/services/files/emacs-init.el b/tw/services/files/emacs-init.el new file mode 100644 index 00000000..0f20782d --- /dev/null +++ b/tw/services/files/emacs-init.el @@ -0,0 +1,1027 @@ +;;; init.el --- Emacs configuration. -*- lexical-binding: t -*- +;;; Commentary: +;;; Code: + +(startup-redirect-eln-cache + (expand-file-name "emacs/eln" (or (getenv "XDG_CACHE_HOME") "~/.cache/"))) +(add-hook 'after-init-hook #'native-compile-prune-cache) + +;; Load settings set through Custom. +;; (setq custom-file (locate-user-emacs-file "custom.el")) +;; (when (file-readable-p custom-file) +;; (load custom-file)) + +(defun tw/xdg-emacs-subdir (type name &optional create) + "Get the name of a file or directory called NAME under $XDG_<TYPE>_HOME/emacs. +If CREATE is true and the resulting directory does not exist, create it." + (let ((dir (expand-file-name + (concat "emacs/" (string-trim-right name "/")) + (pcase type + ('cache (or (getenv "XDG_CACHE_HOME") "~/.cache/")) + ('config (or (getenv "XDG_CONFIG_HOME") "~/.config/")) + ('data (or (getenv "XDG_DATA_HOME") "~/.local/share/")) + ;; The following two are Guix/GuixSD extensions. + ('log (or (getenv "XDG_LOG_HOME") "~/.local/var/log/")) + ('state (or (getenv "XDG_STATE_HOME") "~/.local/var/lib/")) + (_ (error "Unknown XDG directory type: %S" type)))))) + (when (and create (not (file-accessible-directory-p dir))) + (make-directory dir t)) + dir)) + +;; Global/built-in Custom settings +;; Apply these as early as possible so that e.g. the native-comp files go to the right place. +(mapc (apply-partially #'apply #'customize-set-variable) + `((native-comp-async-report-warnings-errors silent "Don't pop up Warnings buffer for native compilation.") + ;; Emacs GUI customization. + (inhibit-startup-screen t "Don't show the startup screen with help links.") + (menu-bar-mode nil "Hide the menu bar globally.") + (tool-bar-mode nil "Hide the tool bar globally.") + (tooltip-mode nil "Show tooltips in the echo area instead.") + (max-mini-window-height 3 "Let the echo area grow to a maximum of 3 lines, e.g. when using `eldoc-mode'.") + (scroll-up-aggressively 0.0 "Don't recenter the window if the point moves off the page.") + (scroll-down-aggressively 0.0 "Don't recenter the window if the point moves off the page.") + (pixel-scroll-precision-mode t "Enable pixel-by-pixel scrolling, e.g. to handle inline images.") + ;; Niceties. + (tramp-default-method "scpx" "ssh and scp hang forever. scpx is faster than sshx for large files.") + (global-hl-line-mode t "Highlight the current line in all buffers.") + (indicate-empty-lines t "Show a little marker in the margin for lines past EOF.") + (column-number-mode t "Show the column number in the statusline.") + (electric-pair-mode t "Auto-pair suitable characters like parentheses.") + (tab-always-indent complete "Enable completion-on-tab.") + (completion-cycle-threshold 6 "Allow cycling through completions if there are 6 or fewer of them.") + (completion-styles (basic partial-completion) "Enable fast completion styles.") + (shell-kill-buffer-on-exit t "Kill *shell* buffers as soon as their shell session exits.") + ;; Indentation, formatting. + (indent-tabs-mode nil "Always use spaces to indent.") + (sentence-end-double-space nil "Use a single space after a sentence.") + (fill-column 78 "Make hard-wrapped text a bit wider.") + (require-final-newline t "Always add a final newline on save, if there is none.") + ;; Make Emacs a good Guix citizen. + (package-archives nil "Don't fetch packages from the internet; only get them from Guix.") + ;; Default mode. + (major-mode text-mode "Use `text-mode' by default in new buffers, not `fundamental-mode'.") + ;; Recent files and history. Keep them out of ~/.config. + (package-user-dir ,(tw/xdg-emacs-subdir 'data "elpa") "Save ELPA-related files here.") + (auto-save-list-file-prefix ,(tw/xdg-emacs-subdir 'data "auto-save-list/saves-") "Put auto-save lists here.") + (make-backup-files nil "Don't create backup files. They're annoying.") + (backup-directory-alist (("." . ,(tw/xdg-emacs-subdir 'data "backup"))) "Put backup files in a sensible place.") + (backup-by-copying t "Avoid breaking hardlinks when making backup files.") + (auto-save-file-name-transforms + ;; `file-name-as-directory' is important, since Emacs takes the directory part when UNIQUIFY is t. + ((".*" ,(file-name-as-directory (tw/xdg-emacs-subdir 'data "auto-save" t)) t)) + "Put auto-save #files# in a sensible directory.") + (recentf-max-saved-items 1000 "Save lots of recently-opened files.") + (recentf-save-file ,(tw/xdg-emacs-subdir 'data "recentf.el") "Save recently-opened files here.") + (recentf-mode t "Save recently-opened files.") + (savehist-file ,(tw/xdg-emacs-subdir 'data "savehist.el") "Save minibuffer history here.") + (savehist-mode t "Save minibuffer history on quit."))) + +(defalias 'yes-or-no-p #'y-or-n-p + "Always use `y-or-n-p' when asking for confirmation.") + +;; Custom modes depending on file names. +(mapc (apply-partially #'add-to-list 'auto-mode-alist) + `((,(rx (or bos "/") "PKGBUILD" eos) . bash-ts-mode) + (,(rx ".install" eos) . bash-ts-mode) + (,(rx (or bos "/") "COMMIT_EDITMSG" eos) . diff-mode) ; useful for `git commit -v' + (,(rx bos "/tmp/neomutt-") . mail-mode) + (,(rx ".eml" eos) . mail-mode) + (,(rx "." (1+ anything) "rc" eos) . conf-unix-mode))) + +(add-to-list 'magic-mode-alist + `(,(rx "#!" (* (not space)) + (? "env" (+ space) (? "-S" (+ space))) + (or "guile" "racket")) + . scheme-mode)) + +(add-hook 'mail-mode-hook #'auto-fill-mode) + +(defun tw/show-trailing-whitespace () + "Highlight trailing spaces in the current buffer." + (setq-local show-trailing-whitespace t)) + +(mapc (lambda (hook) + (add-hook hook #'tw/show-trailing-whitespace)) + '(prog-mode-hook conf-mode-hook yaml-mode-hook alidist-mode-hook)) + +(defun tw/enable-word-wrap () + "Enable word wrapping." + (toggle-word-wrap +1)) +(add-hook 'markdown-mode-hook #'tw/enable-word-wrap) +(add-hook 'org-mode-hook #'tw/enable-word-wrap) + +;; `use-package' requirements. +(require 'package) +(package-initialize t) +(eval-when-compile + (require 'use-package)) +(use-package diminish) ; for using :diminish later +(use-package bind-key) ; for using :bind later + +;; Some packages below have `:commands (...) :demand t'. +;; We need :commands for the byte-compiler, but we want to load the package immediately. + +(use-package gcmh ; "garbage collector magic hack": run GC when not in focus + :config (gcmh-mode +1) + :diminish gcmh-mode) + +;; Look and feel +(set-face-attribute 'default nil :family "Hermit" :height 100) +;; For some reason, Emacs doesn't detect italic support, and falls back to +;; underlining. Stop it from doing this and use italics instead. +(set-face-attribute 'italic nil :slant 'italic :underline nil) + +(use-package catppuccin-theme + :load-path "./" + :custom + (catppuccin-flavor 'mocha "Use the darkest Catppuccin theme.") + (catppuccin-italic-comments t "Make comments italic. It looks nicer.") + (catppuccin-italic-variables t "Make variable names italic. It looks nicer.") + :config (catppuccin-reload)) + +(use-package smart-mode-line + :hook (after-init . sml/setup) + :custom + (sml/no-confirm-load-theme t "Stop Emacs from constantly asking for user confirmation.") + (sml/mode-width 'right "Move the minor-mode list to the right of the modeline.") + (sml/theme 'respectful "Make `smart-mode-line' blend in with the active theme.")) + +;; General editor behaviour. +;; TODO: Move from ivy + counsel to vertico + orderless + consult + marginalia +;; (+ embark?), to integrate better with vanilla Emacs and `completing-read'. +;; https://github.com/minad/vertico -- light completion engine +;; https://github.com/minad/vertico#child-frames-and-popups +;; https://github.com/minad/vertico#complementary-packages +;; https://github.com/minad/marginalia -- docstrings in M-x menu +;; https://github.com/oantolin/orderless -- regex search for vertico +;; https://github.com/minad/consult -- collection of commands using vertico +;; https://github.com/oantolin/embark -- make vertico better depending on thing at point + +(use-package ivy + :commands (ivy-mode) :demand t + :custom + (ivy-use-selectable-prompt t "Allow selecting the ivy input as-is.") + (ivy-use-virtual-buffers t "Show recentf and bookmarks in buffers list.") + :config (ivy-mode +1) + :diminish ivy-mode) + +(use-package counsel ; extra niceties for `ivy-mode' + :after (ivy evil) ; evil for :bind-ing to <leader> + :bind (("<leader>SPC" . counsel-M-x) ; <leader><leader> doesn't work + ("<leader>fr" . counsel-buffer-or-recentf) + :map evil-visual-state-map + ("<leader>SPC" . counsel-M-x)) + :commands (counsel-mode) :demand t + :config (counsel-mode +1) + :diminish counsel-mode) + +(use-package dash-docs + :custom + (dash-docs-docsets-path + (file-name-as-directory (tw/xdg-emacs-subdir 'data "dash-docsets" t)) + "Store docsets in the XDG data directory.") + (dash-docs-browser-func 'eww "Open documentation pages using `eww' instead of an external browser.") + (dash-docs-enable-debugging nil "Disable popping up useless warnings.")) + +(defun tw/counsel-dash-is-help () + "Install `counsel-dash-at-point' as `evil-lookup-func'." + ;; Note: `evil-lookup-func' is already set to something else by + ;; `tw/help-is-eldoc' for `eglot-mode'. + (setq-local evil-lookup-func #'counsel-dash-at-point + counsel-dash-docsets + (cl-case major-mode + (lisp-mode '("Common Lisp")) + ((python-mode python-ts-mode) '("Python 3")) + (c++-mode '("C++")) + (cmake-mode '("CMake")) + (puppet-mode '("Puppet")) + (yaml-mode '("Ansible")) + (tcl-mode '("Tcl")) + (html-mode '("HTML" "CSS")) + ((css-mode css-ts-mode) '("CSS")) + (web-mode '("HTML" "CSS"))))) + +(use-package counsel-dash + :after (dash-docs which-key) + :commands (counsel-dash-at-point) :demand t + :init (which-key-add-key-based-replacements + "<leader>d" '("docs" . "Documentation")) + :bind (("<leader>K" . counsel-dash-at-point) + ("<leader>dK" . counsel-dash) + ("<leader>di" . counsel-dash-install-docset) + ("<leader>da" . counsel-dash-activate-docset) + ("<leader>dd" . counsel-dash-deactivate-docset)) + :hook (( lisp-mode python-mode python-ts-mode cmake-mode c++-mode puppet-mode yaml-mode + tcl-mode html-mode css-mode css-ts-mode web-mode) + . tw/counsel-dash-is-help) + :config + ;; Activate all installed docsets by default. + (setq counsel-dash-common-docsets (dash-docs-installed-docsets))) + +(use-package rainbow-mode + :after (evil) + :bind (("<leader>tR" . rainbow-mode))) + +(use-package form-feed + :commands (global-form-feed-mode) :demand t + :config (global-form-feed-mode +1) + :diminish form-feed-mode) + +(use-package display-line-numbers + ;; Included in Emacs >= 26. Better than `linum-mode'. + ;; There is also `global-display-line-numbers-mode', but that also + ;; enables line numbers in help windows, which I don't want. + :hook (prog-mode conf-mode yaml-mode alidist-mode)) + +(use-package which-key + :commands (which-key-mode) :demand t + :config (which-key-mode +1) + :diminish which-key-mode) + +(use-package undo-tree + :after (evil) ; for our :bind-ing + :bind (("<leader>U" . undo-tree-visualize)) + :custom + (undo-tree-history-directory-alist + `(("." . ,(file-name-as-directory (tw/xdg-emacs-subdir 'data "undo-tree-history")))) + "Store all `undo-tree' history in a single directory, instead of next to the associated file.") + :commands (global-undo-tree-mode) + :demand t ; this is required so that the :config stanza is actually run asap despite :bind + :config (global-undo-tree-mode +1) + :diminish undo-tree-mode) + +;; IDE-like features. +(use-package project + :after (which-key evil) + :init + (which-key-add-key-based-replacements + "<leader>p" '("project" . "Project")) + (evil-define-key '(normal visual) 'global + (kbd "<leader>fp") #'project-find-file) ; also <leader>pf + :bind-keymap ("<leader>p" . project-prefix-map)) + +(use-package vc + :after (which-key evil) + :init (which-key-add-key-based-replacements + "<leader>v" '("vc" . "Version control") + "<leader>vM" '("merge" . "Version control merging")) + :bind-keymap ("<leader>v" . vc-prefix-map)) + +(use-package log-edit + :after (evil vc) + :config + (evil-define-key '(normal visual) log-edit-mode-map + (kbd "<localleader>\\") #'log-edit-done + (kbd "<localleader>a") #'log-edit-insert-changelog + (kbd "<localleader>d") #'log-edit-show-diff + (kbd "<localleader>f") #'log-edit-show-files + (kbd "<localleader>k") #'log-edit-kill-buffer + (kbd "<localleader>w") #'log-edit-generate-changelog-from-diff)) + +(use-package company + :config (global-company-mode +1) + :diminish company-mode) + +(use-package company-quickhelp + :after (company) + :config (company-quickhelp-mode +1) + :diminish company-quickhelp-mode) + +(use-package company-posframe + :after (company) + :config (company-posframe-mode +1) + :diminish company-posframe-mode) + +(use-package flyspell + :hook mail-mode) + +(use-package flymake + :after (evil which-key) + :demand t ; needed for `flymake-collection' + :hook (prog-mode yaml-mode alidist-mode) + :init (which-key-add-key-based-replacements + "<leader>e" '("errors" . "Flymake")) + :bind (("<leader>eb" . flymake-start) + ("<leader>ec" . display-local-help) ; Show the error message at point in the minibuffer. + ; `flymake' also shows it using `eldoc', but documentation + ; seems to override error messages. + ; `flymake-show-diagnostic' only says "Nothing at point". + ("<leader>el" . flymake-show-buffer-diagnostics) + ("<leader>ep" . flymake-show-project-diagnostics) + ("<leader>en" . flymake-goto-next-error) + ("<leader>eN" . flymake-goto-prev-error) + ("<leader>ev" . flymake-running-backends) + ("<leader>eV" . flymake-disabled-backends)) + :custom + (flymake-suppress-zero-counters nil "Show severity counters even when they are zero.")) + +(use-package flymake-collection + :after (flymake) + :demand t ; we need it loaded now + ;; This needs to be called in `after-init-hook' so that all other + ;; packages' `:flymake-hook's are processed before f-c-hook-setup is + ;; called. See https://github.com/mohkale/flymake-collection. + :hook (after-init . flymake-collection-hook-setup)) + +;; Language Server Protocol. +(defun tw/help-is-eldoc (&rest _) + "Set up `evil-lookup-func' to display the `eldoc' buffer." + (when (eglot-managed-p) + (setq-local evil-lookup-func #'eldoc-doc-buffer))) + +(use-package eglot + ;; I have clang (for clangd) and python-lsp-server installed. + ;; `:hook' adds `-mode' to the package name, but `eglot-mode' doesn't exist. + :hook (((python-mode python-ts-mode c-mode c++-mode c-or-c++-ts-mode) . eglot-ensure) + (eglot-managed-mode . tw/help-is-eldoc)) + :commands (eglot) + :functions (eglot-managed-p) + :custom + (eglot-autoshutdown t "Shut down language servers after deleting their last associated buffer.") + (eglot-sync-connect 0.1 "Wait for the language server in the background if it takes longer than 100ms.")) + +;; Tree-sitter +;; TODO: Try any/all of the following new tree-sitter-based major modes. +;; Enable them using the following, replacing the relevant "old" major mode: +;; (add-to-list 'major-mode-remap-alist '(ruby-mode . ruby-ts-mode)) +;; New major mode 'css-ts-mode'. +;; New major mode 'dockerfile-ts-mode'. +;; New major mode 'ruby-ts-mode'. + +(mapc (lambda (dir) + (add-to-list 'treesit-extra-load-path (file-name-as-directory (expand-file-name dir)))) + '("/run/current-system/profile/lib/tree-sitter" + "~/.guix-home/profile/lib/tree-sitter" + "~/.guix-profile/lib/tree-sitter")) + +(use-package treesit + :custom + (treesit-font-lock-level 4 "Enable Angry Fruit Salad mode.")) + +;; Non-LSP language modes. +(use-package c-ts-mode + :init + (add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode)) + (add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode)) + (add-to-list 'major-mode-remap-alist '(c-or-c++-mode . c-or-c++-ts-mode))) + +(use-package cmake-ts-mode + :mode (rx (or (: (or bos "/") "CMakeLists.txt") ".cmake") eos)) + +(use-package json-ts-mode + :mode (rx ".json" eos) + :config + (evil-define-key '(normal visual) json-ts-mode-map + (kbd "<localleader>==") #'json-pretty-print + (kbd "<localleader>=b") #'json-pretty-print-buffer + (kbd "<localleader>=o") #'json-pretty-print-ordered + (kbd "<localleader>=B") #'json-pretty-print-buffer-ordered)) + +(use-package gnuplot + :commands (gnuplot-mode gnuplot-make-buffer) + :mode ((rx ".gnuplot" eos) . gnuplot-mode)) + +(use-package graphviz-dot-mode + :mode (rx ".dot" eos) + :custom (graphviz-dot-view-command "xdot %s" "Use xdot for previewing graphviz files.")) + +(use-package haskell-mode + :mode (rx (or ".hs" ".lhs" ".hsc" ".cpphs" ".c2hs") eos)) + +(use-package hcl-mode + :mode (rx "." (or "hcl" "nomad") eos)) + +(use-package mmm-mode + :commands (mmm-mode) + ;; Don't highlight submodes specially at all. The default background is annoying. + :custom-face (mmm-default-submode-face ((t (:background unspecified))))) + +(use-package puppet-mode + :mode (rx ".pp" eos)) + +(use-package python + :after (flymake-collection) + :commands (python-mode python-ts-mode) + :mode (((rx ".py" (? (or ?\i ?\w)) eos) . python-ts-mode) + ((rx ".aurora" eos) . python-ts-mode)) + :config + ;; Disable all flymake-collection linters in Python modes, since eglot/pylsp + ;; should take care of it. It doesn't do type checking, so enable mypy. + (cl-dolist (mode '(python-ts-mode python-mode)) + (add-to-list 'flymake-collection-config `(,mode flymake-mypy)))) + +(use-package rec-mode + :mode (rx ".rec" eos)) + +(use-package sh-script ; built-in + ;; Use `bash-ts-mode' instead of `sh-mode' if possible. + ;; `bash-ts-mode' falls back to `sh-mode' if necessary. + ;; Manually configuring :mode etc would be annoying, since there are a lot of entries. + :config (add-to-list 'major-mode-remap-alist '(sh-mode . bash-ts-mode)) + :custom (sh-basic-offset 2 "Use 2 spaces for `sh-mode' indents.")) + +(use-package tcl + :mode ((rx ".tcl" eos) . tcl-mode) + :magic ((rx "#%Module1.0") . tcl-mode)) + +(use-package web-mode + :mode (rx "." (or "htm" "html" "js" "css" "scss") eos) + :custom + (web-mode-css-indent-offset 2 "Indent CSS by two spaces.")) + +(use-package yaml-mode + :mode (rx (or (seq ".y" (? "a") "ml") + (seq "aliPublish" (* (not ?/)) ".conf")) + eos)) + +(defun tw/ledger-format-on-save () + "Re-indent the entire file." + ;; Subset of `ledger-mode-clean-buffer'. That also sorts the buffer, which I don't want. + (save-excursion + (let ((start (point-min-marker)) + (end (point-max-marker))) + (untabify start end) + (ledger-post-align-postings start end) + (ledger-mode-remove-extra-lines)))) + +(defun tw/enable-ledger-format-on-save () + "Enable reformating the open file on save." + (add-hook 'before-save-hook #'tw/ledger-format-on-save 0 t)) + +(use-package ledger-mode + :after (evil) + :commands (ledger-mode) + :mode (rx ".journal" eos) + :hook (ledger-mode . tw/enable-ledger-format-on-save) + :custom + (ledger-default-date-format ledger-iso-date-format "Use hledger-style dates.") + (ledger-reconcile-default-date-format ledger-iso-date-format "Use hledger-style dates.") + (ledger-reconcile-default-commodity "€" "Make euros the default currency.") + (ledger-post-account-alignment-column 2 "Use 2-space indents.") + (ledger-post-amount-alignment-at :decimal "Align amounts at decimal points/commas.") + (ledger-post-amount-alignment-column 52 "Align amounts' decimal points to the 52nd column.") + (ledger-highlight-xact-under-point nil "Don't highlight the transaction at point.") + :config + (evil-define-key 'normal ledger-mode-map + (kbd "TAB") #'ledger-indent-line)) + +(use-package lisp + :init (which-key-add-key-based-replacements + "<leader>k" '("sexp-nav" . "S-expression navigation")) + :bind (("<leader>kl" . forward-sexp) + ("<leader>kh" . backward-sexp) + ("<leader>kL" . forward-list) + ("<leader>kH" . backward-list) + ("<leader>kj" . down-list) + ("<leader>kk" . up-list) + ("<leader>kK" . backward-up-list) + ("<leader>kd" . kill-sexp) + ("<leader>kD" . backward-kill-sexp) + ("<leader>kb" . beginning-of-defun) + ("<leader>kB" . beginning-of-defun-comments) + ("<leader>ke" . end-of-defun) + ("<leader>kv" . mark-sexp) + ("<leader>kV" . mark-defun) + ("<leader>kN" . narrow-to-defun) + ("<leader>ks" . insert-pair) + ("<leader>kr" . raise-sexp) + ("<leader>kc" . check-parens))) + +(defun tw/resize-repl-window () + "Make the REPL window small, so it stays out of the way." + (shrink-window (- (window-height) 5))) + +(use-package geiser + :after (evil) + :commands (geiser + geiser-eval-buffer geiser-eval-definition geiser-eval-region + geiser-eval-last-sexp geiser-mode-switch-to-repl + geiser-mode-switch-to-repl-and-enter) + :hook ((scheme-mode . geiser-autodoc-mode) + (geiser-repl-mode . tw/resize-repl-window)) + :config + (evil-define-key '(normal visual) scheme-mode-map + (kbd "<localleader>z") #'geiser-mode-switch-to-repl + (kbd "<localleader>Z") #'geiser-mode-switch-to-repl-and-enter + (kbd "<localleader>eb") #'geiser-eval-buffer + (kbd "<localleader>ef") #'geiser-eval-definition + (kbd "<localleader>er") #'geiser-eval-region + (kbd "<localleader>el") #'geiser-eval-last-sexp) + :defines scheme-mode-map) + +(use-package geiser-guile + :after (geiser)) + +(use-package sly + :after (evil) + :hook ((lisp-mode . sly-mode) ; `common-lisp-mode' is `lisp-mode'. + (sly-mrepl-mode . tw/resize-repl-window)) + :config + (evil-define-key '(normal visual) lisp-mode-map + (kbd "<localleader>C-c") #'sly-interrupt + (kbd "<localleader>z") #'sly + (kbd "<localleader>Z") #'sly-mrepl-sync + (kbd "<localleader>i") #'sly-inspect + (kbd "<localleader>D") #'sly-disassemble-symbol + (kbd "<localleader>E") #'sly-edit-value + (kbd "<localleader>eT") #'sly-list-threads ; eval requests get a new thread each + (kbd "<localleader>e:") #'sly-interactive-eval + (kbd "<localleader>el") #'sly-eval-last-expression + (kbd "<localleader>ep") #'sly-pprint-eval-last-expression + (kbd "<localleader>eb") #'sly-eval-buffer + (kbd "<localleader>ef") #'sly-eval-defun + (kbd "<localleader>er") #'sly-eval-region + (kbd "<localleader>eF") #'sly-compile-defun + (kbd "<localleader>eB") #'sly-compile-file + (kbd "<localleader>eL") #'sly-compile-and-load-file + (kbd "<localleader>eR") #'sly-compile-region + (kbd "<localleader>eU") #'sly-undefine-function + (kbd "<localleader>eM") #'sly-remove-method + (kbd "<localleader>dd") #'sly-describe-symbol + (kbd "<localleader>df") #'sly-describe-function + (kbd "<localleader>da") #'sly-apropos + (kbd "<localleader>dA") #'sly-apropos-all + (kbd "<localleader>dg") #'sly-edit-definition + (kbd "<localleader>dC-o") #'sly-pop-find-definition-stack + (kbd "<localleader>dG") #'sly-edit-uses + (kbd "<localleader>dwc") #'sly-who-calls + (kbd "<localleader>dwC") #'sly-calls-who + (kbd "<localleader>dwr") #'sly-who-references + (kbd "<localleader>dwb") #'sly-who-binds + (kbd "<localleader>dws") #'sly-who-sets + (kbd "<localleader>dwm") #'sly-who-macroexpands + (kbd "<localleader>dwS") #'sly-who-specializes + (kbd "<localleader>dhs") #'hyperspec-lookup ; hyperspec.el is bundled with sly; opens in browser + (kbd "<localleader>dhf") #'hyperspec-lookup-format + (kbd "<localleader>dhm") #'hyperspec-lookup-reader-macro + (kbd "<localleader>cl") #'sly-list-connections + (kbd "<localleader>cn") #'sly-next-connection + (kbd "<localleader>cp") #'sly-prev-connection + (kbd "<localleader>m1") #'sly-expand-1 + (kbd "<localleader>mm") #'sly-macroexpand-all + (kbd "<localleader>mf") #'sly-format-string-expand + (kbd "<localleader>tt") #'sly-trace-dialog-toggle-trace + (kbd "<localleader>ts") #'sly-trace-dialog + (kbd "<localleader>tf") #'sly-toggle-trace-fdefinition + (kbd "<localleader>tF") #'sly-untrace-all + (kbd "<localleader>ss") #'sly-stickers-dwim ; an ephemeral `print' around the thing at point + (kbd "<localleader>sr") #'sly-stickers-replay + (kbd "<localleader>sb") #'sly-stickers-toggle-break-on-stickers + (kbd "<localleader>sf") #'sly-stickers-fetch + (kbd "<localleader>sn") #'sly-stickers-next-sticker + (kbd "<localleader>sp") #'sly-stickers-prev-sticker + (kbd "<localleader>ta") #'sly-autodoc-mode) + :custom + (sly-mrepl-history-file-name (tw/xdg-emacs-subdir 'data "sly-mrepl-history"))) + +;; Org-mode +(use-package org + :commands (org-mode) + :mode ((rx ".org" eos) . org-mode) + :custom + (org-latex-src-block-backend 'minted "Colourise source code.") + (org-latex-packages-alist + '(("" "svg") + ("" "minted")) + "Use svg and syntax highlighting packages.") + (org-latex-pdf-process + '("latexmk -shell-escape -f -pdf -%latex -interaction=nonstopmode -output-directory=%o %f") + "Allow -shell-escape needed by svg and minted packages.")) + +(use-package ob ; org-babel + :after (org) + :custom + (org-confirm-babel-evaluate nil "Allow running code blocks without confirmation.") + ;; List of supported languages: + ;; https://orgmode.org/worg/org-contrib/babel/languages/index.html + (org-babel-load-languages + '((emacs-lisp . t) + (lisp . t) + (dot . t) + (python . t) + (gnuplot . t) + (rec . t)) ; see `ob-rec' below + "Load bindings for more languages for use in #+begin_src blocks.")) + +(defun tw/latex-section-commands (name) + "Create a pair of section commands like (\"\\NAME{%s}\" . \"\\NAME*{%s}\"). +For use in `org-latex-classes'." + (cons (format "\\%s{%%s}" name) (format "\\%s*{%%s}" name))) +(defconst tw/latex-part (tw/latex-section-commands "part") + "Part LaTeX commands for `org-latex-classes'.") +(defconst tw/latex-chapter (tw/latex-section-commands "chapter") + "Chapter LaTeX commands for `org-latex-classes'.") +(defconst tw/latex-section-and-below + (mapcar #'tw/latex-section-commands + '("section" "subsection" "subsubsection" "paragraph" "subparagraph")) + "Section to subparagraph LaTeX commands for `org-latex-classes'.") + +(use-package ox-latex ; org-export-latex + :after (org) + :custom + (org-latex-classes + `(("paperlike" "\\documentclass{paperlike}" . ,tw/latex-section-and-below) + ("examtext" "\\documentclass{examtext}" . ,tw/latex-section-and-below) + ("minutes" "\\documentclass{minutes}" . ,tw/latex-section-and-below) + ("mapreport" "\\documentclass{mapreport}" ,tw/latex-chapter . ,tw/latex-section-and-below) + ("pt3report" "\\documentclass{pt3report}" ,tw/latex-chapter . ,tw/latex-section-and-below) + ("article" "\\documentclass{article}" . ,tw/latex-section-and-below) + ("scrartcl" "\\documentclass{scrartcl}" . ,tw/latex-section-and-below) + ("report" "\\documentclass{report}" ,tw/latex-part ,tw/latex-chapter . ,tw/latex-section-and-below) + ("report-noparts" "\\documentclass{report}" ,tw/latex-chapter . ,tw/latex-section-and-below) + ("book" "\\documentclass{book}" ,tw/latex-part ,tw/latex-chapter . ,tw/latex-section-and-below) + ("book-noparts" "\\documentclass{book}" ,tw/latex-chapter . ,tw/latex-section-and-below) + ("checklist" "\\documentclass{checklist}" . ,tw/latex-section-and-below)) + "Define more documentclasses for org-latex.")) + +(use-package outline + :commands (outline-mode outline-minor-mode) + :custom + ;; Mirror the default "C-c @" binding for `outline-minor-mode'. + (outline-minor-mode-prefix (kbd "<localleader>@") "Use localleader for `outline-minor-mode' keybindings.")) + +;; My own custom packages, and stuff that isn't on MELPA. +(use-package actionlint + :after (flymake) + :load-path "include/" + :hook ((yaml-mode yaml-ts-mode) . actionlint-setup)) + +(use-package alidist-mode + :after (flymake) + :load-path "include/" + :commands (alidist-mode) + :mode (rx (or bot "/") "alidist/" (1+ (not ?\/)) ".sh" eot)) + +(use-package flymake-guile + :after (flymake) + :load-path "include/" + :hook (scheme-mode . flymake-guile-enable)) + +(use-package bemscript-mode + :load-path "include/" + :mode (rx ".bem" eos)) + +(use-package ifm-mode + :load-path "include/" + :mode (rx ".ifm" eos)) + +(use-package pam-env-mode + :load-path "include/" + :mode (rx (or bos "/") (or "pam_env.conf" ".pam_environment") eos)) + +(use-package environmentd-mode + :load-path "include/" + :mode (rx (or bos "/") + (or (: (? "etc/") "environment") + (: ".environment.d/" (1+ (not ?\/)) ".conf")) + eos)) + +(use-package ob-rec + ;; `org-babel' hooks for `rec-mode' + :after (org ob rec-mode) + :load-path "include/") + +(use-package vcard-mode + :load-path "include/" + :mode (rx "." (or "vcf" "vcard") eos)) + +;; Vim keybindings. +(defun tw/switch-to-other-buffer () + "Switch to the last-used buffer." + (interactive) + (switch-to-buffer (other-buffer))) + +(defun tw/new-buffer () + "Open a new, empty buffer." + (interactive) + (switch-to-buffer (generate-new-buffer "untitled"))) + +(defun tw/delete-current-buffer-file () + "Ask for confirmation, then delete the file associated with the current buffer." + (interactive) + (let ((buffer (current-buffer))) + (when (yes-or-no-p (concat "Delete `" (buffer-file-name buffer) "'?")) + (delete-file (buffer-file-name buffer)) + (kill-buffer buffer)))) + +(use-package evil + :after (which-key) + :commands (evil-mode evil-ex-nohighlight) + :init (setq evil-want-keybinding nil) ; evil-collection needs this + :custom + (evil-echo-state nil "Don't show the '--- INSERT ---' string in the echo area on evil state changes.") + (evil-undo-system 'undo-tree "Use `undo-tree' for evil's undo-redo function.") + (evil-search-module 'evil-search "Use evil's built-in search function, for search history support.") + (evil-want-minibuffer t "Use evil bindings in the minibuffer too.") + (evil-want-C-u-scroll t "Scroll on C-u in normal mode, not `universal-argument'.") + (evil-want-C-u-delete t "Delete line on C-u in insert mode, not `universal-argument'.") + (evil-want-Y-yank-to-eol t "Yank from point to end-of-line on Y.") + (evil-symbol-word-search t "Always search by full variable names when using * and #.") + :config + (evil-mode +1) + (evil-set-leader '(normal visual) (kbd "SPC")) ; <leader> + (evil-set-leader '(normal visual) (kbd "\\") t) ; <localleader> + (evil-define-key '(normal motion) diff-mode-shared-map ; not `diff-mode-map', else toggling `read-only-mode' destroys the binding + (kbd "<localleader>\\") #'read-only-mode) ; mirror default binding from evil-collection + (evil-define-key '(normal insert visual replace) 'global + (kbd "C-s") #'save-buffer) + ;; Global major-mode-independent keys should be defined here. Major + ;; mode-dependent keys (e.g. for launching a REPL) should go under + ;; <localleader> instead. Use `use-package' `:bind' for those. + (evil-define-key '(normal visual) 'global + ;; These keybindings mirror the default Spacemacs ones because I have + ;; muscle memory of those. + (kbd "<leader>:") #'eval-expression + (kbd "<leader>TAB") #'tw/switch-to-other-buffer + (kbd "<leader>bb") #'switch-to-buffer + (kbd "<leader>bd") #'kill-current-buffer + (kbd "<leader>bn") #'tw/new-buffer + (kbd "<leader>br") #'revert-buffer-quick + (kbd "<leader>bs") #'scratch-buffer + (kbd "<leader>bw") #'read-only-mode + (kbd "<leader>bx") #'kill-buffer-and-window + (kbd "<leader>fd") #'tw/delete-current-buffer-file + (kbd "<leader>ff") #'find-file + (kbd "<leader>fR") #'rename-visited-file + (kbd "<leader>fs") #'save-buffer + (kbd "<leader>h") help-map + (kbd "<leader>hw") #'which-key-show-top-level + (kbd "<leader>sc") #'evil-ex-nohighlight + (kbd "<leader>td") #'toggle-debug-on-error + (kbd "<leader>tf") #'auto-fill-mode + (kbd "<leader>tl") #'toggle-truncate-lines + (kbd "<leader>tn") #'display-line-numbers-mode + (kbd "<leader>u") #'universal-argument + (kbd "<leader>w") evil-window-map + (kbd "<leader>wd") #'evil-window-delete ; analogous to "<leader>bd" + (kbd "<leader>wx") #'kill-buffer-and-window) ; analogous to "<leader>bx" + (which-key-add-key-based-replacements + ;; Names are a `cons' of a short name and a long name. + ;; E.g. for <leader>b, "buffer" is shown under "b" in the "<leader>" menu, + ;; while "Buffers" is shown as the title in the "<leader>b" menu. + "<leader>b" '("buffer" . "Buffers") + "<leader>f" '("file" . "Files") + "<leader>h" '("help" . "General help and documentation") + "<leader>q" '("quit" . "Finish editing the current buffer in emacsclient") + "<leader>s" '("search" . "Search operations and options") + "<leader>t" '("toggle" . "Toggles and quick settings") + "<leader>w" '("window" . "Windows")) + :functions (evil-define-key evil-set-leader + evil-define-key* evil-window-delete evil-delay) + :defines (evil-visual-state-map)) + +(use-package evil-collection + :after (evil) + :commands (evil-collection-init) :demand t + :config (evil-collection-init) + :diminish evil-collection-unimpaired-mode + :custom + ;; Without `evil-collection-key-blacklist', in `diff-mode', space isn't + ;; assigned to the leader key automatically, unlike in other modes. + (evil-collection-key-blacklist '("SPC" "\\") "Don't bind to our leader keys at all.") + (evil-collection-setup-minibuffer t "Use evil-collection in minibuffer to match `evil-want-minibuffer'.")) + +(use-package evil-org + :after (evil org) + :hook org-mode + :config + (evil-define-key '(normal visual) org-mode-map + (kbd "<localleader>\\") #'org-ctrl-c-ctrl-c + (kbd "<localleader>ib") #'org-insert-structure-template + (kbd "<localleader>id") #'org-insert-drawer + (kbd "<localleader>iD") #'org-insert-time-stamp + (kbd "<localleader>ih") #'org-insert-heading + (kbd "<localleader>iH") #'org-insert-subheading + (kbd "<localleader>it") #'org-insert-todo-heading + (kbd "<localleader>iT") #'org-insert-todo-subheading + (kbd "<localleader>ii") #'org-insert-item + (kbd "<localleader>il") #'org-insert-link + (kbd "<localleader>p") #'org-set-property + (kbd "<localleader>t") #'org-set-tags + ;; Source code block editing + (kbd "<localleader>'") #'org-edit-src-code + (kbd "<localleader>e") #'org-export-dispatch) + (evil-define-key '(normal visual) org-src-mode-map + (kbd "<localleader>'") #'org-edit-src-exit + (kbd "<localleader>\\") #'org-edit-src-save + (kbd "<localleader>a") #'org-edit-src-abort)) + +(use-package evil-replace-with-register + :after (evil) + :commands (evil-replace-with-register-install) :demand t + ;; :custom (evil-replace-with-register-key "gR" "Use the default key.") + :config (evil-replace-with-register-install)) + +(use-package evil-commentary ; e.g. "gcc" / "gcap" to comment out blocks of text + :after (evil) + :commands (evil-commentary-mode) :demand t + :config (evil-commentary-mode +1) + :diminish evil-commentary-mode) + +(use-package evil-expat ; for :reverse, :remove, :rename, :colo, :g*, ... ex commands + :after (evil)) + +(use-package evil-surround + :after (evil) + :commands (global-evil-surround-mode) :demand t + :config (global-evil-surround-mode +1)) + +(use-package smartparens ; required by evil-cleverparens + ;; :custom + ;; (sp-sexp-prefix '() "Set up Guix gexp-related sexp prefixes.") + ) + +(use-package evil-cleverparens + :after (evil smartparens) + :hook ((lisp-mode lisp-data-mode scheme-mode) . evil-cleverparens-mode) + :custom + (evil-cleverparens-use-additional-movement-keys nil "Disable overriding of standard vim bracket navigation keys.")) + +(use-package evil-multiedit + ;; See: https://github.com/hlissner/evil-multiedit#usage + :commands (evil-multiedit-default-keybinds) :demand t + :config (evil-multiedit-default-keybinds)) + +(use-package evil-args + :after (evil) + :config + ;; Bind evil-args text objects only. + ;; See https://github.com/wcsmith/evil-args for more bindings. + (define-key evil-inner-text-objects-map "a" 'evil-inner-arg) + (define-key evil-outer-text-objects-map "a" 'evil-outer-arg)) + +(use-package evil-numbers + :after (evil) + :bind (("<leader>+" . evil-numbers/inc-at-pt) + ("<leader>-" . evil-numbers/dec-at-pt))) + +(use-package evil-goggles ; visual previews for edit operations + :after (evil) + :commands (evil-goggles-mode evil-goggles-use-diff-faces) :demand t + :config + (evil-goggles-mode +1) + (evil-goggles-use-diff-faces) + :diminish evil-goggles-mode) + +(use-package evil-traces ; visual previews for :ex commands + :after (evil) + :commands (evil-traces-mode evil-traces-use-diff-faces) :demand t + :config + (evil-traces-mode +1) + (evil-traces-use-diff-faces) + :diminish evil-traces-mode) + +(use-package evil-markdown + :after (evil markdown-mode) + :hook markdown-mode) + +;; Lots of useful text objects and keybinds: +;; https://github.com/iyefrat/evil-tex#incomplete-showcase +(use-package evil-tex + :after (evil tex-mode) + :hook TeX-mode) + +(use-package evil-text-object-python + :after (evil python) + :hook (python-mode . evil-text-object-python-add-bindings)) + +;; Lisp features +(use-package aggressive-indent + :hook (scheme-mode emacs-lisp-mode lisp-mode sh-mode bash-ts-mode)) + +(defun tw/find-asd-systems (directory) + "Return a list of Common Lisp .asd systems found in DIRECTORY." + (let ((asd-rx (rx ".asd" eos))) + ;; `locate-dominating-file' will call this function once with the original + ;; file name as DIRECTORY, but `directory-files' fails if its argument is + ;; a regular file, so protect against this. + (and (directory-name-p directory) + (mapcar (lambda (file) + (string-trim-right file asd-rx)) + (directory-files directory nil asd-rx))))) + +(defun tw/lisp-project-setup () + "Set up a Lisp REPL for the current project." + (when-let ((fname (buffer-file-name)) + (project-directory + (or (locate-dominating-file fname "guix.scm") + (locate-dominating-file fname #'tw/find-asd-systems) + (project-current nil (file-name-directory fname))))) + (cd project-directory) + (setq-local + inferior-lisp-program + `(;; If a guix.scm file exists, run Lisp in a Guix shell to get dependencies. + ,@(and (file-exists-p (file-name-concat project-directory "guix.scm")) + '("guix" "shell" "-Df" "guix.scm" "--")) + "sbcl" "--noinform" + ;; Load all defined asdf systems. + ,@(mapcan (lambda (system) + (list "--load" (format "%s.asd" system) + "--eval" (format "(require '%s)" system))) + ;; Heuristic: shorter names are earlier in the dependency tree. + ;; For example, X-test.asd depends on X.asd. + (sort (tw/find-asd-systems project-directory) + (lambda (s1 s2) + (< (length s1) (length s2))))) + ;; Assume the project directory name is the name of the main package. + "--eval" ,(format "(in-package #:%s)" + (file-name-base + (directory-file-name project-directory))))))) + +(use-package inf-lisp + :after (lisp-mode) + :hook (lisp-mode . tw/lisp-project-setup) + :custom + (inferior-lisp-program "sbcl")) + +(defun tw/lisp-evil-setup () + "Set up evil in general `lisp-mode' buffers." + ;; https://github.com/wcsmith/evil-args#customization + (setq-local evil-args-delimiters '(" "))) + +;; Sadly, not all Lisp modes derive from `lisp-mode'. +(add-hook 'lisp-mode-hook #'tw/lisp-evil-setup) +(add-hook 'lisp-data-mode-hook #'tw/lisp-evil-setup) ; for elisp +(add-hook 'scheme-mode-hook #'tw/lisp-evil-setup) + +;; buffer-locally set `evil-lookup-func' (used on K keys) for +;; languages where something better than man pages is available +;; (e.g. `describe-symbol' for elisp). +(defun tw/elisp-lookup-func () + "Show help in `emacs-lisp-mode' buffers." + (let ((sym (symbol-at-point))) + (if sym (describe-symbol sym) + (call-interactively #'describe-symbol)))) + +(defun tw/emacs-lisp-evil-setup () + "Set up evil in `emacs-lisp-mode' buffers." + (setq-local evil-lookup-func #'tw/elisp-lookup-func)) + +(add-hook 'emacs-lisp-mode-hook #'tw/emacs-lisp-evil-setup) + +(evil-define-key '(normal visual) emacs-lisp-mode-map + (kbd "<localleader>eb") #'eval-buffer + (kbd "<localleader>ef") #'eval-defun + (kbd "<localleader>er") #'eval-region + (kbd "<localleader>el") #'eval-last-sexp + (kbd "<localleader>ep") #'eval-print-last-sexp) + +;; Guix-related .dir-locals.el entries. These are fine; don't prompt every time. +(add-to-list 'safe-local-variable-values '(geiser-repl-per-project-p . t)) +(add-to-list 'safe-local-variable-values '(geiser-guile-binary . ("guix" "repl"))) +(mapc (apply-partially #'add-to-list 'safe-local-eval-forms) + '((modify-syntax-entry 126 "'") + (modify-syntax-entry 36 "'") + (modify-syntax-entry 43 "'") + (let ((root-dir-unexpanded (locate-dominating-file default-directory ".dir-locals.el"))) + (when root-dir-unexpanded + (let* ((root-dir (file-local-name (expand-file-name root-dir-unexpanded))) + (root-dir* (directory-file-name root-dir))) + (unless (boundp 'geiser-guile-load-path) + (defvar geiser-guile-load-path 'nil)) + (make-local-variable 'geiser-guile-load-path) + (require 'cl-lib) + (cl-pushnew root-dir* geiser-guile-load-path :test #'string-equal)))) + (progn + (require 'lisp-mode) + (defun emacs27-lisp-fill-paragraph (&optional justify) + (interactive "P") + (or (fill-comment-paragraph justify) + (let ((paragraph-start + (concat paragraph-start "\\|\\s-*\\([(;\"]\\|\\s-:\\|`(\\|#'(\\)")) + (paragraph-separate + (concat paragraph-separate "\\|\\s-*\".*[,\\.]$")) + (fill-column + (if (and (integerp emacs-lisp-docstring-fill-column) + (derived-mode-p 'emacs-lisp-mode)) + emacs-lisp-docstring-fill-column + fill-column))) + (fill-paragraph justify)) + t)) + (setq-local fill-paragraph-function #'emacs27-lisp-fill-paragraph)) + + ;; Forms used by Guix upstream. + (add-to-list 'completion-ignored-extensions ".go") + (setq-local guix-directory (locate-dominating-file + default-directory ".dir-locals.el")) + (with-eval-after-load 'yasnippet + (let ((guix-yasnippets (expand-file-name + "etc/snippets/yas" + (locate-dominating-file + default-directory ".dir-locals.el")))) + (unless (member guix-yasnippets yas-snippet-dirs) + (add-to-list 'yas-snippet-dirs guix-yasnippets) + (yas-reload-all)))) + (let ((root-dir-unexpanded (locate-dominating-file + default-directory ".dir-locals.el"))) + (when root-dir-unexpanded + (let* ((root-dir (expand-file-name root-dir-unexpanded)) + (root-dir* (directory-file-name root-dir))) + (unless (boundp 'geiser-guile-load-path) + (defvar geiser-guile-load-path 'nil)) + (make-local-variable 'geiser-guile-load-path) + (require 'cl-lib) + (cl-pushnew root-dir* geiser-guile-load-path + :test #'string-equal)))))) + +;;; init.el ends here diff --git a/tw/services/files/emacs-packages/actionlint.el b/tw/services/files/emacs-packages/actionlint.el new file mode 100644 index 00000000..68a25c57 --- /dev/null +++ b/tw/services/files/emacs-packages/actionlint.el @@ -0,0 +1,147 @@ +;;; actionlint.el --- Flycheck checker for GitHub Actions. -*- lexical-binding: t -*- +;;; Commentary: +;; GitHub Actions are defined using mostly plain YAML files. +;; Actionlint is a linter catching GitHub Action-specific mistakes, and also +;; checks Shell and Python code embedded in Actions (using shellcheck and +;; pyflakes, respectively). +;;; Code: + +(require 'custom) +(require 'flymake) + +(defgroup actionlint nil + "Actionlint-related options." + :group 'languages + :prefix "actionlint-") + +(defcustom actionlint-executable "actionlint" + "The alidistlint executable to use. This will be looked up in $PATH." + :type '(string) + :risky t + :group 'actionlint) + +(defvar actionlint--message-regexp + (rx bol "<stdin>:" ; filename + (group-n 2 (+ digit)) ":" ; line + (group-n 3 (+ digit)) ": " ; column + (? (or (seq "pyflakes reported issue in this script: " + (group-n 4 (+ digit)) ":" ; inner line + (group-n 5 (+ digit)) " ") ; inner column + (seq "shellcheck reported issue in this script: " + (group-n 8 "SC" (+ digit)) ":" ; shellcheck code + (group-n 6 (or "info" "warning" "error")) ":" ; type + (group-n 4 (+ digit)) ":" ; inner line + (group-n 5 (+ digit)) ": "))) ; inner column + (group-n 1 (+? not-newline)) " " ; message + "[" (group-n 7 (+ (not ?\]))) "]" eol) ; backend/error name + "Regular expression matching messages reported by actionlint. + +The following convention for match groups is used: + + 1. free-form message + 2. outer line number + 3. outer column number + 4. (optional) inner line number + 5. (optional) inner column number + 6. (optional) error level/type + 7. backend/error name (e.g. syntax-check or pyflakes) + 8. (optional) backend-specific error code + +The outer line/column numbers are always present and refer to the location of +the key where the error is, normally. If the message was passed through from +another linter (e.g. shellcheck), it may have an inner line/column, which will +be relative to the contents of the key instead.") + +(defun actionlint--next-message (source) + "Return the next message according to REGEXP for buffer SOURCE, if any." + (when-let* ((match (search-forward-regexp actionlint--message-regexp nil t)) + (inner-line (if-let ((match (match-string 4))) + ;; 1-based; don't subtract 1 since we assume + ;; that the script actually starts on the next + ;; line. + (string-to-number match) + 0)) + (inner-column (if-let ((match (match-string 5))) + ;; 1-based; add 1 (assuming 2-space indents) + ;; to pick the right place inside the string. + (1+ (string-to-number match)) + 0)) + (region (flymake-diag-region + source + (+ (string-to-number (match-string 2)) inner-line) + (+ (string-to-number (match-string 3)) inner-column))) + (type (pcase (match-string 6) + ("info" :note) + ("warning" :warning) + ("error" :error) + ('nil :error))) + (message (if-let ((code (match-string 8))) + (concat (match-string 1) " (" (match-string 7) " " code ")") + (concat (match-string 1) " (" (match-string 7) ")")))) + (flymake-make-diagnostic source (car region) (cdr region) type message))) + +(defvar-local actionlint--flymake-proc nil + "The latest invocation of actionlint.") + +;; See info node: (flymake)An annotated example backend. +(defun actionlint-flymake (report-fn &rest _args) + "Run actionlint and report diagnostics from it using REPORT-FN. +Any running invocations are killed before running another one." + (unless (executable-find actionlint-executable) + (funcall report-fn :panic + :explanation "Cannot find `actionlint-executable' program") + (error "Cannot find actionlint executable")) + + ;; Kill previous check, if it's still running. + (when (process-live-p actionlint--flymake-proc) + (kill-process actionlint--flymake-proc)) + + ;; This needs `lexical-binding'. + (let ((source (current-buffer))) + (save-restriction + (widen) + (setq actionlint--flymake-proc + (make-process + :name "actionlint-flymake" :noquery t :connection-type 'pipe + ;; Direct output to a temporary buffer. + :buffer (generate-new-buffer " *actionlint-flymake*") + :command (list actionlint-executable "-oneline" "-no-color" "-") + :sentinel + (lambda (proc _event) + "Parse diagnostic messages once the process PROC has exited." + ;; Check the process has actually exited, not just been suspended. + (when (memq (process-status proc) '(exit signal)) + (unwind-protect + ;; Only proceed if we've got the "latest" process. + (if (with-current-buffer source (eq proc actionlint--flymake-proc)) + (with-current-buffer (process-buffer proc) + (goto-char (point-min)) + (cl-do (diags + (msg (actionlint--next-message source) + (actionlint--next-message source))) + ((null msg) + (funcall report-fn diags)) + (push msg diags))) + (flymake-log :warning "Canceling obsolete check %s" proc)) + ;; Clean up temporary buffer. + (kill-buffer (process-buffer proc))))))) + ;; Send the buffer to actionlint on stdin. + (process-send-region actionlint--flymake-proc (point-min) (point-max)) + (process-send-eof actionlint--flymake-proc)))) + +(defun actionlint-github-workflow-p () + "Does the current buffer contain a GitHub Action?" + (let ((name (buffer-file-name))) + (and name (string-match-p + (rx ".github/workflows/" (+ (not ?\/)) ".yml" eos) name)))) + +(defun actionlint-setup () + "Set up actionlint in this buffer, if it is recognised as a workflow file." + (when (actionlint-github-workflow-p) + (add-hook 'flymake-diagnostic-functions #'actionlint-flymake nil t))) + +(add-hook 'yaml-mode-hook #'actionlint-setup) +(add-hook 'yaml-ts-mode-hook #'actionlint-setup) + +(provide 'actionlint) +;;; actionlint.el ends here diff --git a/tw/services/files/emacs-packages/alidist-mode.el b/tw/services/files/emacs-packages/alidist-mode.el new file mode 100644 index 00000000..fbcef7e5 --- /dev/null +++ b/tw/services/files/emacs-packages/alidist-mode.el @@ -0,0 +1,170 @@ +;;; alidist-mode.el --- Major mode for alidist recipes -*- lexical-binding: t -*- +;;; Commentary: +;;; alidist recipes are shell scripts with a YAML header in front. We +;;; want both these parts highlighted properly, and to lint the whole +;;; thing with a custom script that glues together yamllint and +;;; shellcheck with a few custom checks. +;;; Code: + +(require 'custom) +(require 'flymake) +(require 'mmm-mode) +(require 'mmm-cmds) +(require 'mmm-vars) +(require 'sh-script) +(require 'yaml-mode) + +(defgroup alidist-mode nil + "Alidist-related options." + :group 'languages + :prefix "alidist-mode-") + +(defcustom alidist-mode-alidistlint-executable "alidistlint" + "The alidistlint executable to use. This will be looked up in $PATH." + :type '(string) + :risky t + :group 'alidist-mode) + +(defvar alidist-mode--message-regexp + (rx bol "<stdin>:" ; filename + (group (+ digit)) ":" ; line + (group (+ digit)) ": " ; column + (group (or "note" "warning" "error")) ": " ; type + (group (+ not-newline)) eol) ; message + "Regular expression matching messages from alidistlint. +`alidist-flymake' expects the following capturing groups in this +regexp: (1) line number; (2) column number; (3) error type; (4) +message.") + +(defvar-local alidist-mode--flymake-proc nil + "The latest invocation of alidistlint.") + +;; See info node: (flymake)An annotated example backend. +(defun alidist-flymake (report-fn &rest _args) + "Run alidistlint and report diagnostics from it using REPORT-FN. +Any running invocations are killed before running another one." + (unless (executable-find alidist-mode-alidistlint-executable) + (funcall report-fn :panic + :explanation "Cannot find `alidist-mode-alidistlint-executable' program") + (error "Cannot find alidistlint executable")) + + ;; Kill previous check, if it's still running. + (when (process-live-p alidist-mode--flymake-proc) + (kill-process alidist-mode--flymake-proc)) + + ;; This needs `lexical-binding'. + (let ((source (current-buffer))) + (save-restriction + (widen) + (setq alidist-mode--flymake-proc + (make-process + :name "alidistlint-flymake" :noquery t :connection-type 'pipe + ;; Direct output to a temporary buffer. + :buffer (generate-new-buffer " *alidistlint-flymake*") + :command (list alidist-mode-alidistlint-executable "-f" "gcc" "-") + :sentinel + (lambda (proc _event) + "Parse diagnostic messages once the process PROC has exited." + ;; Check the process has actually exited, not just been suspended. + (when (memq (process-status proc) '(exit signal)) + (unwind-protect + ;; Only proceed if we've got the "latest" process. + (if (with-current-buffer source (eq proc alidist-mode--flymake-proc)) + (with-current-buffer (process-buffer proc) + (goto-char (point-min)) + (cl-loop + while (search-forward-regexp alidist-mode--message-regexp nil t) + for (beg . end) = (flymake-diag-region + source + (string-to-number (match-string 1)) + (string-to-number (match-string 2))) + for type = (pcase (match-string 3) + ("note" :note) + ("warning" :warning) + ("error" :error) + (type (error "Unknown alidistlint error type %s" type))) + collect (flymake-make-diagnostic source beg end type (match-string 4)) + into diags + finally (funcall report-fn diags))) + (flymake-log :warning "Canceling obsolete check %s" proc)) + ;; Clean up temporary buffer. + (kill-buffer (process-buffer proc))))))) + ;; Send the buffer to alidistlint on stdin. + (process-send-region alidist-mode--flymake-proc (point-min) (point-max)) + (process-send-eof alidist-mode--flymake-proc)))) + +(defvar-local alidist-mode--mmm-refresh-timer nil + "An idle timer for the current buffer, to make `mmm-mode' reparse it.") +(put 'alidist-mode--mmm-refresh-timer 'risky-local-variable t) + +(defun alidist-mode--cancel-refresh-timer () + "Cancel and delete the timer that reparses the buffer. +It is stored in `alidist-mode--mmm-refresh-timer'." + (when alidist-mode--mmm-refresh-timer + (cancel-timer alidist-mode--mmm-refresh-timer) + (setq alidist-mode--mmm-refresh-timer nil))) + +(define-derived-mode alidist-mode yaml-mode "alidist" + "An outer mode for alidist recipes, handling the metadata." + (mmm-mode) + ;; `mmm-mode' doesn't refresh its submodes when the buffer changes + ;; (e.g. when a *_recipe key is added to the YAML header), so + ;; refresh manually when idle. + (alidist-mode--cancel-refresh-timer) + (add-hook 'kill-buffer-hook #'alidist-mode--cancel-refresh-timer 0 t) + (setq alidist-mode--mmm-refresh-timer + (run-with-idle-timer + 2 t (lambda (original-buffer) + (when (eq original-buffer (current-buffer)) + ;; Silence `mmm-parse-buffer''s annoying message. + (let ((inhibit-message t)) + (mmm-parse-buffer)))) + ;; Idle timers are global, so make sure we only run the timer + ;; in the right buffer. Save the buffer now to enable this, + ;; and compare every time the timer ticks over. + (current-buffer))) + ;; Set up `flymake-mode'. + (add-hook 'flymake-diagnostic-functions #'alidist-flymake nil t) + (flymake-mode)) + +(define-derived-mode alidist-script-ts-mode bash-ts-mode "Script" + "A mode for scripts in alidist recipes, using tree-sitter.") + +(define-derived-mode alidist-script-mode sh-mode "Script" + "A mode for scripts in alidist recipes with some default settings." + (sh-set-shell "bash")) + +(mmm-add-group + 'alidist-recipe + `((alidist-main-script + :submode alidist-script-mode + :face mmm-default-submode-face + :front ,(rx line-start "---\n") + :back ,(rx buffer-end)) + (alidist-option-script + :submode alidist-script-mode + :face mmm-default-submode-face + ;; Any *_recipe key with a multiline string value is probably a script. + :front ,(rx line-start (* whitespace) + (or "recipe" ; for recipes under prefer_system_replacement_specs + (seq (1+ (any alnum ?\_)) + (or "_recipe" "_check"))) + ": |\n") + ;; End of YAML header, or another YAML key. + :back ,(rx line-start + (or "---\n" + (seq (* whitespace) (+ (any alnum ?\_)) ":" + (or line-end whitespace))))))) + +;; Make `mmm-mode' remember `sh-mode'/`bash-ts-mode' indentation variables. +(cl-dolist (var sh-var-list) + (cl-pushnew `(,var region (sh-mode bash-ts-mode)) + mmm-save-local-variables :test 'equal)) + +(mmm-add-mode-ext-class 'alidist-mode nil 'alidist-recipe) +(add-to-list 'auto-mode-alist + (cons (rx (or bot "/") "alidist/" (1+ (not ?\/)) ".sh" eot) + #'alidist-mode)) + +(provide 'alidist-mode) +;;; alidist-mode.el ends here diff --git a/tw/services/files/emacs-packages/bemscript-mode.el b/tw/services/files/emacs-packages/bemscript-mode.el new file mode 100644 index 00000000..f46c858b --- /dev/null +++ b/tw/services/files/emacs-packages/bemscript-mode.el @@ -0,0 +1,92 @@ +;;; bemscript-mode.el --- Syntax highlighting for MERRILL BEMScript files. +;;; Commentary: +;;; Based on the MERRILL manual. Some commands may have been missed. +;;; Code: + +(defconst bemscript-mode-keywords + '("set" "setsubdomain" "magnetite" "iron" "tm54" "resize" "cubic anisotropy" + "uniaxial anisotropy" "cubicrotation" "easy axis" "external field strength" + "external field direction" "readmesh" "loadmesh" "readmagnetization" + "uniform magnetization" "randomize magnetization" "randomize all moments" + "remesh" "conjugategradient" "steepestdescent" "minimize" "energylog" + "closelogfile" "writeloopdata" "writemagnetization" "writedemag" "writehyst" + "writeboxdata" "appenddemagzone" "magnetizationtopath" "pathtomagnetization" + "renewpath" "refinepathto" "writetecplotpath" "readtecplotpath" + "readtecplotzone" "keypause" "makeinitialpath" "pathminimize" "pathlogfile" + "systemcommand" "pathstructureenergies" "reportenergy" "stop" "end" "loop" + "endloop" "define" "addto" "undefine" "generatecubemesh" "zonename") + "List of keywords for BEMScript mode. Intended for case folding.") + +(defconst bemscript-mode-builtins + '("Aex" "CurvatureWeight" "ExchangeCalculator" "K1" "K2" "Ls" "Ms" "mu" + "MaxEnergyEvaluations" "MaxPathEvaluations" "MaxRestart" "MaxMeshNumber" + "NEBSpring" "PathN" "Zone" "ZoneIncrement") + "List of built-in variable names for BEMScript.") + +(defconst bemscript-mode-special + '("patran" "tecplot" "POINT" "BLOCK" "SD" "muT" "mT" "T" "C") + "Variables with special meanings and units in BEMScript.") + +;; Available font-lock-*-faces: doc type string builtin comment keyword warning +;; constant (reference) preprocessor syntactic-function function-name +;; negation-char variable-name comment-delimiter +(defconst bemscript-mode-font-lock-defaults + `((;; See font-lock-keywords docs. Earlier lines seem to override later ones, + ;; except if both have OVERRIDE? t. + ;; Format: (REGEXP (GROUPNUM FACENAME OVERRIDE? LAXMATCH?)...) + ;; Comments + ("!\\(.*\\)" 1 font-lock-comment-face t t) + ("!" 0 font-lock-comment-delimiter-face t) + ("!!.*$" 0 font-lock-doc-face t) + + ;; Equals signs need spaces around them. + ("\\s-=\\s-" 0 font-lock-type-face t) ; there is no "operator" etc face + ("=" . font-lock-warning-face) + + ;; Numbers and variables + ("\\<[0-9]*\\.?[0-9]+\\(e[-+]?\\)?[0-9]*\\>" . font-lock-constant-face) + ("\\(\\<[#%][A-Z_a-z][0-9A-Z_a-z]*\\>\\|\\$[A-Z_a-z][0-9A-Za-z_]*\\$\\)" + . font-lock-variable-name-face) + + ;; Preprocessor (&-substitution) + (,(concat "\\([^&]\\|^\\)\\(&&\\)*" ; && escapes & + "\\(&\\([_a-zA-Z][_a-zA-Z0-9]*\\|{[_a-zA-Z][_a-zA-Z0-9]*}\\)\\)") + 3 font-lock-preprocessor-face) + (,(concat "\\([^&]\\|^\\)\\(&&\\)*" ; && escapes & + "\\(&\\($" ; bare & + "\\|[^&{_a-zA-Z]\\|{[^_a-zA-Z]" ; invalid char following & or &{ + ; invalid name or unclosed { + "\\|{[_a-zA-Z][_0-9a-zA-Z]*\\([^_0-9a-zA-Z}]\\|$\\)\\)\\)") + 3 font-lock-warning-face t) + + ;; Variable definitions + ("\\<\\(loop\\|define\\)\\s-+\\([_a-zA-Z][_a-zA-Z0-9]*\\)\\>" + 2 font-lock-function-name-face) + ("\\<\\(addto\\|undefine\\)\\s-+\\([_a-zA-Z][_a-zA-Z0-9]*\\)\\>" + 2 font-lock-variable-name-face) + + ;; Keywords + (,(regexp-opt bemscript-mode-special 'words) . font-lock-string-face) + (,(regexp-opt bemscript-mode-keywords 'words) . font-lock-keyword-face) + (,(regexp-opt bemscript-mode-builtins 'words) . font-lock-builtin-face)) + + ;; KEYWORDS-ONLY: if t, no syntactic fontification (strings and comments) + nil + ;; CASE-FOLD: if t, make keywords case-insensitive. + t) + "Font lock settings for BEMScript mode.") + +(define-derived-mode bemscript-mode prog-mode "BEMScript" + "BEMScript-mode is used for editing MERRILL scripts." + (setq comment-start "!" + comment-end "" + tab-width 2 + font-lock-defaults bemscript-mode-font-lock-defaults) + ;; Only word syntax entries are highlighted; add needed chars. + (modify-syntax-entry ?# "w") + ;; Strings in BEMScript are not quoted. + (modify-syntax-entry ?\" "w")) + +(add-to-list 'auto-mode-alist '("\\.bem\\'" . bemscript-mode)) +(provide 'bemscript-mode) +;;; bemscript-mode.el ends here diff --git a/tw/services/files/emacs-packages/environmentd-mode.el b/tw/services/files/emacs-packages/environmentd-mode.el new file mode 100644 index 00000000..4bb8812e --- /dev/null +++ b/tw/services/files/emacs-packages/environmentd-mode.el @@ -0,0 +1,46 @@ +;;; environmentd-mode.el --- Major mode for environment.d(5) files. + +;;; Commentary: + +;; This major mode font-locks files including /etc/environment and +;; ~/.config/environment.d/*.conf. Their format is specified by the +;; environment.d(5) man page. + +;;; Code: + +(defconst environmentd-mode/font-lock-defaults + '((("^[[:blank:]]+[^[:blank:]]+" . font-lock-warning-face) ; stray leading whitespace + ("^#+[[:blank:]]*" . font-lock-comment-delimiter-face) + ("^#+[[:blank:]]*\\(.*\\)$" 1 font-lock-comment-face) + ("\\\\[$\\]" . font-lock-string-face) ; escaped $ \ + ("^\\([A-Za-z_][A-Za-z0-9_]*\\)\\(=\\)" + (1 font-lock-variable-name-face) + (2 font-lock-keyword-face)) + ("\\(\\${\\)\\([A-Za-z_][A-Za-z0-9_]*\\)\\(:[+-]\\)[^}]*\\(}\\)" + (1 font-lock-keyword-face) + (2 font-lock-variable-name-face) + (3 font-lock-keyword-face) + (4 font-lock-keyword-face)) ; ${X:-default}-variable references + ("\\(\\${\\)\\([A-Za-z_][A-Za-z0-9_]*\\)\\(}\\)" + (1 font-lock-keyword-face) + (2 font-lock-variable-name-face) + (3 font-lock-keyword-face)) ; ${X}-variable references + ("\\(\\$\\)\\([A-Za-z_][A-Za-z0-9_]*\\)" + (1 font-lock-keyword-face) + (2 font-lock-variable-name-face))) ; $X-variable references + t nil ((?\' . "w") (?\" . "w"))) + "Font lock settings for Environment.d mode. See `font-lock-defaults' for documentation.") + +(define-derived-mode environmentd-mode prog-mode "Environment.d" + "Environment.d mode is used for environment.d(5) files." + (setq-local comment-start "#" + comment-start-skip "#" + comment-end "" + font-lock-defaults environmentd-mode/font-lock-defaults)) + +(add-to-list 'auto-mode-alist + '("/environment\\.d/[^/]+\\.conf\\'\\|\\`/etc/environment\\'" + . environmentd-mode)) + +(provide 'environmentd-mode) +;;; environmentd-mode.el ends here diff --git a/tw/services/files/emacs-packages/flymake-guile.el b/tw/services/files/emacs-packages/flymake-guile.el new file mode 100644 index 00000000..edfbce82 --- /dev/null +++ b/tw/services/files/emacs-packages/flymake-guile.el @@ -0,0 +1,123 @@ +;;; flymake-guile.el --- Flymake checker using `guild compile' -*- lexical-binding: t -*- +;;; Commentary: +;;; "guild compile" compiles Guile code to bytecode and can output a few basic +;;; warnings. Let's use this as a linter! +;;; Code: + +(require 'custom) +(require 'flymake) +(require 'geiser-impl) ; for `geiser-active-implementations' + +(defcustom flymake-guile-guild-executable "guild" + "The guild executable to use. This will be looked up in $PATH." + :type '(string) + :risky t + :group 'flymake-guile) + +(defvar-local flymake-guile--flymake-proc nil + "The latest invocation of guild compile.") + +(defvar-local flymake-guile--temp-file nil + "The temporary file name to pass to guild.") + +(defun flymake-guile--encode-filename (buffer-name) + "Create a safe temporary file name from BUFFER-NAME." + (concat "/tmp/flymake-guile-" + (string-replace + "/" "!" ; we don't want to create subdirs under /tmp + (or buffer-name + (format "temp-%s.scm" + (random most-positive-fixnum)))))) + +;; See info node: (flymake)An annotated example backend. +(defun flymake-guile (report-fn &rest _args) + "Run guild compile and report diagnostics from it using REPORT-FN. +Any running invocations are killed before running another one." + (unless (executable-find flymake-guile-guild-executable) + (funcall report-fn :panic + :explanation "Cannot find `flymake-guile-guild-executable' program") + (error "Cannot find guild executable")) + + (unless flymake-guile--temp-file + (setq-local flymake-guile--temp-file (flymake-guile--encode-filename (buffer-file-name)))) + + ;; Kill previous check, if it's still running. + (when (process-live-p flymake-guile--flymake-proc) + (kill-process flymake-guile--flymake-proc)) + + ;; This needs `lexical-binding'. + (let ((source (current-buffer)) + ;; Copy `flymake-guile--temp-file' to a local var so that we can refer to it in the `lambda' below. + (temp-file flymake-guile--temp-file)) + (save-restriction + (widen) + ;; Send the buffer to guild on stdin. + (with-temp-file flymake-guile--temp-file + (insert-buffer-substring-no-properties source)) + (setq flymake-guile--flymake-proc + (make-process + :name "flymake-guild" :noquery t :connection-type 'pipe + ;; Direct output to a temporary buffer. + :buffer (generate-new-buffer " *flymake-guile*") + ;; Guild can't read from stdin; it needs a file. + :command (list flymake-guile-guild-executable "compile" + ;; See "guild --warn=help" for details. + ;; "--warn=unsupported-warning" ; ignore unsupported warning types + ;; "--warn=unused-variable" ; too many false positives from macros + "--warn=unused-toplevel" + "--warn=shadowed-toplevel" + "--warn=unbound-variable" + "--warn=macro-use-before-definition" + "--warn=use-before-definition" + "--warn=non-idempotent-definition" + "--warn=arity-mismatch" + "--warn=duplicate-case-datum" + "--warn=bad-case-datum" + "--warn=format" + "-L" (expand-file-name + (project-root (project-current nil (file-name-directory + (buffer-file-name source))))) + flymake-guile--temp-file) + :sentinel + (lambda (proc _event) + "Parse diagnostic messages once the process PROC has exited." + ;; Check the process has actually exited, not just been suspended. + (when (memq (process-status proc) '(exit signal)) + (unwind-protect + ;; Only proceed if we've got the "latest" process. + (if (with-current-buffer source (not (eq proc flymake-guile--flymake-proc))) + (flymake-log :warning "Canceling obsolete check %s" proc) + (with-current-buffer (process-buffer proc) + (goto-char (point-min)) + (cl-loop + with msg-regexp = (rx bol (literal temp-file) ":" ; filename + (group (+ digit)) ":" ; line + (group (+ digit)) ": " ; column + (group (or "warning" "error")) ": " ; type + (group (+ not-newline)) eol) ; message + while (search-forward-regexp msg-regexp nil t) + for (beg . end) = (flymake-diag-region + source ; we filter for messages matching our buffer in the regexp + (string-to-number (match-string 1)) + ;; guild outputs 0-based column numbers + (1+ (string-to-number (match-string 2)))) + for type = (pcase (match-string 3) + ("warning" :warning) + ("error" :error) + (type (error "Unknown guild error type %s" type))) + collect (flymake-make-diagnostic source beg end type (match-string 4)) + into diags + finally (funcall report-fn diags)))) + ;; Clean up temporary buffer. + (kill-buffer (process-buffer proc)) + (delete-file temp-file))))))))) + +(defun flymake-guile-enable () + "Set up the Guile checker for flymake, if in a Guile buffer." + (when (memq 'guile geiser-active-implementations) + (add-hook 'flymake-diagnostic-functions #'flymake-guile nil t))) + +(add-hook 'scheme-mode-hook #'flymake-guile-enable) + +(provide 'flymake-guile) +;;; flymake-guile.el ends here diff --git a/tw/services/files/emacs-packages/ifm-mode.el b/tw/services/files/emacs-packages/ifm-mode.el new file mode 100644 index 00000000..7416588b --- /dev/null +++ b/tw/services/files/emacs-packages/ifm-mode.el @@ -0,0 +1,18 @@ +(define-generic-mode 'ifm-mode + '("#") + '("title" "map" "require" "room" "join" "to" "dir" "exit" "go" "oneway" + "tag" "from" "link" "nolink" "item" "in" "note" "score" "need" "after" + "before" "leave" "all" "except" "cmd" "length" "start" "finish" "nodrop" + "nopath" "style" "hidden" "keep" "with" "until" "ignore" "give" "lost" + "do" "get" "drop" "until" "safe" "ignore" "goto" "endstyle") + '(("\\<\\(\\(north\\|south\\)\\(east\\|west\\)?\\|[ns][ew]?\\|east\\|west\\|[ew]\\)\\>" + . 'font-lock-builtin-face) + ("\\<\\([du]\\|down\\|up\\|in\\|out\\|last\\|it\\|them\\)\\>" + . 'font-lock-builtin-face) + ("\\<[0-9]+" . 'font-lock-constant-face) + ("\\<[_a-zA-Z][_0-9A-Za-z]*\\>" . 'font-lock-variable-name-face)) + '("\\.ifm\\'") + nil + "A mode for interactive fiction manager files") + +(provide 'ifm-mode) diff --git a/tw/services/files/emacs-packages/pam-env-mode.el b/tw/services/files/emacs-packages/pam-env-mode.el new file mode 100644 index 00000000..75b0bf94 --- /dev/null +++ b/tw/services/files/emacs-packages/pam-env-mode.el @@ -0,0 +1,45 @@ +;;; pam-env.el --- Major mode for pam_env.conf(5) files. + +;;; Commentary: + +;; This major mode font-locks files including ~/.pam_environment and +;; /etc/security/pam_env.conf, but notably not /etc/environment. Their format is +;; specified by the pam_env.conf(5) man page. + +;; TODO: Only apply font-lock-variable-name-face to variable declarations if +;; the previous line didn't end with a backslash. The following case didn't +;; work (some declarations that should've been font-locked weren't): +;; '("\\(?:^$\\|[^\\\\]\\)[\r\n]\\([^[:blank:]]+\\)" +;; 1 font-lock-variable-name-face keep) + +;; pam_env does not support escaped double quotes ("). Single-quoted strings are +;; not used as string delimiters. We can only match against word chars in +;; `pam-env-mode/font-lock-defaults', so make double quotes word chars. + +;;; Code: + +(defconst pam-env-mode/font-lock-defaults + '((("^#+" . font-lock-comment-delimiter-face) + ("^#+[[:blank:]]*\\(.*\\)$" 1 font-lock-comment-face) + ("\\\\[@$\\]" . font-lock-string-face) ; escaped $ @ \ + ("@{[^}]+}" . font-lock-builtin-face) ; @{}-variable references + ("\\${[^}]+}" . font-lock-variable-name-face) ; ${}-variable references + ("\"[^\"]*\"" 0 font-lock-string-face keep) ; double-quoted strings; escaped " not supported + ("\\<\\(DEFAULT\\|OVERRIDE\\)=" . font-lock-keyword-face) ; DEFAULT= and OVERRIDE= + ("^[^[:blank:]]+" . font-lock-variable-name-face) ; variable declarations + ("[[:blank:]]+[^[:blank:]]+" . font-lock-warning-face)) ; stray whitespace + t nil ((?\' . "w") (?\" . "w"))) + "Font lock settings for PAM-Environment mode. See `font-lock-defaults' for documentation.") + +(define-derived-mode pam-env-mode prog-mode "PAM-Environment" + "PAM-environment mode is used for pam_env.conf(5) files." + (set (make-local-variable 'comment-start) "#") + (set (make-local-variable 'comment-start-skip) "^#+[[:blank:]]*") + (set (make-local-variable 'comment-end) "") + (set (make-local-variable 'font-lock-defaults) pam-env-mode/font-lock-defaults)) + +(let ((regexp "\\(\\`\\|/\\)\\(pam_env\\.conf\\|\\.pam_environment\\)\\'")) + (add-to-list 'auto-mode-alist `(,regexp . pam-env-mode))) + +(provide 'pam-env-mode) +;;; pam-env.el ends here diff --git a/tw/services/files/emacs-packages/vcard-mode.el b/tw/services/files/emacs-packages/vcard-mode.el new file mode 100644 index 00000000..a932477a --- /dev/null +++ b/tw/services/files/emacs-packages/vcard-mode.el @@ -0,0 +1,56 @@ +;;; vcard-mode.el --- Major mode for vCard files. + +;; Copyright (C) 2012 Desmond O. Chang + +;; Author: Desmond O. Chang <dochang@gmail.com> +;; Version: 0.1.0 +;; Keywords: files + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This package provides a major mode to edit vCard files. + +;; To install it, put this file under your load path. Then add the +;; following to your .emacs file: + +;; (require 'vcard-mode) + +;; Or if you don't want to load it until editing a vCard file: + +;; (autoload 'vcard-mode "vcard-mode" "Major mode for vCard files" t) +;; (add-to-list 'auto-mode-alist '("\\.vc\\(f\\|ard\\)\\'" . vcard-mode)) + +;;; Code: + +(require 'generic) + +(defun vcard-mode-init () + (set (make-local-variable 'paragraph-start) "BEGIN:VCARD")) + +;;;###autoload +(define-generic-mode vcard-mode + '() + nil + '(("^BEGIN:VCARD" . font-lock-function-name-face) + (";[^:\n]+:" . font-lock-type-face) + ("^\\([^;:\n]+\\):?" . font-lock-keyword-face)) + '("\\.\\(vcf\\|vcard\\)\\'") + '(vcard-mode-init) + "Generic mode for vCard files.") + +(provide 'vcard-mode) + +;;; vcard-mode.el ends here diff --git a/tw/services/files/emacsclient.desktop b/tw/services/files/emacsclient.desktop new file mode 100644 index 00000000..5e68ffef --- /dev/null +++ b/tw/services/files/emacsclient.desktop @@ -0,0 +1,22 @@ +[Desktop Entry] +Name=Emacs (Client) +GenericName=Text Editor +Comment=Edit text +MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; +Exec=emacsclient --alternate-editor= --create-frame %F +Icon=emacs +Type=Application +Terminal=false +Categories=Development;TextEditor; +StartupNotify=true +StartupWMClass=Emacs +Keywords=emacsclient; +Actions=new-window;new-instance; + +[Desktop Action new-window] +Name=New Window +Exec=emacsclient --alternate-editor= --create-frame %F + +[Desktop Action new-instance] +Name=New Instance +Exec=emacs %F diff --git a/tw/services/files/gtk2.ini b/tw/services/files/gtk2.ini new file mode 100644 index 00000000..6af8200a --- /dev/null +++ b/tw/services/files/gtk2.ini @@ -0,0 +1,20 @@ +gtk-theme-name="Catppuccin-Dark" +gtk-icon-theme-name="Papirus-Dark" +gtk-font-name="Fira Sans, 10" +gtk-cursor-theme-name="Catppuccin-Mocha-Dark-Cursors" +gtk-cursor-theme-size=0 +gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ +gtk-toolbar-icon-size=GTK_ICON_SIZE_MENU +gtk-button-images=1 +gtk-menu-images=1 +gtk-enable-event-sounds=1 +gtk-enable-input-feedback-sounds=1 +gtk-xft-antialias=1 +gtk-xft-hinting=1 +gtk-xft-hintstyle="hintslight" +gtk-xft-rgba="rgb" +#gtk-modules="appmenu-gtk-module" +gtk-enable-animations=1 +gtk-primary-button-warps-slider=0 +# Use Qt UI conventions, I think (at least this setting is from KDE). +gtk-alternative-button-order = 1 diff --git a/tw/services/files/gtk3.ini b/tw/services/files/gtk3.ini new file mode 100644 index 00000000..fff5946b --- /dev/null +++ b/tw/services/files/gtk3.ini @@ -0,0 +1,16 @@ +[Settings] +gtk-theme-name=Catppuccin-Dark +gtk-icon-theme-name=Papirus-Dark +gtk-font-name=Fira Sans 10 +gtk-cursor-theme-name=Catppuccin-Mocha-Dark-Cursors +gtk-cursor-theme-size=0 +gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ +gtk-toolbar-icon-size=GTK_ICON_SIZE_MENU +gtk-button-images=1 +gtk-menu-images=1 +gtk-enable-event-sounds=1 +gtk-enable-input-feedback-sounds=1 +gtk-xft-antialias=1 +gtk-xft-hinting=1 +gtk-xft-hintstyle=hintslight +gtk-xft-rgba=rgb diff --git a/tw/services/files/i3.conf b/tw/services/files/i3.conf new file mode 100644 index 00000000..10ae1133 --- /dev/null +++ b/tw/services/files/i3.conf @@ -0,0 +1,273 @@ +# +# i3 config file (v4) +# +# Please see http://i3wm.org/docs/userguide.html for a complete reference! +# Use xev to see keycodes for special keys. + +# Appearance and Styling {{{ +# Font for window titles. Will also be used by the bar unless a different font +# is used in the bar {} block below. +font pango:Fira Sans 10 + +title_align center +default_border pixel 3 +default_floating_border pixel 3 +hide_edge_borders smart +gaps inner 15 +gaps outer 0 +smart_gaps on + +# Catppuccin colours +# Foregrounds +set $c_fg #cdd6f4 +set $c_inactive #7f849c +# Backgrounds +set $c_bg #11111b +set $c_active #585b70 +set $c_urgent #f9e2af + +# class border background text indicator child_border +client.focused $c_active $c_active $c_fg $c_active $c_active +client.focused_inactive $c_bg $c_bg $c_fg $c_bg $c_bg +client.unfocused $c_bg $c_bg $c_inactive $c_bg $c_bg +client.urgent $c_urgent $c_urgent $c_fg $c_urgent $c_urgent +client.placeholder $c_bg $c_bg $c_inactive $c_bg $c_bg +client.background $c_bg +# }}} + +# Basic Configuration {{{ +# use the Super key as $mod +set $mod Mod4 + +# Use Mouse+$mod to drag floating windows to their wanted position +floating_modifier $mod + +# essential applications +bindsym $mod+Return exec kitty "--directory=$(xcwd)" +bindsym $mod+i exec icecat --new-window +bindsym $mod+shift+i exec icecat --new-tab "$(xclip -out)" +bindsym $mod+e exec $ASYNC_EDITOR +# Use ASYNC_EDITOR so I can continue using ranger while the editor +# remains open in a separate window. +bindsym $mod+slash exec EDITOR=$ASYNC_EDITOR kitty ranger "$(xcwd)" +bindsym $mod+semicolon exec --no-startup-id nheko +bindsym $mod+shift+colon exec --no-startup-id kitty aerc +bindsym $mod+y exec kitty pulsemixer + +# volume +bindsym XF86AudioRaiseVolume exec --no-startup-id volume +5 +bindsym XF86AudioLowerVolume exec --no-startup-id volume -5 +bindsym XF86AudioMute exec --no-startup-id volume toggle-mute + +# notifications +bindsym $mod+n exec dunstctl close +bindsym $mod+shift+n exec dunstctl history-pop +bindsym $mod+period exec dunstctl context + +# screen locking +bindsym $mod+shift+slash exec screenlock + +# kill focused window +bindsym $mod+shift+q kill + +# rofi menus +bindsym $mod+d exec rofi -show combi +bindsym $mod+shift+e exec rofi -show session:sessionmenu +# When selecting a history line in rofi-calc, it is printed; copy it so we can use it elsewhere. +bindsym $mod+q exec rofi -show calc | xclip -quiet -i -rmlastnl -selection clipboard +bindsym $mod+p exec passmenu --type-all +bindsym $mod+shift+p exec passmenu --type-pass +bindsym $mod+o exec passmenu --type-otp +bindsym $mod+comma exec rofi-colors.sh +bindsym $mod+shift+Return exec rofi -show ssh +# }}} + +# Basic Movement {{{ +# change focus +bindsym $mod+h focus left +bindsym $mod+j focus down +bindsym $mod+k focus up +bindsym $mod+l focus right +bindsym $mod+Left focus left +bindsym $mod+Down focus down +bindsym $mod+Up focus up +bindsym $mod+Right focus right + +# move focused window +bindsym $mod+shift+h move left +bindsym $mod+shift+j move down +bindsym $mod+shift+k move up +bindsym $mod+shift+l move right +bindsym $mod+shift+Left move left +bindsym $mod+shift+Down move down +bindsym $mod+shift+Up move up +bindsym $mod+shift+Right move right + +bindsym $mod+a focus parent +bindsym $mod+shift+a focus child +# }}} + +# Layout {{{ +bindsym $mod+b split h +bindsym $mod+v split v + +# enter fullscreen mode for the focused container +bindsym $mod+f fullscreen toggle +bindsym $mod+shift+f floating enable, resize set 1920 1080, move position 0 0 + +# change container layout (stacked, tabbed, toggle split) +bindsym $mod+s layout stacking +bindsym $mod+w layout tabbed +bindsym $mod+x layout toggle split + +bindsym $mod+shift+space floating toggle +# change focus between tiling / floating windows +bindsym $mod+space focus mode_toggle + +# scratchpad +bindsym $mod+numbersign scratchpad show +bindsym $mod+shift+numbersign move to scratchpad +bindsym $mod+apostrophe sticky disable, floating disable +bindsym $mod+shift+apostrophe sticky enable, floating enable + +# move workspaces +bindsym $mod+shift+comma move workspace to output left +bindsym $mod+shift+period move workspace to output right +# }}} + +# Default Workspaces {{{ +# switch to workspace +bindsym $mod+Escape workspace back_and_forth +bindsym $mod+1 workspace 1 +bindsym $mod+2 workspace 2 +bindsym $mod+3 workspace 3 +bindsym $mod+4 workspace 4 +bindsym $mod+5 workspace 5 +bindsym $mod+6 workspace 6 +bindsym $mod+7 workspace 7 +bindsym $mod+8 workspace 8 +bindsym $mod+9 workspace 9 +bindsym $mod+0 workspace 10 +bindsym $mod+parenleft workspace prev +bindsym $mod+parenright workspace next + +# move focused container to workspace +bindsym $mod+shift+Escape move container to workspace back_and_forth +bindsym $mod+shift+1 move container to workspace 1 +bindsym $mod+shift+2 move container to workspace 2 +bindsym $mod+shift+3 move container to workspace 3 +bindsym $mod+shift+4 move container to workspace 4 +bindsym $mod+shift+5 move container to workspace 5 +bindsym $mod+shift+6 move container to workspace 6 +bindsym $mod+shift+7 move container to workspace 7 +bindsym $mod+shift+8 move container to workspace 8 +bindsym $mod+shift+9 move container to workspace 9 +bindsym $mod+shift+0 move container to workspace 10 +bindsym $mod+shift+parenleft move container to workspace prev +bindsym $mod+shift+parenright move container to workspace next +# }}} + +# Custom Workspaces {{{ +set $ws_terminal 0:>_ +bindsym $mod+grave workspace "$ws_terminal" +bindsym $mod+shift+grave move container to workspace "$ws_terminal" + +set $ws_coding 50:🖊️ +bindsym $mod+c workspace "$ws_coding" +bindsym $mod+shift+c move container to workspace "$ws_coding" + +set $ws_games 60:🎮 +bindsym $mod+g workspace "$ws_games" +bindsym $mod+shift+g move container to workspace "$ws_games" + +set $ws_music 80:🎵 +bindsym $mod+u workspace "$ws_music" +bindsym $mod+shift+u move container to workspace "$ws_music" + +set $ws_messaging 90:💬 +bindsym $mod+m workspace "$ws_messaging" +bindsym $mod+shift+m move container to workspace "$ws_messaging" + +# set default screens for workspaces +# laptop: eDP-1-1 is the laptop screen, HDMI-0 is the external screen. +# work desktop: DP-1-8 is on the left, DP-2 is the wide screen on the right. +# The first workspaces listed for each output will be active at startup. +workspace 1 output HDMI-0 DP-1-8 +workspace "$ws_messaging" output eDP-1-1 DP-2 +workspace 2 output HDMI-0 DP-1-8 +workspace 3 output HDMI-0 DP-1-8 +workspace 4 output HDMI-0 DP-1-8 +workspace 5 output HDMI-0 DP-1-8 +workspace 6 output eDP-1-1 DP-2 +workspace 7 output eDP-1-1 DP-2 +workspace 8 output eDP-1-1 DP-2 +workspace 9 output eDP-1-1 DP-2 +workspace 10 output eDP-1-1 DP-2 +workspace "$ws_terminal" output eDP-1-1 DP-1-8 +workspace "$ws_coding" output HDMI-0 DP-2 +workspace "$ws_games" output HDMI-0 DP-1-8 +workspace "$ws_music" output eDP-1-1 DP-1-8 + +assign [class="^Franz$"] "$ws_messaging" +assign [window_role="^weechat$"] "$ws_messaging" +assign [window_role="^mutt$"] "$ws_messaging" +assign [class="^evolution-initial$"] "$ws_messaging" +assign [class="^kontact$"] "$ws_messaging" + +# NOTE: no_focus will also be ignored for the first window on a workspace as +# there shouldn’t be a reason to not focus the window in this case. This allows +# for better usability in combination with workspace_layout. (From i3 docs) +#no_focus [class="^Franz$"] +#no_focus [window_role="^weechat$"] +#no_focus [window_role="^mutt$"] +#no_focus [class="^evolution-initial$"] + +## PlayOnLinux +for_window [title="PlayOnLinux"] floating enable + +## Plasma/KDE: https://ryanlue.com/posts/2019-06-13-kde-i3 +# Don’t treat Plasma pop-ups as full-sized windows +for_window [class="plasmashell"] floating enable +# Don’t spawn an empty window for the Plasma Desktop +for_window [title="Desktop — Plasma"] move scratchpad +# Don’t let notifications and non-interactive pop-up windows steal focus +#no_focus [class="plasmashell" window_type="on_screen_display"] +# https://github.com/heckelson/i3-and-kde-plasma +# Move notifications to top-right corner. +#for_window [class="plasmashell" window_type="notification"] move up 400, move right 750, no_focus +# Notifications appear in the centre of the screen. According to +# https://old.reddit.com/r/i3wm/comments/bw1yfs/kde_notifications_appearing_in_the_centre_of/, +# setting notifications to appear in the top-left corner gets placement right. +no_focus [class="plasmashell" window_type="notification"] + +for_window [class="^Pyneedle$"] floating enable +for_window [instance="^emacs-initial$"] floating enable +for_window [class="^Spotify$"] move container to workspace "$ws_music" +for_window [class="^Pidgin$"] move container to workspace "$ws_messaging" +for_window [class="^kitty$" title="^aerc$"] move container to workspace "$ws_messaging" +# annoying pop-up from Bluetooth network manager +for_window [class="^.blueman-applet-real$"] kill +# }}} + +# Modes {{{ +mode "resize" { + bindsym h resize shrink width 10 px or 10 ppt + bindsym j resize grow height 10 px or 10 ppt + bindsym k resize shrink height 10 px or 10 ppt + bindsym l resize grow width 10 px or 10 ppt + + bindsym shift+h resize shrink width 5 px or 5 ppt + bindsym shift+j resize grow height 5 px or 5 ppt + bindsym shift+k resize shrink height 5 px or 5 ppt + bindsym shift+l resize grow width 5 px or 5 ppt + + bindsym left resize shrink width 10 px or 10 ppt + bindsym down resize grow height 10 px or 10 ppt + bindsym up resize shrink height 10 px or 10 ppt + bindsym right resize grow width 10 px or 10 ppt + + bindsym Return mode "default" + bindsym Escape mode "default" +} +bindsym $mod+r mode "resize" +# }}} diff --git a/tw/services/files/khal.conf b/tw/services/files/khal.conf new file mode 100644 index 00000000..3240609a --- /dev/null +++ b/tw/services/files/khal.conf @@ -0,0 +1,44 @@ +# https://lostpackets.de/khal/configure.html + +[default] +default_calendar = Personal +highlight_event_days = True +show_all_days = True +timedelta = 7d + +[highlight_days] +default_color = dark gray +method = foreground + +[locale] +timeformat = %H:%M +dateformat = %d/%m +longdateformat = %d/%m/%Y +datetimeformat = %d/%m %H:%M +longdatetimeformat = %d/%m/%Y %H:%M +weeknumbers = off + +[view] +monthdisplay = firstfullweek + +[calendars] +[[birthdays]] +type = birthdays +path = ~/.local/share/vdirsyncer/main-contacts/contacts +color = dark red +# Prefer other events' colours when colouring days. +priority = -1 + +[[indico]] +path = ~/.local/share/vdirsyncer/indico +color = yellow +readonly = True + +[[cern]] +path = ~/.local/share/vdirsyncer/cern +color = yellow +readonly = True + +[[calendars]] +type = discover +path = ~/.local/share/vdirsyncer/calendars/imported-*ics diff --git a/tw/services/files/khard.conf b/tw/services/files/khard.conf new file mode 100644 index 00000000..a3cfe41a --- /dev/null +++ b/tw/services/files/khard.conf @@ -0,0 +1,22 @@ +# https://khard.readthedocs.io/en/latest/man/khard.conf.html + +[addressbooks] +[[main]] +path = ~/.local/share/vdirsyncer/main-contacts/contacts +[[sandbox]] +path = ~/.local/share/vdirsyncer/sandbox-contacts/sandbox-contacts + +[general] +default_action = list +merge_editor = vimdiff + +[contact table] +display = formatted_name +sort = last_name +group_by_addressbook = yes +localize_dates = yes +show_nicknames = yes +show_kinds = yes +show_uids = no +preferred_phone_number_type = pref, cell, home +preferred_email_address_type = pref, home, work diff --git a/tw/services/files/kitty.conf b/tw/services/files/kitty.conf new file mode 100644 index 00000000..014e70f6 --- /dev/null +++ b/tw/services/files/kitty.conf @@ -0,0 +1,1337 @@ +# vim:fileencoding=utf-8:ft=conf:foldmethod=marker + +#: Fonts {{{ + +#: kitty has very powerful font management. You can configure +#: individual font faces and even specify special fonts for particular +#: characters. + +font_family Hermit +# bold_font auto +# italic_font auto +# bold_italic_font auto + +#: You can specify different fonts for the bold/italic/bold-italic +#: variants. To get a full list of supported fonts use the `kitty +#: list-fonts` command. By default they are derived automatically, by +#: the OSes font system. Setting them manually is useful for font +#: families that have many weight variants like Book, Medium, Thick, +#: etc. For example:: + +#: font_family Operator Mono Book +#: bold_font Operator Mono Medium +#: italic_font Operator Mono Book Italic +#: bold_italic_font Operator Mono Medium Italic + +font_size 10.0 + +#: Font size (in pts) + +# force_ltr no + +#: kitty does not support BIDI (bidirectional text), however, for RTL +#: scripts, words are automatically displayed in RTL. That is to say, +#: in an RTL script, the words "HELLO WORLD" display in kitty as +#: "WORLD HELLO", and if you try to select a substring of an RTL- +#: shaped string, you will get the character that would be there had +#: the the string been LTR. For example, assuming the Hebrew word +#: ירושלים, selecting the character that on the screen appears to be ם +#: actually writes into the selection buffer the character י. + +#: kitty's default behavior is useful in conjunction with a filter to +#: reverse the word order, however, if you wish to manipulate RTL +#: glyphs, it can be very challenging to work with, so this option is +#: provided to turn it off. Furthermore, this option can be used with +#: the command line program GNU FriBidi +#: <https://github.com/fribidi/fribidi#executable> to get BIDI +#: support, because it will force kitty to always treat the text as +#: LTR, which FriBidi expects for terminals. + +# adjust_line_height 0 +# adjust_column_width 0 + +#: Change the size of each character cell kitty renders. You can use +#: either numbers, which are interpreted as pixels or percentages +#: (number followed by %), which are interpreted as percentages of the +#: unmodified values. You can use negative pixels or percentages less +#: than 100% to reduce sizes (but this might cause rendering +#: artifacts). + +# symbol_map U+E0A0-U+E0A3,U+E0C0-U+E0C7 PowerlineSymbols + +#: Map the specified unicode codepoints to a particular font. Useful +#: if you need special rendering for some symbols, such as for +#: Powerline. Avoids the need for patched fonts. Each unicode code +#: point is specified in the form U+<code point in hexadecimal>. You +#: can specify multiple code points, separated by commas and ranges +#: separated by hyphens. symbol_map itself can be specified multiple +#: times. Syntax is:: + +#: symbol_map codepoints Font Family Name + +# disable_ligatures never + +#: Choose how you want to handle multi-character ligatures. The +#: default is to always render them. You can tell kitty to not render +#: them when the cursor is over them by using cursor to make editing +#: easier, or have kitty never render them at all by using always, if +#: you don't like them. The ligature strategy can be set per-window +#: either using the kitty remote control facility or by defining +#: shortcuts for it in kitty.conf, for example:: + +#: map alt+1 disable_ligatures_in active always +#: map alt+2 disable_ligatures_in all never +#: map alt+3 disable_ligatures_in tab cursor + +#: Note that this refers to programming ligatures, typically +#: implemented using the calt OpenType feature. For disabling general +#: ligatures, use the font_features setting. + +# font_features none + +#: Choose exactly which OpenType features to enable or disable. This +#: is useful as some fonts might have features worthwhile in a +#: terminal. For example, Fira Code Retina includes a discretionary +#: feature, zero, which in that font changes the appearance of the +#: zero (0), to make it more easily distinguishable from Ø. Fira Code +#: Retina also includes other discretionary features known as +#: Stylistic Sets which have the tags ss01 through ss20. + +#: Note that this code is indexed by PostScript name, and not the font +#: family. This allows you to define very precise feature settings; +#: e.g. you can disable a feature in the italic font but not in the +#: regular font. + +#: On Linux, these are read from the FontConfig database first and +#: then this, setting is applied, so they can be configured in a +#: single, central place. + +#: To get the PostScript name for a font, use kitty + list-fonts +#: --psnames: + +#: .. code-block:: sh + +#: $ kitty + list-fonts --psnames | grep Fira +#: Fira Code +#: Fira Code Bold (FiraCode-Bold) +#: Fira Code Light (FiraCode-Light) +#: Fira Code Medium (FiraCode-Medium) +#: Fira Code Regular (FiraCode-Regular) +#: Fira Code Retina (FiraCode-Retina) + +#: The part in brackets is the PostScript name. + +#: Enable alternate zero and oldstyle numerals:: + +#: font_features FiraCode-Retina +zero +onum + +#: Enable only alternate zero:: + +#: font_features FiraCode-Retina +zero + +#: Disable the normal ligatures, but keep the calt feature which (in +#: this font) breaks up monotony:: + +#: font_features TT2020StyleB-Regular -liga +calt + +#: In conjunction with force_ltr, you may want to disable Arabic +#: shaping entirely, and only look at their isolated forms if they +#: show up in a document. You can do this with e.g.:: + +#: font_features UnifontMedium +isol -medi -fina -init + +# box_drawing_scale 0.001, 1, 1.5, 2 + +#: Change the sizes of the lines used for the box drawing unicode +#: characters These values are in pts. They will be scaled by the +#: monitor DPI to arrive at a pixel value. There must be four values +#: corresponding to thin, normal, thick, and very thick lines. + +#: }}} + +#: Cursor customization {{{ + +# cursor #cccccc + +#: Default cursor color + +# cursor_text_color #111111 + +#: Choose the color of text under the cursor. If you want it rendered +#: with the background color of the cell underneath instead, use the +#: special keyword: background + +# cursor_shape block + +#: The cursor shape can be one of (block, beam, underline) + +# cursor_beam_thickness 1.5 + +#: Defines the thickness of the beam cursor (in pts) + +# cursor_underline_thickness 2.0 + +#: Defines the thickness of the underline cursor (in pts) + +# cursor_blink_interval -1 + +#: The interval (in seconds) at which to blink the cursor. Set to zero +#: to disable blinking. Negative values mean use system default. Note +#: that numbers smaller than repaint_delay will be limited to +#: repaint_delay. + +# cursor_stop_blinking_after 15.0 + +#: Stop blinking cursor after the specified number of seconds of +#: keyboard inactivity. Set to zero to never stop blinking. + +#: }}} + +#: Scrollback {{{ + +scrollback_lines 100000 + +#: Number of lines of history to keep in memory for scrolling back. +#: Memory is allocated on demand. Negative numbers are (effectively) +#: infinite scrollback. Note that using very large scrollback is not +#: recommended as it can slow down performance of the terminal and +#: also use large amounts of RAM. Instead, consider using +#: scrollback_pager_history_size. + +# scrollback_pager less --chop-long-lines --RAW-CONTROL-CHARS +INPUT_LINE_NUMBER + +#: Program with which to view scrollback in a new window. The +#: scrollback buffer is passed as STDIN to this program. If you change +#: it, make sure the program you use can handle ANSI escape sequences +#: for colors and text formatting. INPUT_LINE_NUMBER in the command +#: line above will be replaced by an integer representing which line +#: should be at the top of the screen. Similarly CURSOR_LINE and +#: CURSOR_COLUMN will be replaced by the current cursor position. + +scrollback_pager_history_size 1024 + +#: Separate scrollback history size, used only for browsing the +#: scrollback buffer (in MB). This separate buffer is not available +#: for interactive scrolling but will be piped to the pager program +#: when viewing scrollback buffer in a separate window. The current +#: implementation stores the data in UTF-8, so approximatively 10000 +#: lines per megabyte at 100 chars per line, for pure ASCII text, +#: unformatted text. A value of zero or less disables this feature. +#: The maximum allowed size is 4GB. + +scrollback_fill_enlarged_window yes + +#: Fill new space with lines from the scrollback buffer after +#: enlarging a window. + +# wheel_scroll_multiplier 5.0 + +#: Modify the amount scrolled by the mouse wheel. Note this is only +#: used for low precision scrolling devices, not for high precision +#: scrolling on platforms such as macOS and Wayland. Use negative +#: numbers to change scroll direction. + +# touch_scroll_multiplier 1.0 + +#: Modify the amount scrolled by a touchpad. Note this is only used +#: for high precision scrolling devices on platforms such as macOS and +#: Wayland. Use negative numbers to change scroll direction. + +#: }}} + +#: Mouse {{{ + +# mouse_hide_wait 3.0 + +#: Hide mouse cursor after the specified number of seconds of the +#: mouse not being used. Set to zero to disable mouse cursor hiding. +#: Set to a negative value to hide the mouse cursor immediately when +#: typing text. Disabled by default on macOS as getting it to work +#: robustly with the ever-changing sea of bugs that is Cocoa is too +#: much effort. + +# url_color #0087bd +# url_style curly + +#: The color and style for highlighting URLs on mouse-over. url_style +#: can be one of: none, single, double, curly + +open_url_modifiers shift +# open_url_modifiers kitty_mod + +#: The modifier keys to press when clicking with the mouse on URLs to +#: open the URL + +# open_url_with default + +#: The program with which to open URLs that are clicked on. The +#: special value default means to use the operating system's default +#: URL handler. + +# url_prefixes http https file ftp gemini irc gopher mailto news git + +#: The set of URL prefixes to look for when detecting a URL under the +#: mouse cursor. + +# detect_urls yes + +#: Detect URLs under the mouse. Detected URLs are highlighted with an +#: underline and the mouse cursor becomes a hand over them. Even if +#: this option is disabled, URLs are still clickable. + +# copy_on_select no + +#: Copy to clipboard or a private buffer on select. With this set to +#: clipboard, simply selecting text with the mouse will cause the text +#: to be copied to clipboard. Useful on platforms such as macOS that +#: do not have the concept of primary selections. You can instead +#: specify a name such as a1 to copy to a private kitty buffer +#: instead. Map a shortcut with the paste_from_buffer action to paste +#: from this private buffer. For example:: + +#: map cmd+shift+v paste_from_buffer a1 + +#: Note that copying to the clipboard is a security risk, as all +#: programs, including websites open in your browser can read the +#: contents of the system clipboard. + +# strip_trailing_spaces never + +#: Remove spaces at the end of lines when copying to clipboard. A +#: value of smart will do it when using normal selections, but not +#: rectangle selections. always will always do it. + +# rectangle_select_modifiers ctrl+alt + +#: The modifiers to use rectangular selection (i.e. to select text in +#: a rectangular block with the mouse) + +# terminal_select_modifiers shift + +#: The modifiers to override mouse selection even when a terminal +#: application has grabbed the mouse + +# select_by_word_characters @-./_~?&=%+# + +#: Characters considered part of a word when double clicking. In +#: addition to these characters any character that is marked as an +#: alphanumeric character in the unicode database will be matched. + +# click_interval -1.0 + +#: The interval between successive clicks to detect double/triple +#: clicks (in seconds). Negative numbers will use the system default +#: instead, if available, or fallback to 0.5. + +focus_follows_mouse yes + +#: Set the active window to the window under the mouse when moving the +#: mouse around + +# pointer_shape_when_grabbed arrow + +#: The shape of the mouse pointer when the program running in the +#: terminal grabs the mouse. Valid values are: arrow, beam and hand + +# default_pointer_shape beam + +#: The default shape of the mouse pointer. Valid values are: arrow, +#: beam and hand + +# pointer_shape_when_dragging beam + +#: The default shape of the mouse pointer when dragging across text. +#: Valid values are: arrow, beam and hand + +#: }}} + +#: Performance tuning {{{ + +# repaint_delay 10 + +#: Delay (in milliseconds) between screen updates. Decreasing it, +#: increases frames-per-second (FPS) at the cost of more CPU usage. +#: The default value yields ~100 FPS which is more than sufficient for +#: most uses. Note that to actually achieve 100 FPS you have to either +#: set sync_to_monitor to no or use a monitor with a high refresh +#: rate. Also, to minimize latency when there is pending input to be +#: processed, repaint_delay is ignored. + +# input_delay 3 + +#: Delay (in milliseconds) before input from the program running in +#: the terminal is processed. Note that decreasing it will increase +#: responsiveness, but also increase CPU usage and might cause flicker +#: in full screen programs that redraw the entire screen on each loop, +#: because kitty is so fast that partial screen updates will be drawn. + +# sync_to_monitor yes + +#: Sync screen updates to the refresh rate of the monitor. This +#: prevents tearing (https://en.wikipedia.org/wiki/Screen_tearing) +#: when scrolling. However, it limits the rendering speed to the +#: refresh rate of your monitor. With a very high speed mouse/high +#: keyboard repeat rate, you may notice some slight input latency. If +#: so, set this to no. + +#: }}} + +#: Terminal bell {{{ + +# enable_audio_bell yes + +#: Enable/disable the audio bell. Useful in environments that require +#: silence. + +# visual_bell_duration 0.0 + +#: Visual bell duration. Flash the screen when a bell occurs for the +#: specified number of seconds. Set to zero to disable. + +# window_alert_on_bell yes + +#: Request window attention on bell. Makes the dock icon bounce on +#: macOS or the taskbar flash on linux. + +# bell_on_tab yes + +#: Show a bell symbol on the tab if a bell occurs in one of the +#: windows in the tab and the window is not the currently focused +#: window + +# command_on_bell none + +#: Program to run when a bell occurs. + +#: }}} + +#: Window layout {{{ + +# remember_window_size yes +# initial_window_width 640 +# initial_window_height 400 + +#: If enabled, the window size will be remembered so that new +#: instances of kitty will have the same size as the previous +#: instance. If disabled, the window will initially have size +#: configured by initial_window_width/height, in pixels. You can use a +#: suffix of "c" on the width/height values to have them interpreted +#: as number of cells instead of pixels. + +# enabled_layouts * + +#: The enabled window layouts. A comma separated list of layout names. +#: The special value all means all layouts. The first listed layout +#: will be used as the startup layout. Default configuration is all +#: layouts in alphabetical order. For a list of available layouts, see +#: the https://sw.kovidgoyal.net/kitty/index.html#layouts. + +# window_resize_step_cells 2 +# window_resize_step_lines 2 + +#: The step size (in units of cell width/cell height) to use when +#: resizing windows. The cells value is used for horizontal resizing +#: and the lines value for vertical resizing. + +# window_border_width 0.5pt + +#: The width of window borders. Can be either in pixels (px) or pts +#: (pt). Values in pts will be rounded to the nearest number of pixels +#: based on screen resolution. If not specified the unit is assumed to +#: be pts. Note that borders are displayed only when more than one +#: window is visible. They are meant to separate multiple windows. + +# draw_minimal_borders yes + +#: Draw only the minimum borders needed. This means that only the +#: minimum needed borders for inactive windows are drawn. That is only +#: the borders that separate the inactive window from a neighbor. Note +#: that setting a non-zero window margin overrides this and causes all +#: borders to be drawn. + +# window_margin_width 0 + +#: The window margin (in pts) (blank area outside the border). A +#: single value sets all four sides. Two values set the vertical and +#: horizontal sides. Three values set top, horizontal and bottom. Four +#: values set top, right, bottom and left. + +# single_window_margin_width -1 + +#: The window margin (in pts) to use when only a single window is +#: visible. Negative values will cause the value of +#: window_margin_width to be used instead. A single value sets all +#: four sides. Two values set the vertical and horizontal sides. Three +#: values set top, horizontal and bottom. Four values set top, right, +#: bottom and left. + +# window_padding_width 0 + +#: The window padding (in pts) (blank area between the text and the +#: window border). A single value sets all four sides. Two values set +#: the vertical and horizontal sides. Three values set top, horizontal +#: and bottom. Four values set top, right, bottom and left. + +# placement_strategy center + +#: When the window size is not an exact multiple of the cell size, the +#: cell area of the terminal window will have some extra padding on +#: the sides. You can control how that padding is distributed with +#: this option. Using a value of center means the cell area will be +#: placed centrally. A value of top-left means the padding will be on +#: only the bottom and right edges. + +# active_border_color #00ff00 + +#: The color for the border of the active window. Set this to none to +#: not draw borders around the active window. + +# inactive_border_color #cccccc + +#: The color for the border of inactive windows + +# bell_border_color #ff5a00 + +#: The color for the border of inactive windows in which a bell has +#: occurred + +# inactive_text_alpha 1.0 + +#: Fade the text in inactive windows by the specified amount (a number +#: between zero and one, with zero being fully faded). + +# hide_window_decorations no + +#: Hide the window decorations (title-bar and window borders) with +#: yes. On macOS, titlebar-only can be used to only hide the titlebar. +#: Whether this works and exactly what effect it has depends on the +#: window manager/operating system. + +# resize_debounce_time 0.1 + +#: The time (in seconds) to wait before redrawing the screen when a +#: resize event is received. On platforms such as macOS, where the +#: operating system sends events corresponding to the start and end of +#: a resize, this number is ignored. + +# resize_draw_strategy static + +#: Choose how kitty draws a window while a resize is in progress. A +#: value of static means draw the current window contents, mostly +#: unchanged. A value of scale means draw the current window contents +#: scaled. A value of blank means draw a blank window. A value of size +#: means show the window size in cells. + +# resize_in_steps no + +#: Resize the OS window in steps as large as the cells, instead of +#: with the usual pixel accuracy. Combined with an +#: initial_window_width and initial_window_height in number of cells, +#: this option can be used to keep the margins as small as possible +#: when resizing the OS window. Note that this does not currently work +#: on Wayland. + +# confirm_os_window_close 0 + +#: Ask for confirmation when closing an OS window or a tab that has at +#: least this number of kitty windows in it. A value of zero disables +#: confirmation. This confirmation also applies to requests to quit +#: the entire application (all OS windows, via the quit action). + +#: }}} + +#: Tab bar {{{ + +# tab_bar_edge bottom + +#: Which edge to show the tab bar on, top or bottom + +# tab_bar_margin_width 0.0 + +#: The margin to the left and right of the tab bar (in pts) + +# tab_bar_style fade + +#: The tab bar style, can be one of: fade, separator, powerline, or +#: hidden. In the fade style, each tab's edges fade into the +#: background color, in the separator style, tabs are separated by a +#: configurable separator, and the powerline shows the tabs as a +#: continuous line. If you use the hidden style, you might want to +#: create a mapping for the select_tab action which presents you with +#: a list of tabs and allows for easy switching to a tab. + +# tab_bar_min_tabs 2 + +#: The minimum number of tabs that must exist before the tab bar is +#: shown + +# tab_switch_strategy previous + +#: The algorithm to use when switching to a tab when the current tab +#: is closed. The default of previous will switch to the last used +#: tab. A value of left will switch to the tab to the left of the +#: closed tab. A value of right will switch to the tab to the right of +#: the closed tab. A value of last will switch to the right-most tab. + +# tab_fade 0.25 0.5 0.75 1 + +#: Control how each tab fades into the background when using fade for +#: the tab_bar_style. Each number is an alpha (between zero and one) +#: that controls how much the corresponding cell fades into the +#: background, with zero being no fade and one being full fade. You +#: can change the number of cells used by adding/removing entries to +#: this list. + +# tab_separator " ┇" + +#: The separator between tabs in the tab bar when using separator as +#: the tab_bar_style. + +# tab_powerline_style angled + +#: The powerline separator style between tabs in the tab bar when +#: using powerline as the tab_bar_style, can be one of: angled, +#: slanted, or round. + +# tab_activity_symbol none + +#: Some text or a unicode symbol to show on the tab if a window in the +#: tab that does not have focus has some activity. + +# tab_title_template "{title}" + +#: A template to render the tab title. The default just renders the +#: title. If you wish to include the tab-index as well, use something +#: like: {index}: {title}. Useful if you have shortcuts mapped for +#: goto_tab N. In addition you can use {layout_name} for the current +#: layout name and {num_windows} for the number of windows in the tab. +#: Note that formatting is done by Python's string formatting +#: machinery, so you can use, for instance, {layout_name[:2].upper()} +#: to show only the first two letters of the layout name, upper-cased. +#: If you want to style the text, you can use styling directives, for +#: example: {fmt.fg.red}red{fmt.fg.default}normal{fmt.bg._00FF00}green +#: bg{fmt.bg.normal}. Similarly, for bold and italic: +#: {fmt.bold}bold{fmt.nobold}normal{fmt.italic}italic{fmt.noitalic}. + +# active_tab_title_template none + +#: Template to use for active tabs, if not specified falls back to +#: tab_title_template. + +# active_tab_foreground #000 +# active_tab_background #eee +# active_tab_font_style bold-italic +# inactive_tab_foreground #444 +# inactive_tab_background #999 +# inactive_tab_font_style normal + +#: Tab bar colors and styles + +# tab_bar_background none + +#: Background color for the tab bar. Defaults to using the terminal +#: background color. + +#: }}} + +#: Color scheme {{{ + +# foreground #dddddd +# background #000000 + +#: The foreground and background colors + +# background_opacity 1.0 + +#: The opacity of the background. A number between 0 and 1, where 1 is +#: opaque and 0 is fully transparent. This will only work if +#: supported by the OS (for instance, when using a compositor under +#: X11). Note that it only sets the background color's opacity in +#: cells that have the same background color as the default terminal +#: background. This is so that things like the status bar in vim, +#: powerline prompts, etc. still look good. But it means that if you +#: use a color theme with a background color in your editor, it will +#: not be rendered as transparent. Instead you should change the +#: default background color in your kitty config and not use a +#: background color in the editor color scheme. Or use the escape +#: codes to set the terminals default colors in a shell script to +#: launch your editor. Be aware that using a value less than 1.0 is a +#: (possibly significant) performance hit. If you want to dynamically +#: change transparency of windows set dynamic_background_opacity to +#: yes (this is off by default as it has a performance cost) + +# background_image none + +#: Path to a background image. Must be in PNG format. + +# background_image_layout tiled + +#: Whether to tile or scale the background image. + +# background_image_linear no + +#: When background image is scaled, whether linear interpolation +#: should be used. + +# dynamic_background_opacity no + +#: Allow changing of the background_opacity dynamically, using either +#: keyboard shortcuts (increase_background_opacity and +#: decrease_background_opacity) or the remote control facility. + +# background_tint 0.0 + +#: How much to tint the background image by the background color. The +#: tint is applied only under the text area, not margin/borders. Makes +#: it easier to read the text. Tinting is done using the current +#: background color for each window. This setting applies only if +#: background_opacity is set and transparent windows are supported or +#: background_image is set. + +# dim_opacity 0.75 + +#: How much to dim text that has the DIM/FAINT attribute set. One +#: means no dimming and zero means fully dimmed (i.e. invisible). + +# selection_foreground #000000 + +#: The foreground for text selected with the mouse. A value of none +#: means to leave the color unchanged. + +# selection_background #fffacd + +#: The background for text selected with the mouse. + + +#: The 256 terminal colors. There are 8 basic colors, each color has a +#: dull and bright version, for the first 16 colors. You can set the +#: remaining 240 colors as color16 to color255. + +# color0 #000000 +# color8 #767676 + +#: black + +# color1 #cc0403 +# color9 #f2201f + +#: red + +# color2 #19cb00 +# color10 #23fd00 + +#: green + +# color3 #cecb00 +# color11 #fffd00 + +#: yellow + +# color4 #0d73cc +# color12 #1a8fff + +#: blue + +# color5 #cb1ed1 +# color13 #fd28ff + +#: magenta + +# color6 #0dcdcd +# color14 #14ffff + +#: cyan + +# color7 #dddddd +# color15 #ffffff + +#: white + +# mark1_foreground black + +#: Color for marks of type 1 + +# mark1_background #98d3cb + +#: Color for marks of type 1 (light steel blue) + +# mark2_foreground black + +#: Color for marks of type 2 + +# mark2_background #f2dcd3 + +#: Color for marks of type 1 (beige) + +# mark3_foreground black + +#: Color for marks of type 3 + +# mark3_background #f274bc + +#: Color for marks of type 1 (violet) + +#: }}} + +#: Advanced {{{ + +# shell . + +#: The shell program to execute. The default value of . means to use +#: whatever shell is set as the default shell for the current user. +#: Note that on macOS if you change this, you might need to add +#: --login to ensure that the shell starts in interactive mode and +#: reads its startup rc files. + +# editor . + +#: The console editor to use when editing the kitty config file or +#: similar tasks. A value of . means to use the environment variables +#: VISUAL and EDITOR in that order. Note that this environment +#: variable has to be set not just in your shell startup scripts but +#: system-wide, otherwise kitty will not see it. + +# close_on_child_death no + +#: Close the window when the child process (shell) exits. If no (the +#: default), the terminal will remain open when the child exits as +#: long as there are still processes outputting to the terminal (for +#: example disowned or backgrounded processes). If yes, the window +#: will close as soon as the child process exits. Note that setting it +#: to yes means that any background processes still using the terminal +#: can fail silently because their stdout/stderr/stdin no longer work. + +# allow_remote_control no + +#: Allow other programs to control kitty. If you turn this on other +#: programs can control all aspects of kitty, including sending text +#: to kitty windows, opening new windows, closing windows, reading the +#: content of windows, etc. Note that this even works over ssh +#: connections. You can chose to either allow any program running +#: within kitty to control it, with yes or only programs that connect +#: to the socket specified with the kitty --listen-on command line +#: option, if you use the value socket-only. The latter is useful if +#: you want to prevent programs running on a remote computer over ssh +#: from controlling kitty. + +# listen_on none + +#: Tell kitty to listen to the specified unix/tcp socket for remote +#: control connections. Note that this will apply to all kitty +#: instances. It can be overridden by the kitty --listen-on command +#: line flag. This option accepts only UNIX sockets, such as +#: unix:${TEMP}/mykitty or (on Linux) unix:@mykitty. Environment +#: variables are expanded. If {kitty_pid} is present then it is +#: replaced by the PID of the kitty process, otherwise the PID of the +#: kitty process is appended to the value, with a hyphen. This option +#: is ignored unless you also set allow_remote_control to enable +#: remote control. See the help for kitty --listen-on for more +#: details. + +# env + +#: Specify environment variables to set in all child processes. Note +#: that environment variables are expanded recursively, so if you +#: use:: + +#: env MYVAR1=a +#: env MYVAR2=${MYVAR1}/${HOME}/b + +#: The value of MYVAR2 will be a/<path to home directory>/b. + +# update_check_interval 0.0 + +#: Periodically check if an update to kitty is available. If an update +#: is found a system notification is displayed informing you of the +#: available update. The default is to check every 24 hrs, set to zero +#: to disable. + +# startup_session none + +#: Path to a session file to use for all kitty instances. Can be +#: overridden by using the kitty --session command line option for +#: individual instances. See +#: https://sw.kovidgoyal.net/kitty/index.html#sessions in the kitty +#: documentation for details. Note that relative paths are interpreted +#: with respect to the kitty config directory. Environment variables +#: in the path are expanded. + +# clipboard_control write-clipboard write-primary + +#: Allow programs running in kitty to read and write from the +#: clipboard. You can control exactly which actions are allowed. The +#: set of possible actions is: write-clipboard read-clipboard write- +#: primary read-primary. You can additionally specify no-append to +#: disable kitty's protocol extension for clipboard concatenation. The +#: default is to allow writing to the clipboard and primary selection +#: with concatenation enabled. Note that enabling the read +#: functionality is a security risk as it means that any program, even +#: one running on a remote server via SSH can read your clipboard. + +# allow_hyperlinks yes + +#: Process hyperlink (OSC 8) escape sequences. If disabled OSC 8 +#: escape sequences are ignored. Otherwise they become clickable +#: links, that you can click by holding down ctrl+shift and clicking +#: with the mouse. The special value of ``ask`` means that kitty will +#: ask before opening the link. + +# term xterm-kitty + +#: The value of the TERM environment variable to set. Changing this +#: can break many terminal programs, only change it if you know what +#: you are doing, not because you read some advice on Stack Overflow +#: to change it. The TERM variable is used by various programs to get +#: information about the capabilities and behavior of the terminal. If +#: you change it, depending on what programs you run, and how +#: different the terminal you are changing it to is, various things +#: from key-presses, to colors, to various advanced features may not +#: work. + +#: }}} + +#: OS specific tweaks {{{ + +# wayland_titlebar_color system + +#: Change the color of the kitty window's titlebar on Wayland systems +#: with client side window decorations such as GNOME. A value of +#: system means to use the default system color, a value of background +#: means to use the background color of the currently active window +#: and finally you can use an arbitrary color, such as #12af59 or red. + +# macos_titlebar_color system + +#: Change the color of the kitty window's titlebar on macOS. A value +#: of system means to use the default system color, a value of +#: background means to use the background color of the currently +#: active window and finally you can use an arbitrary color, such as +#: #12af59 or red. WARNING: This option works by using a hack, as +#: there is no proper Cocoa API for it. It sets the background color +#: of the entire window and makes the titlebar transparent. As such it +#: is incompatible with background_opacity. If you want to use both, +#: you are probably better off just hiding the titlebar with +#: hide_window_decorations. + +# macos_option_as_alt no + +#: Use the option key as an alt key. With this set to no, kitty will +#: use the macOS native Option+Key = unicode character behavior. This +#: will break any Alt+key keyboard shortcuts in your terminal +#: programs, but you can use the macOS unicode input technique. You +#: can use the values: left, right, or both to use only the left, +#: right or both Option keys as Alt, instead. + +# macos_hide_from_tasks no + +#: Hide the kitty window from running tasks (⌘+Tab) on macOS. + +# macos_quit_when_last_window_closed no + +#: Have kitty quit when all the top-level windows are closed. By +#: default, kitty will stay running, even with no open windows, as is +#: the expected behavior on macOS. + +# macos_window_resizable yes + +#: Disable this if you want kitty top-level (OS) windows to not be +#: resizable on macOS. + +# macos_thicken_font 0 + +#: Draw an extra border around the font with the given width, to +#: increase legibility at small font sizes. For example, a value of +#: 0.75 will result in rendering that looks similar to sub-pixel +#: antialiasing at common font sizes. + +# macos_traditional_fullscreen no + +#: Use the traditional full-screen transition, that is faster, but +#: less pretty. + +# macos_show_window_title_in all + +#: Show or hide the window title in the macOS window or menu-bar. A +#: value of window will show the title of the currently active window +#: at the top of the macOS window. A value of menubar will show the +#: title of the currently active window in the macOS menu-bar, making +#: use of otherwise wasted space. all will show the title everywhere +#: and none hides the title in the window and the menu-bar. + +# macos_custom_beam_cursor no + +#: Enable/disable custom mouse cursor for macOS that is easier to see +#: on both light and dark backgrounds. WARNING: this might make your +#: mouse cursor invisible on dual GPU machines. + +# linux_display_server auto + +#: Choose between Wayland and X11 backends. By default, an appropriate +#: backend based on the system state is chosen automatically. Set it +#: to x11 or wayland to force the choice. + +#: }}} + +#: Keyboard shortcuts {{{ + +#: Keys are identified simply by their lowercase unicode characters. +#: For example: ``a`` for the A key, ``[`` for the left square bracket +#: key, etc. For functional keys, such as ``Enter or Escape`` the +#: names are present at https://sw.kovidgoyal.net/kitty/keyboard- +#: protocol.html#functional-key-definitions. For a list of modifier +#: names, see: GLFW mods +#: <https://www.glfw.org/docs/latest/group__mods.html> + +#: On Linux you can also use XKB key names to bind keys that are not +#: supported by GLFW. See XKB keys +#: <https://github.com/xkbcommon/libxkbcommon/blob/master/xkbcommon/xkbcommon- +#: keysyms.h> for a list of key names. The name to use is the part +#: after the XKB_KEY_ prefix. Note that you can only use an XKB key +#: name for keys that are not known as GLFW keys. + +#: Finally, you can use raw system key codes to map keys, again only +#: for keys that are not known as GLFW keys. To see the system key +#: code for a key, start kitty with the kitty --debug-keyboard option. +#: Then kitty will output some debug text for every key event. In that +#: text look for ``native_code`` the value of that becomes the key +#: name in the shortcut. For example: + +#: .. code-block:: none + +#: on_key_input: glfw key: 65 native_code: 0x61 action: PRESS mods: 0x0 text: 'a' + +#: Here, the key name for the A key is 0x61 and you can use it with:: + +#: map ctrl+0x61 something + +#: to map ctrl+a to something. + +#: You can use the special action no_op to unmap a keyboard shortcut +#: that is assigned in the default configuration:: + +#: map kitty_mod+space no_op + +#: You can combine multiple actions to be triggered by a single +#: shortcut, using the syntax below:: + +#: map key combine <separator> action1 <separator> action2 <separator> action3 ... + +#: For example:: + +#: map kitty_mod+e combine : new_window : next_layout + +#: this will create a new window and switch to the next available +#: layout + +#: You can use multi-key shortcuts using the syntax shown below:: + +#: map key1>key2>key3 action + +#: For example:: + +#: map ctrl+f>2 set_font_size 20 + +# kitty_mod ctrl+shift + +#: The value of kitty_mod is used as the modifier for all default +#: shortcuts, you can change it in your kitty.conf to change the +#: modifiers for all the default shortcuts. + +# clear_all_shortcuts no + +#: You can have kitty remove all shortcut definition seen up to this +#: point. Useful, for instance, to remove the default shortcuts. + +# kitten_alias hints hints --hints-offset=0 + +#: You can create aliases for kitten names, this allows overriding the +#: defaults for kitten options and can also be used to shorten +#: repeated mappings of the same kitten with a specific group of +#: options. For example, the above alias changes the default value of +#: kitty +kitten hints --hints-offset to zero for all mappings, +#: including the builtin ones. + +#: Clipboard {{{ + +# map kitty_mod+c copy_to_clipboard + +#: There is also a copy_or_interrupt action that can be optionally +#: mapped to Ctrl+c. It will copy only if there is a selection and +#: send an interrupt otherwise. Similarly, copy_and_clear_or_interrupt +#: will copy and clear the selection or send an interrupt if there is +#: no selection. + +# map kitty_mod+v paste_from_clipboard +# map kitty_mod+s paste_from_selection +# map shift+insert paste_from_selection +# map kitty_mod+o pass_selection_to_program + +#: You can also pass the contents of the current selection to any +#: program using pass_selection_to_program. By default, the system's +#: open program is used, but you can specify your own, the selection +#: will be passed as a command line argument to the program, for +#: example:: + +#: map kitty_mod+o pass_selection_to_program firefox + +#: You can pass the current selection to a terminal program running in +#: a new kitty window, by using the @selection placeholder:: + +#: map kitty_mod+y new_window less @selection + +#: }}} + +#: Scrolling {{{ + +# map kitty_mod+up scroll_line_up +# map kitty_mod+k scroll_line_up +# map kitty_mod+down scroll_line_down +# map kitty_mod+j scroll_line_down +map shift+page_up scroll_page_up +map shift+page_down scroll_page_down +map shift+home scroll_home +map shift+end scroll_end +# map kitty_mod+h show_scrollback + +#: You can pipe the contents of the current screen + history buffer as +#: STDIN to an arbitrary program using the ``launch`` function. For +#: example, the following opens the scrollback buffer in less in an +#: overlay window:: + +#: map f1 launch --stdin-source=@screen_scrollback --stdin-add-formatting --type=overlay less +G -R + +#: For more details on piping screen and buffer contents to external +#: programs, see launch. + +#: }}} + +#: Window management {{{ + +# map kitty_mod+enter new_window + +#: You can open a new window running an arbitrary program, for +#: example:: + +#: map kitty_mod+y launch mutt + +#: You can open a new window with the current working directory set to +#: the working directory of the current window using:: + +#: map ctrl+alt+enter launch --cwd=current + +#: You can open a new window that is allowed to control kitty via the +#: kitty remote control facility by prefixing the command line with @. +#: Any programs running in that window will be allowed to control +#: kitty. For example:: + +#: map ctrl+enter launch --allow-remote-control some_program + +#: You can open a new window next to the currently active window or as +#: the first window, with:: + +#: map ctrl+n launch --location=neighbor some_program +#: map ctrl+f launch --location=first some_program + +#: For more details, see launch. + +# map kitty_mod+n new_os_window + +#: Works like new_window above, except that it opens a top level OS +#: kitty window. In particular you can use new_os_window_with_cwd to +#: open a window with the current working directory. + +# map kitty_mod+w close_window +# map kitty_mod+] next_window +# map kitty_mod+[ previous_window +# map kitty_mod+f move_window_forward +# map kitty_mod+b move_window_backward +# map kitty_mod+` move_window_to_top +# map kitty_mod+r start_resizing_window +# map kitty_mod+1 first_window +# map kitty_mod+2 second_window +# map kitty_mod+3 third_window +# map kitty_mod+4 fourth_window +# map kitty_mod+5 fifth_window +# map kitty_mod+6 sixth_window +# map kitty_mod+7 seventh_window +# map kitty_mod+8 eighth_window +# map kitty_mod+9 ninth_window +# map kitty_mod+0 tenth_window +#: }}} + +#: Tab management {{{ + +# map kitty_mod+right next_tab +# map kitty_mod+left previous_tab +# map kitty_mod+t new_tab +# map kitty_mod+q close_tab +# map kitty_mod+. move_tab_forward +# map kitty_mod+, move_tab_backward +# map kitty_mod+alt+t set_tab_title + +#: You can also create shortcuts to go to specific tabs, with 1 being +#: the first tab, 2 the second tab and -1 being the previously active +#: tab, and any number larger than the last tab being the last tab:: + +#: map ctrl+alt+1 goto_tab 1 +#: map ctrl+alt+2 goto_tab 2 + +#: Just as with new_window above, you can also pass the name of +#: arbitrary commands to run when using new_tab and use +#: new_tab_with_cwd. Finally, if you want the new tab to open next to +#: the current tab rather than at the end of the tabs list, use:: + +#: map ctrl+t new_tab !neighbor [optional cmd to run] +#: }}} + +#: Layout management {{{ + +# map kitty_mod+l next_layout + +#: You can also create shortcuts to switch to specific layouts:: + +#: map ctrl+alt+t goto_layout tall +#: map ctrl+alt+s goto_layout stack + +#: Similarly, to switch back to the previous layout:: + +#: map ctrl+alt+p last_used_layout +#: }}} + +#: Font sizes {{{ + +#: You can change the font size for all top-level kitty OS windows at +#: a time or only the current one. + +# map kitty_mod+equal change_font_size all +2.0 +# map kitty_mod+plus change_font_size all +2.0 +# map kitty_mod+kp_add change_font_size all +2.0 +# map kitty_mod+minus change_font_size all -2.0 +# map kitty_mod+kp_subtract change_font_size all -2.0 +# map kitty_mod+backspace change_font_size all 0 + +#: To setup shortcuts for specific font sizes:: + +#: map kitty_mod+f6 change_font_size all 10.0 + +#: To setup shortcuts to change only the current OS window's font +#: size:: + +#: map kitty_mod+f6 change_font_size current 10.0 +#: }}} + +#: Select and act on visible text {{{ + +#: Use the hints kitten to select text and either pass it to an +#: external program or insert it into the terminal or copy it to the +#: clipboard. + +# map kitty_mod+e kitten hints + +#: Open a currently visible URL using the keyboard. The program used +#: to open the URL is specified in open_url_with. + +# map kitty_mod+p>f kitten hints --type path --program - + +#: Select a path/filename and insert it into the terminal. Useful, for +#: instance to run git commands on a filename output from a previous +#: git command. + +# map kitty_mod+p>shift+f kitten hints --type path + +#: Select a path/filename and open it with the default open program. + +# map kitty_mod+p>l kitten hints --type line --program - + +#: Select a line of text and insert it into the terminal. Use for the +#: output of things like: ls -1 + +# map kitty_mod+p>w kitten hints --type word --program - + +#: Select words and insert into terminal. + +# map kitty_mod+p>h kitten hints --type hash --program - + +#: Select something that looks like a hash and insert it into the +#: terminal. Useful with git, which uses sha1 hashes to identify +#: commits + +# map kitty_mod+p>n kitten hints --type linenum + +#: Select something that looks like filename:linenum and open it in +#: vim at the specified line number. + +# map kitty_mod+p>y kitten hints --type hyperlink + +#: Select a hyperlink (i.e. a URL that has been marked as such by the +#: terminal program, for example, by ls --hyperlink=auto). + + +#: The hints kitten has many more modes of operation that you can map +#: to different shortcuts. For a full description see kittens/hints. +#: }}} + +#: Miscellaneous {{{ + +# map kitty_mod+f11 toggle_fullscreen +# map kitty_mod+f10 toggle_maximized +# map kitty_mod+u kitten unicode_input +# map kitty_mod+f2 edit_config_file +# map kitty_mod+escape kitty_shell window + +#: Open the kitty shell in a new window/tab/overlay/os_window to +#: control kitty using commands. + +# map kitty_mod+a>m set_background_opacity +0.1 +# map kitty_mod+a>l set_background_opacity -0.1 +# map kitty_mod+a>1 set_background_opacity 1 +# map kitty_mod+a>d set_background_opacity default +# map kitty_mod+delete clear_terminal reset active + +#: You can create shortcuts to clear/reset the terminal. For example:: + +#: # Reset the terminal +#: map kitty_mod+f9 clear_terminal reset active +#: # Clear the terminal screen by erasing all contents +#: map kitty_mod+f10 clear_terminal clear active +#: # Clear the terminal scrollback by erasing it +#: map kitty_mod+f11 clear_terminal scrollback active +#: # Scroll the contents of the screen into the scrollback +#: map kitty_mod+f12 clear_terminal scroll active + +#: If you want to operate on all windows instead of just the current +#: one, use all instead of active. + +#: It is also possible to remap Ctrl+L to both scroll the current +#: screen contents into the scrollback buffer and clear the screen, +#: instead of just clearing the screen:: + +#: map ctrl+l combine : clear_terminal scroll active : send_text normal,application \x0c + + +#: You can tell kitty to send arbitrary (UTF-8) encoded text to the +#: client program when pressing specified shortcut keys. For example:: + +#: map ctrl+alt+a send_text all Special text + +#: This will send "Special text" when you press the ctrl+alt+a key +#: combination. The text to be sent is a python string literal so you +#: can use escapes like \x1b to send control codes or \u21fb to send +#: unicode characters (or you can just input the unicode characters +#: directly as UTF-8 text). The first argument to send_text is the +#: keyboard modes in which to activate the shortcut. The possible +#: values are normal or application or kitty or a comma separated +#: combination of them. The special keyword all means all modes. The +#: modes normal and application refer to the DECCKM cursor key mode +#: for terminals, and kitty refers to the special kitty extended +#: keyboard protocol. + +#: Another example, that outputs a word and then moves the cursor to +#: the start of the line (same as pressing the Home key):: + +#: map ctrl+alt+a send_text normal Word\x1b[H +#: map ctrl+alt+a send_text application Word\x1bOH + +#: }}} + +# }}} diff --git a/tw/services/files/mimeapps.list b/tw/services/files/mimeapps.list new file mode 100644 index 00000000..6cbf5ce9 --- /dev/null +++ b/tw/services/files/mimeapps.list @@ -0,0 +1,57 @@ +[Default Applications] +inode/directory=ranger.desktop +x-scheme-handler/http=icecat.desktop +x-scheme-handler/https=icecat.desktop +x-scheme-handler/chrome=icecat.desktop +x-scheme-handler/about=icecat.desktop +x-scheme-handler/unknown=icecat.desktop +x-scheme-handler/mailto=aerc.desktop +application/x-extension-htm=icecat.desktop +application/x-extension-html=icecat.desktop +application/x-extension-shtml=icecat.desktop +application/xhtml+xml=icecat.desktop +application/x-extension-xhtml=icecat.desktop +application/x-extension-xht=icecat.desktop +application/octet-stream=emacsclient.desktop +text/html=icecat.desktop +text/xml=icecat.desktop +text/plain=emacsclient.desktop +text/english=emacsclient.desktop +text/x-makefile=emacsclient.desktop +text/x-c++hdr=emacsclient.desktop +text/x-c++src=emacsclient.desktop +text/x-chdr=emacsclient.desktop +text/x-java=emacsclient.desktop +text/x-moc=emacsclient.desktop +text/x-pascal=emacsclient.desktop +text/x-tcl=emacsclient.desktop +text/x-tex=emacsclient.desktop +text/x-c=emacsclient.desktop +text/x-c++=emacsclient.desktop +application/x-shellscript=emacsclient.desktop +image/bmp=imv.desktop +image/gif=imv.desktop +image/jpeg=imv.desktop +image/jpg=imv.desktop +image/pjpeg=imv.desktop +image/png=imv.desktop +image/tiff=imv.desktop +image/x-bmp=imv.desktop +image/x-pcx=imv.desktop +image/x-png=imv.desktop +image/x-portable-anymap=imv.desktop +image/x-portable-bitmap=imv.desktop +image/x-portable-graymap=imv.desktop +image/x-portable-pixmap=imv.desktop +image/x-tga=imv.desktop +image/x-xbitmap=imv.desktop +image/heif=imv.desktop +image/webp=imv.desktop +application/pdf=org.pwmt.zathura-pdf-poppler.desktop +application/postscript=org.pwmt.zathura-ps.desktop +application/eps=org.pwmt.zathura-ps.desktop +application/x-eps=org.pwmt.zathura-ps.desktop +image/eps=org.pwmt.zathura-ps.desktop +image/x-eps=org.pwmt.zathura-ps.desktop + +[Added Associations] diff --git a/tw/services/files/newsboat.conf b/tw/services/files/newsboat.conf new file mode 100644 index 00000000..7959e138 --- /dev/null +++ b/tw/services/files/newsboat.conf @@ -0,0 +1,29 @@ +# newsboat config -*- conf-space -*- +# https://newsboat.org/releases/2.29/docs/newsboat.html#_newsboat_configuration_commands +# Vim-like keys. +bind-key j down +bind-key k up +bind-key J next-feed articlelist +bind-key K prev-feed articlelist + +# Reload feeds on startup, in parallel. +auto-reload yes +reload-threads 100 + +text-width 72 # wrap rendered HTML at 72 cols (or terminal width, if smaller) +scrolloff 2 # show 2 lines above/below selected line +show-keymap-hint no +show-title-bar yes +datetime-format "%e %b %Y" # e.g. " 9 Dec 2022" +notify-program "dunstify -a newsboat -i newsboat Newsboat" +notify-format "%d new articles (%n unread articles, %f unread feeds)" + +# Sync with Nextcloud News. +urls-source "ocnews" +ocnews-url "https://cloud.wilkenfamily.de/" +ocnews-login "timo" +ocnews-passwordeval "pass www/nextcloud/timo | head -1" +ocnews-flag-star "s" + +# Catppuccin theme. +include ~/.config/newsboat/config.catppuccin diff --git a/tw/services/files/passmenu b/tw/services/files/passmenu new file mode 100755 index 00000000..9bf7f7e3 --- /dev/null +++ b/tw/services/files/passmenu @@ -0,0 +1,93 @@ +#!/bin/sh -eu + +usage() { + cat << EOF +$(basename "$0") [-c | -p | -a] + + -c, --clip copy the user-selected password to the clipboard + -p, --type-pass auto-type the user-selected password only + -o, --type-otp auto-type the user-selected six-digit OTP code + -a, --type-all auto-type the user-selected username <tab> password + -h, --help show this help message and exit + -v, --version show the program version number and exit + +Later options override conflicting earlier ones. +If no option is given, -c/--clip is the default. +GNU-style combination of short options (e.g. -pa) is not supported. + +Abnormal exit codes: + 1 no password selected by user + 2 invalid command-line argument + 3 internal error + +(C) 2019-2023 Timo Wilken; MIT Licence. +Adapted from https://git.zx2c4.com/password-store/tree/contrib/dmenu/passmenu. +EOF +} + +version() { + # Changelog: + # 1.0.0 (2019-??-??) initial version + # 1.0.1 (2022-07-17) script formatting; throw away passwords asap + # 1.0.2 (2022-10-??) remove fix_xdotool; this should be done on login + # 1.0.3 (2023-12-11) customise prompt to show what will be typed + echo "$(basename "$0") 1.0.3" +} + +password_names() { + find "${PASSWORD_STORE_DIR-$HOME/.password-store}" -name '*.gpg' -type f \ + -printf '%P\n' | sed 's/\.gpg$//' +} + +extract_key() { + sed -rn "s/^$1:\\s+(.+)\$/\\1/p" +} + +type_stdin() { + tr -d '\n' | xdotool getactivewindow type --clearmodifiers --file - +} + +## Command-line arguments +while [ $# -gt 0 ]; do + case "$1" in + -o|--type-otp) mode=type-otp prompt=OTP; shift;; + -p|--type-pass) mode=type-pass prompt=Password; shift;; + -a|--type-all) mode=type-all prompt=Login; shift;; + -c|--clip) mode=clip prompt=Copy; shift;; + -h|--help) usage; exit;; + -v|--version) version; exit;; + + *) + echo "$(basename "$0"): unknown option: $1" >&2 + usage >&2 + exit 2;; + esac +done +: "${mode=clip}" "${prompt=Copy}" + +## Password selection menu +password_name=$(password_names | rofi -dmenu -i -p "$prompt" -no-custom) +[ -n "$password_name" ] || exit 1 + +## Password typing +case "$mode" in + clip) + # Suppress "copied ... to clipboard" notice on stdout. + pass show --clip "$password_name" > /dev/null;; + + type-otp) + pass otp "$password_name" | type_stdin;; + + type-pass|type-all) + entry=$(pass show "$password_name") + if [ "$mode" = type-all ]; then + echo "$entry" | extract_key username | type_stdin + xdotool getactivewindow key Tab + fi + echo "$entry" | head -1 | type_stdin + unset entry;; + + *) + echo "$(basename "$0"): internal error: unknown mode: $mode" >&2 + exit 3;; +esac diff --git a/tw/services/files/picom.conf b/tw/services/files/picom.conf new file mode 100644 index 00000000..a7d86571 --- /dev/null +++ b/tw/services/files/picom.conf @@ -0,0 +1,304 @@ +# +# ~/.config/picom.conf -- Picom compositor configuration +# + +## Backend + +# Backend to use: "xrender" or "glx". +# GLX backend is typically much faster but depends on a sane driver. +backend: "glx"; + +## GLX backend + +glx-no-stencil: true; + +# GLX backend: Copy unmodified regions from front buffer instead of redrawing +# them all. My tests with nvidia-drivers show a 10% decrease in performance +# when the whole screen is modified, but a 20% increase when only 1/4 is. My +# tests on nouveau show terrible slowdown. +glx-copy-from-front: false; + +# GLX backend: Avoid rebinding pixmap on window damage. Probably could improve +# performance on rapid window content changes, but is known to break things on +# some drivers (LLVMpipe). Recommended if it works. +glx-no-rebind-pixmap: true; + +## Shadows + +# Enabled client-side shadows on windows. +shadow: false; +# The blur radius for shadows. (default 12) +shadow-radius: 25; +# The left offset for shadows. (default -15) +shadow-offset-x: -25; +# The top offset for shadows. (default -15) +shadow-offset-y: -25; +# The translucency for shadows. (default .75) +shadow-opacity: .3; + +# Set if you want different colour shadows +shadow-red: 0.03; +shadow-green: 0.03; +shadow-blue: 0.04; + +# The shadow exclude options are helpful if you have shadows enabled. Due to +# the way compton draws its shadows, certain applications will have visual +# glitches (most applications are fine, only apps that do weird things with +# xshapes or argb are affected). This list includes all the affected apps I +# found in my testing. The "! name~=''" part excludes shadows on any "Unknown" +# windows, this prevents a visual glitch with the XFWM alt tab switcher. +# From "man picom", Format of Conditions: WM_CLASS = class_i, class_g +shadow-exclude: [ +# "! name~=''", +# "name = 'Notification'", +# "name = 'Plank'", +# "name = 'Docky'", +# "name = 'Kupfer'", +# "name = 'xfce4-notifyd'", +# "name *= 'VLC'", + "name *= 'mpv'", + "class_g = 'ffplay'", +# "name *= 'compton'", +# "name *= 'Chromium'", +# "name *= 'Chrome'", + "class_g ?= 'Firefox'", +# "class_g = 'Conky'", + "_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'", + "_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'", + "_GTK_FRAME_EXTENTS@:c", + "class_g ?= 'ulauncher'", + "class_g ?= 'tray'", + "class_g ?= 'i3-frame'", +# "class_g ?= 'Notify-osd'", +# "class_g ?= 'Cairo-dock'", +# "class_g ?= 'Xfce4-notifyd'", +# "class_g ?= 'Xfce4-power-manager'" + "class_g ?= 'Xfce4-screenshooter'", + "class_g ?= 'peek'" +]; + +# Avoid drawing shadow on all shaped windows (c.f. --detect-rounded-corners) +shadow-ignore-shaped: false; + +## Opacity + +inactive-opacity: 1; +active-opacity: 1; +frame-opacity: 1; +inactive-opacity-override: false; + +# Dim inactive windows. (0.0 - 1.0) +#inactive-dim = 0.1; +# Do not let dimness adjust based on window opacity. +#inactive-dim-fixed = true; + +# Blur background of transparent windows. Bad performance with X Render +# backend. GLX backend is preferred. +blur-method: "dual_kawase"; +blur-strength: 7; +#blur-method: "kernel"; +# generate kernel using compton-convgen.py --dump-compton gaussian 15 -f sigma=15 +#blur-kernel: "..."; +blur-background: true; +# Blur background of opaque windows with transparent frames as well. +blur-background-frame: true; +# Do not let blur radius adjust based on window opacity. +blur-background-fixed: true; +blur-background-exclude: [ + #"window_type = 'dock'", + #"window_type = 'desktop'", + "window_type = 'dnd'", + "window_type = 'dropdown_menu'", + "window_type = 'popup_menu'", + #"class_g = 'Rofi'" + "class_g ?= 'Xfce4-screenshooter'", + # for xfce4-screenshooter triggered from its xfce4-panel button + "class_g ?= 'Wrapper-2.0'", + "class_g ?= 'peek'" +]; + +## Rounded corners +#corner-radius: 16; +#rounded-corners-exclude: [ +# "window_type = 'dock'", +# "window_type = 'desktop'", +# "class_g ?= 'plasmashell'", +# "class_g ?= 'krunner'", +# "class_g ?= 'i3-frame'" +#]; + +## Fading + +# Fade windows during opacity changes. +fading: true; +# The time between steps in a fade in milliseconds. (default 10). +fade-delta: 5; +# Opacity change between steps while fading in. (default 0.028). +fade-in-step: 0.03; +# Opacity change between steps while fading out. (default 0.03). +fade-out-step: 0.03; +# Fade windows in/out when opening/closing +no-fading-openclose: false; + +# Specify a list of conditions of windows that should not be faded. +fade-exclude: []; + +## Other + +# Try to detect WM windows and mark them as active. +mark-wmwin-focused: true; +# Mark all non-WM but override-redirect windows active (e.g. menus). +mark-ovredir-focused: true; +# Use EWMH _NET_WM_ACTIVE_WINDOW to determine which window is focused instead +# of using FocusIn/Out events. Usually more reliable but depends on a +# EWMH-compliant WM. +use-ewmh-active-win: true; +# Detect rounded corners and treat them as rectangular when +# --shadow-ignore-shaped is on. +detect-rounded-corners: true; + +# Detect _NET_WM_OPACITY on client windows, useful for window managers not +# passing _NET_WM_OPACITY of client windows to frame windows. This prevents +# opacity being ignored for some apps. For example without this enabled my +# xfce4-notifyd is 100% opacity no matter what. +detect-client-opacity: true; + +# Toggle VSync. See also: --vsync drm/opengl/opengl-oml. +vsync: true; + +# Enable DBE painting mode, intended to use with VSync to (hopefully) eliminate +# tearing. Reported to have no effect, though. +dbe: true; + +# Unredirect all windows if a full-screen opaque window is detected, to +# maximize performance for full-screen windows, like games. Known to cause +# flickering when redirecting/unredirecting windows. paint-on-overlay may make +# the flickering less obvious. +unredir-if-possible: true; + +# Specify a list of conditions of windows that should always be considered focused. +focus-exclude: []; + +# Use WM_TRANSIENT_FOR to group windows, and consider windows in the same group +# focused at the same time. +detect-transient: true; +# Use WM_CLIENT_LEADER to group windows, and consider windows in the same group +# focused at the same time. WM_TRANSIENT_FOR has higher priority if +# --detect-transient is enabled, too. +detect-client-leader: true; + +opacity-rule: [ + "100:name *?= 'Call'", + "100:name *?= 'Conky'", + "100:class_g = 'Darktable'", + "50:class_g = 'Dmenu'", + "100:name *?= 'Event'", + "100:class_g = 'Firefox'", + "100:class_g = 'GIMP'", + "100:name *?= 'Image'", + "100:class_g = 'Lazpaint'", + "100:class_g = 'Midori'", + "100:name *?= 'Minitube'", + "83:class_g = 'Mousepad'", + "100:name *?= 'MuseScore'", + "90:name *?= 'Page Info'", + "100:name *?= 'Pale Moon'", + "100:name *?= 'Screenshot'", + "100:class_g = 'Viewnior'", + "100:name *?= 'VirtualBox'", + "100:name *?= 'VLC'", + "100:class_g = 'mpv'", + "100:name *?= 'Write'", + "0:_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'", + "100:_NET_WM_STATE@:32a *= '_NET_WM_STATE_STICKY'" +]; + +## Window type settings + +wintypes: { + # WINDOW_TYPE is one of the 15 window types defined in the EWMH standard: + # https://specifications.freedesktop.org/wm-spec/latest/ar01s05.html#idm45550357242464 + # fade: Fade the particular type of windows. + # shadow: Give those windows shadow + # opacity: Default opacity for the type of windows. + # focus: Controls whether the window of this type is to be always considered + # focused. (By default, all window types except "normal" and "dialog" has + # this on.) + # full-shadow: Controls whether shadow is drawn under the parts of the + # window that you normally won't be able to see. Useful when the window + # has parts of it transparent, and you want shadows in those areas. + # redir-ignore: Controls whether this type of windows should cause screen to + # become redirected again after been unredirected. If you have + # --unredir-if-possible set, and doesn't want certain window to cause + # unnecessary screen redirection, you can set this to true. + + normal: { + opacity: 1; + }; + + dialog: { + opacity: 1; + }; + + # On-screen notification + notify: { + opacity: 1; + }; + + tooltip: { + opacity: .85; + }; + + # Desktop window with icons etc. + desktop: { + }; + + # Persistent dock, usually on top of all other windows + dock: { + opacity: 1; + }; + + # Window representing something being dragged + dnd: { + opacity: .85; + shadow: true; + full-shadow: true; + }; + + # Menu "torn off" from another window + menu: { + opacity: 1; + }; + + # Toolbar "torn off" from another window + toolbar: { + opacity: 1; + }; + + # A menu from a right click + popup_menu: { + opacity: 1; + }; + + # A menu from a menu bar + dropdown_menu: { + opacity: 1; + }; + + # The pop-up/drop-down from a combo box + combo: { + opacity: 1; + }; + + # A starting application's splash screen + splash: { + opacity: 1; + }; + + # A small persistent utility window, such as a palette or toolbox + utility: { + }; + + unknown: { + }; +}; diff --git a/tw/services/files/rofi.rasi b/tw/services/files/rofi.rasi new file mode 100644 index 00000000..83363c14 --- /dev/null +++ b/tw/services/files/rofi.rasi @@ -0,0 +1,41 @@ +/* -*- mode: css -*- */ +configuration { + modi: "combi,windowcd,calc"; + combi-modi: "window,drun,session:sessionmenu,ssh,run"; + terminal: "rofi-sensible-terminal"; + icon-theme: "Papirus-Dark"; + drun-show-actions: true; /* show actions defined in .desktop files as well */ + combi-display-format: "{text}"; /* hide {mode} prefix */ + show-icons: true; + disable-history: false; + case-sensitive: false; + cycle: true; + matching: "normal"; + scroll-method: 0; + /* Needed by Catppuccin theme: */ + sidebar-mode: true; + hide-scrollbar: true; + location: 0; + /* End of theme-related config. */ + display-window: "Windows"; + display-windowcd: "Workspace"; + display-run: "Run"; + display-ssh: "SSH"; + display-drun: "Desktop"; + display-combi: "Combined"; + display-calc: "Calculator"; + display-session: "Session"; + display-keys: "Keys"; + display-filebrowser: "Files"; + display-emoji: "Emoji"; + timeout { + action: "kb-cancel"; + delay: 0; + } + filebrowser { + directories-first: true; + sorting-method: "name"; + } +} + +@theme "catppuccin" diff --git a/tw/services/files/sessionmenu b/tw/services/files/sessionmenu new file mode 100755 index 00000000..91839d8e --- /dev/null +++ b/tw/services/files/sessionmenu @@ -0,0 +1,38 @@ +#!/usr/bin/env -S guile --no-auto-compile +!# +(use-modules (ice-9 format) + (ice-9 match) + (ice-9 ports)) + +(define (call-command/stderr . command) + "Call COMMAND using `system*', but redirect all output to stderr." + (with-output-to-port (current-error-port) + (lambda () (apply system* command)))) + +(match (command-line) + ((_ "quit") + (exit 0)) + ((_ "Reload i3 configuration") + (call-command/stderr "i3-msg" "reload")) + ((_ "Sleep") + ;; "screenlock" blocks until unlocked by the user, so run in background. + ;; TODO: write "mem" to /sys/power/state, but it's owned by root. + (let ((locker (spawn "screenlock" '("screenlock"))) + (sleepfile (open-file "/sys/power/state" "w"))) + (display "mem" sleepfile) + (close sleepfile) + (waitpid locker))) + ((_ "Log out") + (call-command/stderr "i3-msg" "exit")) + ((_ "Shutdown") + (call-command/stderr "sudo" "-n" "/run/current-system/profile/sbin/shutdown")) + ((_ "Reboot") + (call-command/stderr "sudo" "-n" "/run/current-system/profile/sbin/reboot")) + (_ + (format #t "\0~a\x1f~a~%~{~a\0icon\x1f~a~%~}" + "prompt" "Session" + '("Reload i3 configuration" "reload" + "Sleep" "system-suspend" + "Log out" "system-log-out" + "Shutdown" "system-shutdown" + "Reboot" "system-reboot")))) diff --git a/tw/services/files/vdirsyncer.conf b/tw/services/files/vdirsyncer.conf new file mode 100644 index 00000000..0745c98f --- /dev/null +++ b/tw/services/files/vdirsyncer.conf @@ -0,0 +1,87 @@ +[general] +status_path = "~/.local/share/vdirsyncer/status" + +# Main contact list from Nextcloud. +[pair main_contacts] +a = "nextcloud_main_contacts" +b = "local_main_contacts" +metadata = ["displayname", "description"] +collections = ["from a", "from b"] +conflict_resolution = "a wins" + +[storage local_main_contacts] +type = "filesystem" +path = "~/.local/share/vdirsyncer/main-contacts" +fileext = ".vcf" + +[storage nextcloud_main_contacts] +type = "carddav" +url = "https://cloud.wilkenfamily.de/remote.php/dav/addressbooks/users/timo/contacts/" +username.fetch = ["shell", "~/.guix-home/profile/bin/pass www/nextcloud/timo | awk '/^username: /{print $2}'"] +password.fetch = ["shell", "~/.guix-home/profile/bin/pass www/nextcloud/timo | head -1"] + +# "Sandbox Contacts" from Nextcloud, mostly for WhatsApp. +[pair sandbox_contacts] +a = "nextcloud_sandbox_contacts" +b = "local_sandbox_contacts" +metadata = ["displayname", "description"] +collections = ["from a", "from b"] +conflict_resolution = "a wins" + +[storage local_sandbox_contacts] +type = "filesystem" +path = "~/.local/share/vdirsyncer/sandbox-contacts" +fileext = ".vcf" + +[storage nextcloud_sandbox_contacts] +type = "carddav" +url = "https://cloud.wilkenfamily.de/remote.php/dav/addressbooks/users/timo/sandbox-contacts/" +username.fetch = ["shell", "~/.guix-home/profile/bin/pass www/nextcloud/timo | awk '/^username: /{print $2}'"] +password.fetch = ["shell", "~/.guix-home/profile/bin/pass www/nextcloud/timo | head -1"] + +# Calendar from Nextcloud. +[pair calendars] +a = "nextcloud_calendars" +b = "local_calendars" +metadata = ["color", "displayname", "description", "order"] +collections = ["from a", "from b"] +conflict_resolution = "a wins" + +[storage local_calendars] +type = "filesystem" +path = "~/.local/share/vdirsyncer/calendars" +fileext = ".ics" + +[storage nextcloud_calendars] +type = "caldav" +url = "https://cloud.wilkenfamily.de/remote.php/dav/principals/users/timo/" +username.fetch = ["shell", "~/.guix-home/profile/bin/pass www/nextcloud/timo | awk '/^username: /{print $2}'"] +password.fetch = ["shell", "~/.guix-home/profile/bin/pass www/nextcloud/timo | head -1"] + +# Work Indico calendar (read-only). +[pair indico] +a = "indico_calendar" +b = "local_indico_calendar" +metadata = [] +collections = null +conflict_resolution = "a wins" + +[storage local_indico_calendar] +type = "filesystem" +path = "~/.local/share/vdirsyncer/indico" +fileext = ".ics" + +[storage indico_calendar] +type = "http" +# The URL contains an access token, so get it from pass. +url.fetch = ["shell", "~/.guix-home/profile/bin/pass cern/indico-calendar-url | head -1"] + +[storage local_cern_calendar] +type = "filesystem" +path = "~/.local/share/vdirsyncer/cern" +fileext = ".ics" + +[storage cern_calendar] +type = "http" +# The URL contains an access token, so get it from pass. +url.fetch = ["shell", "~/.guix-home/profile/bin/pass cern/exol/calendar-url | head -1"] diff --git a/tw/services/files/vimrc b/tw/services/files/vimrc new file mode 100644 index 00000000..9c48346f --- /dev/null +++ b/tw/services/files/vimrc @@ -0,0 +1,60 @@ +let mapleader = "\<SPACE>" +let maplocalleader = "\\" + +set showcmd " show command as they are typed +set showmatch " show matching brackets, briefly jump to matching one +set matchtime=0 " tenths of a sec to jump to matching brackets +set showmode " show NORMAL/INSERT/VISUAL indicator +set ruler " show cursor position +set number " show line numbers +set cursorline " highlight current line +set modeline " check for modelines +set hlsearch " highlight search results +set ignorecase " case-insensitive searching +set smartcase " ...unless query has capital letters +set incsearch " incremental search +set gdefault " :s/search/replace/ has g by default +set magic " use extended regexes +set wildmenu " autocomplete :commands +set nolazyredraw " redraw during macro execution etc. +set foldlevelstart=10 " open most folds by default +set foldmethod=syntax " (or marker, manual, expr, syntax, diff) +set noequalalways " don't resize all windows when closing/opening another +set eadirection=both " 'equalalways' applies horizontally and vertically + +set expandtab " tabs are actually spaces +set tabstop=4 " tab width +set softtabstop=4 " when reading a '\t', it will be this wide +set shiftwidth=4 " autoindent tab width +set list " show whitespace with characters in 'listchars' +" possible chars: eol, tab, space, trail, extends, precedes, conceal, nbsp +set listchars=tab:>\ ,trail:_ " highlight tabs and trailing spaces specially +set showbreak=>\ " character to show at start of wrapped lines +set nojoinspaces " don't add two spaces after [.!?] + +set scrolloff=5 " always show these many lines around the current one +set sidescrolloff=15 " always show these many columns around the current one +set colorcolumn=80 " highlight 80th column +set textwidth=79 " break long lines on whitespace when inserted +set linebreak " wrap by words (affects display only) +set breakindent " wrapped lines have same virtual indent as first line +set formatoptions=tcqn2 " preserve textwidth, comments, allow gq, numbered + " lists, second line indent + +set mouse=a " use mouse in terminal; press shift to disable temporarily +set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50 + \,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor + \,sm:block-blinkwait175-blinkoff150-blinkon175 + +" Fix colours in kitty -- see :help xterm-true-color. +set termguicolors +let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum" +let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum" + +" Enable auto-highlighting and auto-detection of file types and indentation rules. +filetype on +filetype plugin on +filetype indent on +syntax on + +source ~/.vim/catppuccin.vim diff --git a/tw/services/files/volume b/tw/services/files/volume new file mode 100755 index 00000000..96398553 --- /dev/null +++ b/tw/services/files/volume @@ -0,0 +1,60 @@ +#!/usr/bin/env -S guile --no-auto-compile +!# +(use-modules (ice-9 format) + (ice-9 match) + (ice-9 popen) + (ice-9 regex) + (ice-9 textual-ports)) + +(define (read-from-pactl . args) + (let* ((port (apply open-pipe* OPEN_READ "pactl" args)) + (output (get-string-all port))) + (close-pipe port) + (string-trim-right output #\newline))) + +(define %default-sink + (read-from-pactl "get-default-sink")) + +(define* (sink-muted? #:optional (sink %default-sink)) + (match (read-from-pactl "get-sink-mute" sink) + ("Mute: yes" #t) + ("Mute: no" #f) + (output (error "Unknown `pactl get-sink-mute' output" output)))) + +(define* (sink-volume #:optional (sink %default-sink)) + (match-let ((`#(,match (,start . ,end)) + (string-match "[0-9]+%" (read-from-pactl "get-sink-volume" sink)))) + (string->number (substring match start (1- end))))) ; trim trailing "%" + +(define* (set-sink-mute! #:optional (state "toggle") (sink %default-sink)) + (status:exit-val + (system* "pactl" "set-sink-mute" sink state))) + +(define* (increment-sink-volume! increment-percent #:optional (sink %default-sink)) + (status:exit-val + (system* "pactl" "set-sink-volume" sink + ;; A percentage with a sign is an increment. + (format #f "~@d%" increment-percent)))) + +(define* (notify #:optional (muted? (sink-muted?)) (volume (sink-volume))) + (status:exit-val + (system* "dunstify" "-a" "volume" "-u" "low" + "-i" (cond (muted? "audio-volume-muted") + ((< volume 50) "audio-volume-low") + (#t "audio-volume-high")) + "-h" "string:x-canonical-private-synchronous:volume" + "-h" (format #f "int:value:~d" (if muted? 0 volume)) + (if muted? "Volume muted" "Volume")))) + +(match (cdr (program-arguments)) + (() 0) ; notify only + (("mute") (set-sink-mute! "true")) + (("unmute") (set-sink-mute! "false")) + (("toggle-mute") (set-sink-mute! "toggle")) + (((? string->number increment-percent)) + (and (set-sink-mute! "false") + (increment-sink-volume! + (string->number increment-percent)))) + (args (error "Could not parse command-line arguments:" args))) + +(notify) diff --git a/tw/services/files/zathurarc b/tw/services/files/zathurarc new file mode 100644 index 00000000..06a9351f --- /dev/null +++ b/tw/services/files/zathurarc @@ -0,0 +1,32 @@ +# see man zathurarc -*- mode: conf-space -*- + +# [c]ommand line, [s]tatus bar, [v]ertical/[h]orizontal scrollbar +set guioptions s +set recolor true +set recolor-keephue false +set recolor-reverse-video true +set render-loading true + +set scroll-hstep -1 +set scroll-step 40 +set scroll-full-overlap 0.0 +set scroll-page-aware true + +set window-title-basename true +set window-title-home-tilde true +set window-title-page false +set statusbar-basename false +set statusbar-home-tilde true + +set selection-clipboard clipboard +set selection-notification true + +# Completion +set show-directories true +set show-hidden true +set show-recent 10 + +# Theme +set font "Hermit 10" +set page-padding 0 # px between pages +include catppuccin |