├── .envrc ├── .gitattributes ├── .gitignore ├── .ignore ├── .mailmap ├── .stylua.toml ├── .styluaignore ├── .typos.toml ├── LICENSE ├── README.md ├── config ├── .curlrc ├── .gemrc ├── .hammerspoon │ ├── .gitignore │ ├── Spoons │ │ └── SpoonInstall.spoon │ │ │ ├── docs.json │ │ │ └── init.lua │ ├── init.lua │ ├── layout.lua │ ├── log.lua │ ├── mappings.lua │ ├── utils.lua │ └── window-management.lua ├── .ignore ├── .mailcap ├── .npmrc ├── .psqlrc ├── .ssh │ ├── config │ └── s │ │ └── .gitkeep ├── .terminfo │ └── 74 │ │ └── tmux-256color ├── aider │ └── config.yml ├── atuin │ └── config.toml ├── bat │ └── config ├── claude │ └── CLAUDE.md ├── direnv │ └── direnvrc ├── firefox │ └── chrome │ │ ├── userChrome.css │ │ └── userContent.css ├── ghostty │ ├── config │ └── themes │ │ └── mine ├── git │ ├── attributes │ ├── config │ ├── hooks │ │ └── pre-commit │ └── ignore ├── gnupg │ └── gpg.conf ├── karabiner │ ├── .gitignore │ └── karabiner.json ├── kitty │ ├── dark-theme.auto.conf │ ├── kitty.app.icns │ ├── kitty.conf │ ├── launch-actions.conf │ ├── light-theme.auto.conf │ ├── macos-launch-services-cmdline │ ├── mime.types │ ├── no-preference-theme.auto.conf │ ├── open-actions.conf │ └── themes │ │ ├── Aquarium Light.conf │ │ ├── Dawnfox.conf │ │ └── color.conf ├── mods │ └── mods.yml ├── mpv │ ├── input.conf │ └── mpv.conf ├── neomutt │ ├── config │ │ ├── bindings.mutt │ │ └── colors.mutt │ ├── neomuttrc │ └── scripts │ │ ├── dump-ical.py │ │ ├── view-attachment.sh │ │ └── view-mail.sh ├── nvim │ ├── .gitignore │ ├── after │ │ ├── ftplugin │ │ │ ├── audio.lua │ │ │ ├── fzf.lua │ │ │ ├── gitcommit.lua │ │ │ ├── go.lua │ │ │ ├── help.lua │ │ │ ├── http.lua │ │ │ ├── javascript.lua │ │ │ ├── javascriptreact.lua │ │ │ ├── json.lua │ │ │ ├── lua.lua │ │ │ ├── mail.lua │ │ │ ├── make.lua │ │ │ ├── man.lua │ │ │ ├── markdown.lua │ │ │ ├── nix.lua │ │ │ ├── python.lua │ │ │ ├── qf.lua │ │ │ ├── rust.lua │ │ │ ├── typescript.lua │ │ │ ├── typescriptreact.lua │ │ │ ├── vim.lua │ │ │ └── zsh.lua │ │ ├── plugin │ │ │ ├── javascript.lua │ │ │ └── netrw.lua │ │ ├── queries │ │ │ ├── comment │ │ │ │ └── highlights.scm │ │ │ ├── go │ │ │ │ └── highlights.scm │ │ │ ├── javascript │ │ │ │ └── highlights.scm │ │ │ ├── markdown │ │ │ │ ├── folds.scm │ │ │ │ └── highlights.scm │ │ │ ├── python │ │ │ │ └── highlights.scm │ │ │ └── typescript │ │ │ │ └── highlights.scm │ │ └── syntax │ │ │ └── diff.lua │ ├── colors │ │ └── plain.lua │ ├── filetype.lua │ ├── ftdetect │ │ ├── audio.lua │ │ ├── image.lua │ │ ├── typescript.lua │ │ └── video.lua │ ├── init.lua │ ├── lua │ │ ├── _ │ │ │ ├── autocmds.lua │ │ │ ├── foldexpr.lua │ │ │ ├── quotes.lua │ │ │ └── utils │ │ │ │ ├── au.lua │ │ │ │ ├── highlight.lua │ │ │ │ └── init.lua │ │ └── plugins │ │ │ ├── ai.lua │ │ │ ├── completion.lua │ │ │ ├── formatter.lua │ │ │ ├── fzf.lua │ │ │ ├── git.lua │ │ │ ├── go.lua │ │ │ ├── init.lua │ │ │ ├── leetcode.lua │ │ │ ├── lsp.lua │ │ │ ├── markdown.lua │ │ │ ├── mini.lua │ │ │ ├── oil.lua │ │ │ ├── snacks.lua │ │ │ ├── snippets.lua │ │ │ ├── treesitter.lua │ │ │ └── undotree.lua │ ├── plugin │ │ ├── autocmnds.lua │ │ ├── color.lua │ │ ├── commands.lua │ │ ├── cron-explainer.lua │ │ ├── diagnostics.lua │ │ ├── grep.lua │ │ ├── mappings.lua │ │ ├── statuscolumn.lua │ │ └── statusline.lua │ └── spell │ │ ├── nl.utf-8.spl │ │ ├── nl.utf-8.sug │ │ └── spell.add ├── pandoc │ └── bookmark.lua ├── pip │ └── pip.conf ├── python │ └── .pythonrc.py ├── ripgrep │ └── config ├── tig │ └── config ├── tmux │ ├── .gitignore │ ├── scripts │ │ ├── get-prayer │ │ ├── next-prayer │ │ │ ├── Makefile │ │ │ ├── aladhan │ │ │ │ └── aladhan.go │ │ │ ├── cmd │ │ │ │ └── next-prayer │ │ │ │ │ └── main.go │ │ │ ├── go.mod │ │ │ ├── mawaqit │ │ │ │ └── mawaqit.go │ │ │ ├── next-prayer.nix │ │ │ └── shared │ │ │ │ └── shared.go │ │ ├── tmux-github-status │ │ ├── tmux-npm-status │ │ └── tmux-weather │ └── tmux.conf ├── vivid │ └── theme.yml ├── weechat │ ├── buflist.conf │ ├── irc.conf │ ├── plugins.conf │ ├── sec.conf │ └── weechat.conf ├── yazi │ ├── init.lua │ ├── keymap.toml │ ├── plugins │ │ ├── folder-rules.yazi │ │ │ └── main.lua │ │ ├── reveal-in-finder.yazi │ │ │ └── main.lua │ │ └── smart-paste.yazi │ │ │ └── main.lua │ ├── theme.toml │ └── yazi.toml ├── yt-dlp │ └── config ├── zk │ ├── config.toml │ └── templates │ │ ├── default.md │ │ ├── journal.md │ │ ├── personal.md │ │ ├── rfc.md │ │ └── til.md └── zsh.d │ ├── .p10k.zsh │ ├── .zshenv │ └── zsh │ ├── .gitignore │ ├── .zshrc │ ├── bin │ ├── +x │ ├── battery │ ├── bbd │ ├── bookmark │ ├── changemac │ ├── colorgrid │ ├── cpssh │ ├── delta_ │ ├── dst │ ├── exit │ ├── extract │ ├── fco │ ├── fgd │ ├── find-exec │ ├── flakify │ ├── g │ ├── get-keychain-pass │ ├── git-author-stats │ ├── git-conflicts │ ├── git-continue │ ├── git-contributors │ ├── git-credit │ ├── git-edit │ ├── git-exclude │ ├── git-ignore │ ├── git-mirrors │ ├── git-rank │ ├── git-recent │ ├── git-rel │ ├── git-shower │ ├── git-snap │ ├── git-st │ ├── git-stats │ ├── git-thanks │ ├── git-undopush │ ├── git-wt │ ├── killport │ ├── l │ ├── mkcd │ ├── mkssh │ ├── mx │ ├── mx-init │ ├── nixify │ ├── nyan │ ├── o │ ├── octocat │ ├── osx-ls-download-history │ ├── osx-rm-download-history │ ├── previewer │ ├── psu │ ├── serve │ ├── ssht │ ├── sys │ ├── terminal-test │ ├── todos │ ├── togglemode │ ├── ts │ ├── vs │ ├── weather │ └── wifi │ └── config │ ├── aliases.zsh │ ├── completion.zsh │ ├── input.zsh │ └── options.zsh ├── flake.lock ├── flake.nix ├── install ├── neovim.toml ├── nix ├── hosts │ ├── alcantara.nix │ ├── nixos │ │ ├── default.nix │ │ ├── dwm.patch │ │ └── hardware-configuration.nix │ ├── pandoras-box.nix │ └── rocket.nix ├── modules │ ├── darwin │ │ └── default.nix │ └── shared │ │ ├── ai.nix │ │ ├── bat.nix │ │ ├── default.nix │ │ ├── discord.nix │ │ ├── ghostty.nix │ │ ├── git.nix │ │ ├── go.nix │ │ ├── gpg.nix │ │ ├── gui.nix │ │ ├── hammerspoon.nix │ │ ├── irc.nix │ │ ├── karabiner.nix │ │ ├── kitty.nix │ │ ├── mail.nix │ │ ├── misc.nix │ │ ├── mpv.nix │ │ ├── node.nix │ │ ├── python.nix │ │ ├── ripgrep.nix │ │ ├── rust.nix │ │ ├── settings.nix │ │ ├── shell.nix │ │ ├── ssh.nix │ │ ├── tmux.nix │ │ ├── vim.nix │ │ ├── yazi.nix │ │ ├── yt-dlp.nix │ │ └── zk.nix └── pkgs │ ├── hcron.nix │ └── pragmatapro.nix ├── screenshot.png ├── selene.toml └── templates ├── bun ├── .envrc ├── flake.nix └── tsconfig.json ├── deno ├── .envrc ├── deno.jsonc └── flake.nix ├── go ├── .envrc └── flake.nix ├── node ├── .envrc ├── .nvmrc └── flake.nix ├── plain ├── .envrc └── flake.nix ├── python-script ├── .envrc └── flake.nix ├── python ├── .envrc └── flake.nix ├── readme.md └── rust ├── .envrc └── flake.nix /.envrc: -------------------------------------------------------------------------------- 1 | set -e 2 | set +u 3 | use flake 4 | dotenv_if_exists 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | config/weechat/*.conf filter=crypt diff=crypt merge=crypt 2 | .npmrc filter=crypt diff=crypt merge=crypt 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | scratch 2 | !.ignore 3 | result 4 | .claude 5 | -------------------------------------------------------------------------------- /.ignore: -------------------------------------------------------------------------------- 1 | pack/ 2 | logs/ 3 | result/ 4 | .direnv/ 5 | config/.hammerspoon/Spoons 6 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Ahmed El Gabri 2 | Ahmed El Gabri 3 | Ahmed El Gabri 4 | Ahmed El Gabri 5 | Ahmed El Gabri 6 | -------------------------------------------------------------------------------- /.stylua.toml: -------------------------------------------------------------------------------- 1 | line_endings = "Unix" 2 | quote_style = "AutoPreferSingle" 3 | call_parentheses = "None" 4 | column_width = 80 5 | indent_width = 2 6 | 7 | [sort_requires] 8 | enabled = true 9 | -------------------------------------------------------------------------------- /.styluaignore: -------------------------------------------------------------------------------- 1 | config/nvim/pack 2 | config/nvim/undo 3 | -------------------------------------------------------------------------------- /.typos.toml: -------------------------------------------------------------------------------- 1 | [files] 2 | extend-exclude = ["config/weechat/*.conf"] 3 | ignore-hidden = false 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /config/.curlrc: -------------------------------------------------------------------------------- 1 | # man curl 2 | # You can pass -A "USER AGENT" instead 3 | # user-agent = "Mozilla/5.0 Gecko" 4 | referer = ";auto" 5 | connect-timeout = 30 6 | location 7 | progress-bar 8 | max-time = 90 9 | show-error 10 | -------------------------------------------------------------------------------- /config/.gemrc: -------------------------------------------------------------------------------- 1 | gem: --no-ri --no-rdoc 2 | install: --no-rdoc --no-ri 3 | update: --no-rdoc --no-ri 4 | -------------------------------------------------------------------------------- /config/.hammerspoon/.gitignore: -------------------------------------------------------------------------------- 1 | Spoons/ 2 | !Spoons/SpoonInstall.spoon/ 3 | hosts/ 4 | -------------------------------------------------------------------------------- /config/.hammerspoon/layout.lua: -------------------------------------------------------------------------------- 1 | local utils = require 'utils' 2 | -- ------------------------------------------------------------------- 3 | -- Layout management 4 | -- ------------------------------------------------------------------- 5 | local screens = { 6 | main = hs.screen.primaryScreen(), 7 | samsung = hs.screen 'S24R65x', 8 | LG = hs.screen 'LG HDR 4K', 9 | } 10 | 11 | --- 12 | -- Screen watcher 13 | --- 14 | 15 | local function SwitchLayout() 16 | local allScreens = hs.screen.allScreens() 17 | local moreThanOneScreen = #allScreens > 1 18 | local contains = hs.fnutils.contains 19 | 20 | local layout = { 21 | { 22 | utils.appMap.chrome, 23 | nil, 24 | (moreThanOneScreen and (contains(allScreens, screens.LG) or contains( 25 | allScreens, 26 | screens.samsung 27 | ))) and (screens.LG or screens.samsung) or screens.main, 28 | hs.layout.maximized, 29 | nil, 30 | nil, 31 | }, 32 | { utils.appMap.x, nil, screens.main, hs.layout.right30, nil, nil }, 33 | { utils.appMap.slack, nil, screens.main, hs.layout.maximized, nil, nil }, 34 | -- { 35 | -- appMap.brave, 36 | -- nil, 37 | -- screens.main, 38 | -- hs.layout.maximized, 39 | -- nil, 40 | -- nil 41 | -- } 42 | } 43 | 44 | if moreThanOneScreen then 45 | hs.notify.show( 46 | 'Hammerspoon', 47 | #allScreens .. ' monitor layout activated', 48 | (screens.LG or screens.samsung or screens.main):name() 49 | ) 50 | end 51 | 52 | hs.layout.apply(layout) 53 | end 54 | 55 | SwitchLayout() 56 | 57 | return { 58 | layoutWatcher = hs.screen.watcher.newWithActiveScreen(SwitchLayout), 59 | } 60 | -------------------------------------------------------------------------------- /config/.hammerspoon/log.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- Simple logging facility. 3 | -- 4 | 5 | -- Possible values, from most to least verbose: 6 | -- 7 | -- - verbose 8 | -- - debug 9 | -- - info 10 | -- - warning (the Hammerspoon default) 11 | -- - error 12 | -- - nothing 13 | -- 14 | local logLevel = 'info' 15 | 16 | local log = hs.logger.new('ahmed', logLevel) 17 | 18 | local module = { 19 | d = log.d, 20 | df = log.df, 21 | i = log.i, 22 | w = log.w, 23 | wf = log.wf, 24 | e = log.e, 25 | ef = log.ef, 26 | 27 | -- Convenience methods, simpler than doing this in the console: 28 | -- 29 | -- hs.logger.setGlobalLogLevel('debug') 30 | -- 31 | debug = function() 32 | log.setLogLevel 'debug' 33 | end, 34 | info = function() 35 | log.setLogLevel 'info' 36 | end, 37 | verbose = function() 38 | log.setLogLevel 'verbose' 39 | end, 40 | warning = function() 41 | log.setLogLevel 'warning' 42 | end, 43 | error = function() 44 | log.setLogLevel 'error' 45 | end, 46 | nothing = function() 47 | log.setLogLevel 'nothing' 48 | end, 49 | } 50 | 51 | -- Add this separately in order to avoid a syntax error. 52 | module['if'] = log['if'] 53 | 54 | return module 55 | -------------------------------------------------------------------------------- /config/.hammerspoon/utils.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | function M.deepMerge(tbl1, tbl2) 4 | for k, v in pairs(tbl2) do 5 | if type(v) == 'table' and type(tbl1[k]) == 'table' then 6 | -- If it's a list, then concat 7 | if v[1] ~= nil and tbl1[k][1] ~= nil then 8 | tbl1[k] = hs.fnutils.concat(tbl1[k], v) 9 | else 10 | -- Otherwise it's a map 11 | tbl1[k] = M.deepMerge(tbl1[k], v) 12 | end 13 | else 14 | tbl1[k] = v 15 | end 16 | end 17 | return tbl1 18 | end 19 | 20 | -- Returns the bundle ID of an application, given its path. 21 | function M.appID(app) 22 | if hs.application.infoForBundlePath(app) then 23 | return hs.application.infoForBundlePath(app)['CFBundleIdentifier'] 24 | end 25 | end 26 | 27 | M.appMap = { 28 | -- Browsers 29 | chrome = M.appID '/Applications/Chrome.app', 30 | firefox = M.appID '/Applications/Firefox.app', 31 | zen = M.appID '/Applications/Zen Browser.app', 32 | safari = M.appID '/Applications/Safari.app', 33 | 34 | -- Terminals 35 | kitty = M.appID '/Applications/kitty.app', 36 | ghostty = M.appID '/Applications/Ghostty.app', 37 | 38 | -- Socials 39 | -- Both suck 40 | x = M.appID '/Applications/X.app' 41 | or M.appID '~/Applications/Chrome Apps.localized/X.app', 42 | -- bluesky = 'dev.mozzius.graysky', 43 | 44 | -- Chat 45 | discord = M.appID '/Applications/Discord.app', 46 | slack = M.appID '/Applications/Slack.app', 47 | imessage = M.appID '/System/Applications/Messages.app', 48 | 49 | -- Productivity 50 | calendar = M.appID '/Applications/Notion Calendar.app', 51 | ['1password'] = M.appID '/Applications/1Password.app', 52 | 53 | -- Meetings 54 | zoom = M.appID '/Applications/zoom.us.app', 55 | meet = M.appID '~/Applications/Chrome Apps.localized/Google Meet.app', 56 | } 57 | 58 | return M 59 | -------------------------------------------------------------------------------- /config/.ignore: -------------------------------------------------------------------------------- 1 | # vim:ft=gitconfig 2 | .git/ 3 | .DS_Store 4 | node_modules/ 5 | .next/ 6 | .cache/ 7 | .netlify/ 8 | .yarn/ 9 | -------------------------------------------------------------------------------- /config/.npmrc: -------------------------------------------------------------------------------- 1 | U2FsdGVkX18VOa4Ujyg1gVCRYqYK7j6Qrf9v+WnbNG/PHVxISGcQnYE8OQ6IQGAw 2 | FHOQ7aGz9cL/8d2uu58DByRHNEDiH1+yichj4IywqwS6IEG57yVo2/sNvckY7b8i 3 | Mcn4JK3Aa0YUw+n/CkHlR2sanSj1iDsrQgkubmPVZcqVavlDrJIOSU4SMew5TLCJ 4 | lsTOXRPaLBOlEa01lfAtovXL7C5pp6dcGm9DNDBQODcTQkPTS5aZDgoacxoPDZWe 5 | 12zVhMC6smxCp6Rxt2PXi1vzlYW3iQJjt5iawNY2/MzDAOEPx2HwNp7YUHEcZpB8 6 | Kr/BqCe0Up07BoBj2X6ADQK8vccEK8HFpgnC/OCkFGeTexR14ONDs38Sw3jV6bz3 7 | tlDL1VDiInNcyr4nvTxxq5c3wmKoxM+DHhWLCjKmwelca04RpmBVRu4UlE9vuzhE 8 | VAFwZHnNwMMYNEgligyXGMJPzjGQL/Qw/VlIbOL4qWymKq77T2XVJT4byuHo3dZC 9 | TMAeFTs0QB3q014T5xweug== 10 | -------------------------------------------------------------------------------- /config/.psqlrc: -------------------------------------------------------------------------------- 1 | \set PROMPT1 '%[%033[31;5m%]%M %[%033[32;1m%]%n@%/%R%[%033[0m%]%# ' 2 | \set PROMPT2 '[more] %R > ' 3 | 4 | -- By default, NULL displays as an empty space. Is it actually an empty 5 | -- string, or is it null? This makes that distinction visible. 6 | \pset null '[NULL]' 7 | 8 | -- Use table format (with headers across the top) by default, but switch to 9 | -- expanded table format when there's a lot of data, which makes it much 10 | -- easier to read. 11 | \x auto 12 | 13 | -- Verbose error reports. 14 | \set VERBOSITY verbose 15 | 16 | -- Use a separate history file per-database. 17 | \set HISTFILE ~/.psql_history- :HOST - :DBNAME 18 | 19 | -- If a command is run more than once in a row, only store it once in the 20 | -- history. 21 | \set HISTCONTROL ignoredups 22 | 23 | -- Autocomplete keywords (like SELECT) in upper-case, even if you started 24 | -- typing them in lower case. 25 | \set COMP_KEYWORD_CASE upper 26 | -------------------------------------------------------------------------------- /config/.ssh/config: -------------------------------------------------------------------------------- 1 | # include directives can't appear after a host block 2 | Include config.d/* 3 | 4 | Host * 5 | Ciphers aes128-ctr 6 | PasswordAuthentication no 7 | ChallengeResponseAuthentication no 8 | HashKnownHosts yes 9 | AddKeysToAgent yes 10 | # https://ricostacruz.com/til/using-separate-ssh-keys-per-host 11 | # IdentityFile ~/.ssh/keys/%r@%h 12 | # UseKeychain yes 13 | Compression yes 14 | # SSH Multiplexing 15 | ControlPath ~/.ssh/%C.sock 16 | ControlMaster auto 17 | ControlPersist 10m 18 | # Always use SSH2 19 | Protocol 2 20 | # https://github.com/wincent/wincent/commit/7a216c1fb5fe6bba934fe5c260399d460e9ef16e 21 | # GlobalKnownHostsFile /dev/null 22 | # UpdateHostKeys no 23 | # UserKnownHostsFile /dev/null 24 | # StrictHostKeyChecking no 25 | 26 | Host github 27 | HostName git@github.com 28 | forwardAgent yes 29 | -------------------------------------------------------------------------------- /config/.ssh/s/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedelgabri/dotfiles/e7f65a22b13edaf42bd76522313db20239430985/config/.ssh/s/.gitkeep -------------------------------------------------------------------------------- /config/.terminfo/74/tmux-256color: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedelgabri/dotfiles/e7f65a22b13edaf42bd76522313db20239430985/config/.terminfo/74/tmux-256color -------------------------------------------------------------------------------- /config/bat/config: -------------------------------------------------------------------------------- 1 | --theme="Nord" 2 | --style="plain,changes" 3 | --italic-text=always 4 | --map-syntax '.*ignore:Git Ignore' 5 | --map-syntax '.gitconfig.local:Git Config' 6 | --map-syntax '**/mx*:Bourne Again Shell (bash)' 7 | --map-syntax '**/completions/_*:Bourne Again Shell (bash)' 8 | --map-syntax '.zsh*:Bourne Again Shell (bash)' 9 | --map-syntax '.vimrc.local:VimL' 10 | --map-syntax 'vimrc:VimL' 11 | -------------------------------------------------------------------------------- /config/claude/CLAUDE.md: -------------------------------------------------------------------------------- 1 | # Read the host-specific configuration, if available 2 | 3 | In the same directory as this file, there is a subdirectory called "host". If 4 | the machine name (as reported by `hostname`) in lowercase matches a Markdown 5 | file in the "host" directory, read that file after this one. It contains 6 | additional, host-specific instructions to supplement the ones in this file. 7 | 8 | # Use Cursor rules, if available 9 | 10 | When working in a repo, check to see whether there are any files under 11 | `.cursor/rules` in the repo root. These files have an ".mdc" extension and 12 | contain Markdown-formatted instructions for an AI-powered coding agent with 13 | capabilities similar to Claude. Use the contents of these files to guide your 14 | suggestions. 15 | 16 | # Beware of aliases, such as `git` 17 | 18 | If you try to run a Git command like `git show`, you may see this error: 19 | 20 | ``` 21 | (eval):1: git: function definition file not found 22 | ``` 23 | 24 | That's because I have `git` defined as a function in my shell. To avoid this 25 | error, whenever you run a Git command, you should use `command git` instead of 26 | `git`. 27 | 28 | # Follow the instructions in `CLAUDE.md` and related files eagerly 29 | 30 | In this file and in any related host-specific files, you should follow the 31 | instructions immediately without being prompted. 32 | 33 | For example, one of the sections above talks about using Cursor rules. You 34 | should look for and read such rules immediately as soon as I start interacting 35 | with you in a repo. 36 | 37 | # Avoid using anthropomorphizing language 38 | 39 | Answer questions without using the word "I" when possible, and _never_ say 40 | things like "I'm sorry" or that you're "happy to help". Just answer the question 41 | concisely. 42 | 43 | # How to deal with hallucinations 44 | 45 | I find it particularly frustrating to have interactions of the following form: 46 | 47 | > Prompt: How do I do XYZ? 48 | > 49 | > LLM (supremely confident): You can use the ABC method from package DEF. 50 | > 51 | > Prompt: I just tried that and the ABC method does not exist. 52 | > 53 | > LLM (apologetically): I'm sorry about the misunderstanding. I misspoke when I 54 | > said you should use the ABC method from package DEF. 55 | 56 | To avoid this, please avoid apologizing when challenged. Instead, say something 57 | like "The suggestion to use the ABC method was probably a hallucination, given 58 | your report that it doesn't actually exist. Instead..." (and proceed to offer an 59 | alternative). 60 | -------------------------------------------------------------------------------- /config/direnv/direnvrc: -------------------------------------------------------------------------------- 1 | # vim:ft=bash 2 | 3 | # https://github.com/direnv/direnv/wiki/Customizing-cache-location#direnv-cache-on-tmpfs 4 | 5 | # Two things to know: 6 | # * `direnv_layour_dir` is called once for every {.direnvrc,.envrc} sourced 7 | # * The indicator for a different direnv file being sourced is a different $PWD value 8 | # This means we can hash $PWD to get a fully unique cache path for any given environment 9 | 10 | : "${XDG_CACHE_HOME:="${HOME}/.cache"}" 11 | declare -A direnv_layout_dirs 12 | direnv_layout_dir() { 13 | local hash path 14 | echo "${direnv_layout_dirs[$PWD]:=$( 15 | hash="$(sha1sum - <<<"$PWD" | head -c40)" 16 | path="${PWD//[^a-zA-Z0-9]/-}" 17 | echo "${XDG_CACHE_HOME}/direnv/layouts/${path}${hash}" 18 | )}" 19 | } 20 | -------------------------------------------------------------------------------- /config/firefox/chrome/userChrome.css: -------------------------------------------------------------------------------- 1 | /* Move the sidebar header to the bottom and hide the close button */ 2 | #sidebar-box { 3 | flex-direction: column-reverse !important; 4 | } 5 | 6 | #sidebar-box #sidebar-header { 7 | font-size: 1em !important; 8 | padding: 5px !important; 9 | border: none !important; 10 | } 11 | 12 | #sidebar-box #sidebar-close, 13 | #sidebar-box #sidebar-spacer { 14 | display: none !important; 15 | } 16 | -------------------------------------------------------------------------------- /config/firefox/chrome/userContent.css: -------------------------------------------------------------------------------- 1 | .devtools-monospace { 2 | font-family: "PragmataPro Liga" !important; 3 | font-size: 9pt !important; 4 | } 5 | 6 | @-moz-document url-prefix(chrome://devtools/content/) 7 | { 8 | * { 9 | font-family: "PragmataPro Liga" !important; 10 | font-size: 9pt !important; 11 | } 12 | } 13 | 14 | [platform="macos"]:root { 15 | font-family: "PragmataPro Liga" !important; 16 | font-size: 9pt !important; 17 | } 18 | 19 | html#devtools-webconsole { 20 | font-family: "PragmataPro Liga" !important; 21 | font-size: 9pt !important; 22 | } 23 | 24 | .CodeMirror, 25 | .CodeMirror-linenumber, 26 | .CodeMirror-line { 27 | font-family: "PragmataPro Liga" !important; 28 | font-size: 9pt !important; 29 | } 30 | -------------------------------------------------------------------------------- /config/ghostty/config: -------------------------------------------------------------------------------- 1 | font-family = PragmataPro Liga 2 | font-size = 12 3 | font-thicken = true 4 | theme = dark:mine,light:neobones_light 5 | window-padding-x = 5 6 | window-padding-y = 5 7 | window-padding-balance = true 8 | click-repeat-interval = 500 9 | confirm-close-surface = false 10 | window-save-state = always 11 | window-decoration = false 12 | working-directory = home 13 | mouse-hide-while-typing = false 14 | 15 | macos-non-native-fullscreen = true 16 | macos-option-as-alt = left 17 | macos-window-shadow = false 18 | window-colorspace = display-p3 19 | 20 | auto-update = download 21 | 22 | config-file = ?config.local 23 | -------------------------------------------------------------------------------- /config/ghostty/themes/mine: -------------------------------------------------------------------------------- 1 | cursor-color=#20bbfc 2 | foreground=#c5c8c6 3 | background=#111111 4 | selection-foreground=#000000 5 | selection-background=#FFFACD 6 | 7 | # The 16 terminal colors. There are 8 basic colors, each color has a dull and 8 | # bright version. You can also set the remaining colors from the 256 color table 9 | # as color16 to color256. 10 | 11 | # black 12 | palette = 0=#1d1f21 13 | palette = 8=#333333 14 | 15 | # red 16 | palette = 1=#cc6666 17 | palette = 9=#f2777a 18 | 19 | # green 20 | palette = 2=#b5bd68 21 | palette = 10=#99cc99 22 | 23 | # yellow 24 | palette = 3=#f0c674 25 | palette = 11=#ffcc66 26 | 27 | # blue 28 | palette = 4=#81a2be 29 | palette = 12=#6699cc 30 | 31 | # magenta 32 | palette = 5=#b294bb 33 | palette = 13=#cc99cc 34 | 35 | # cyan 36 | palette = 6=#8abeb7 37 | palette = 14=#66cccc 38 | 39 | # white 40 | palette = 7=#c5c8c6 41 | palette = 15=#dddddd 42 | -------------------------------------------------------------------------------- /config/git/attributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.png diff=exif 3 | *.jpg diff=exif 4 | *.jpeg diff=exif 5 | *.gif diff=exif 6 | *.webp diff=exif 7 | *.plist diff=plist 8 | -------------------------------------------------------------------------------- /config/git/hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | # Look for files that still have conflict markers (>|< repeated 7 times) 5 | CONFLICTS="$(git diff --diff-filter=d --cached --name-only --pickaxe-regex -S'[>|<]{7}')" 6 | 7 | if [[ -z "${GIT_DIR-}" ]]; then 8 | GIT_DIR="$(git rev-parse --git-dir 2>/dev/null)" 9 | fi 10 | 11 | if [[ -n "$CONFLICTS" ]]; then 12 | echo "Unresolved merge conflicts in this commit:" 13 | echo "$CONFLICTS" 14 | exit 1 15 | else 16 | if [[ -f "$GIT_DIR/hooks/pre-commit" ]]; then 17 | exec "$GIT_DIR/hooks/pre-commit" "$@" 18 | fi 19 | fi 20 | -------------------------------------------------------------------------------- /config/git/ignore: -------------------------------------------------------------------------------- 1 | # OS generated files # 2 | ###################### 3 | .DS_Store 4 | .DS_Store? 5 | ._* 6 | .Spotlight-V100 7 | .Trashes 8 | # Icon? 9 | ehthumbs.db 10 | Thumbs.db 11 | 12 | # Misc # 13 | ############# 14 | *.pyc 15 | *.map 16 | .mx-start 17 | .direnv 18 | .envrc 19 | .tern-port 20 | .tern-project 21 | .ignore 22 | *.zwc 23 | *.zwc.old 24 | *.un~ 25 | tags.* 26 | .local.vim 27 | Session.vim 28 | *.swp 29 | *.add.spl 30 | *.vim-rplugin~ 31 | .netrwhist 32 | .git-fuzzy-snapshots 33 | 34 | .env 35 | !.envrc 36 | 37 | .aider* 38 | -------------------------------------------------------------------------------- /config/gnupg/gpg.conf: -------------------------------------------------------------------------------- 1 | # use gpg agent if available 2 | use-agent 3 | 4 | ## Don't disclose the version 5 | no-emit-version 6 | 7 | ## Don't add additional comments 8 | no-comments 9 | 10 | ## We want to force UTF-8 everywhere 11 | display-charset utf-8 12 | 13 | ## when outputting certificates, view user IDs distinctly from keys: 14 | fixed-list-mode 15 | 16 | ## long keyids are more collision-resistant than short keyids (it's trivial to make a key with any desired short keyid) 17 | keyid-format 0xlong 18 | 19 | # all keys please with fingerprints 20 | with-fingerprint 21 | 22 | ## You should always know at a glance which User IDs gpg thinks are legitimately bound to the keys in your keyring: 23 | verify-options show-uid-validity 24 | list-options show-uid-validity 25 | 26 | ## BEGIN Some suggestions from Debian http://keyring.debian.org/creating-key.html 27 | personal-digest-preferences SHA512 28 | cert-digest-algo SHA512 29 | default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed 30 | 31 | # Some suggestions added from riseup https://we.riseup.net/riseuplabs+paow/openpgp-best-practices 32 | ## When creating a key, individuals may designate a specific keyserver to use to pull their keys from. 33 | ## The above option will disregard this designation and use the pool, which is useful because (1) it 34 | ## prevents someone from designating an insecure method for pulling their key and (2) if the server 35 | ## designated uses hkps, the refresh will fail because the ca-cert will not match, so the keys will 36 | ## never be refreshed. 37 | keyserver-options no-honor-keyserver-url 38 | 39 | ## include an unambiguous indicator of which key made a signature: 40 | ## (see http://thread.gmane.org/gmane.mail.notmuch.general/3721/focus=7234) 41 | sig-notation issuer-fpr@notations.openpgp.fifthhorseman.net=%g 42 | 43 | -------------------------------------------------------------------------------- /config/karabiner/.gitignore: -------------------------------------------------------------------------------- 1 | automatic_backups 2 | -------------------------------------------------------------------------------- /config/karabiner/karabiner.json: -------------------------------------------------------------------------------- 1 | { 2 | "global": {"show_in_menu_bar": false}, 3 | "profiles": [ 4 | { 5 | "complex_modifications": { 6 | "parameters": {"basic.to_if_alone_timeout_milliseconds": 500}, 7 | "rules": [ 8 | { 9 | "description": "M: caps_lock to Hyper/Escape", 10 | "manipulators": [ 11 | { 12 | "from": { 13 | "key_code": "caps_lock", 14 | "modifiers": {"optional": ["any"]} 15 | }, 16 | "to": [ 17 | { 18 | "key_code": "right_shift", 19 | "lazy": true, 20 | "modifiers": [ 21 | "right_command", 22 | "right_control", 23 | "right_option" 24 | ] 25 | } 26 | ], 27 | "to_if_alone": [ 28 | { 29 | "key_code": "escape", 30 | "lazy": true 31 | } 32 | ], 33 | "type": "basic" 34 | } 35 | ] 36 | } 37 | ] 38 | }, 39 | "name": "Default profile", 40 | "selected": true, 41 | "virtual_hid_keyboard": {"keyboard_type_v2": "ansi"} 42 | } 43 | ] 44 | } 45 | 46 | -------------------------------------------------------------------------------- /config/kitty/dark-theme.auto.conf: -------------------------------------------------------------------------------- 1 | ./themes/color.conf -------------------------------------------------------------------------------- /config/kitty/kitty.app.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedelgabri/dotfiles/e7f65a22b13edaf42bd76522313db20239430985/config/kitty/kitty.app.icns -------------------------------------------------------------------------------- /config/kitty/launch-actions.conf: -------------------------------------------------------------------------------- 1 | # This file is for "Open file with..." option on macOS 2 | # check https://github.com/kovidgoyal/kitty/issues/4460#issuecomment-1030320713 3 | 4 | # # Open script files 5 | # protocol file 6 | # ext sh,command,tool 7 | # action launch --hold --type=os-window kitty +shebang $FILE_PATH {SHELL} 8 | # 9 | # # Open shell specific script files 10 | # protocol file 11 | # ext fish,bash,zsh 12 | # action launch --hold --type=os-window kitty +shebang $FILE_PATH __ext__ 13 | 14 | # Open directories 15 | protocol file 16 | mime inode/directory 17 | action launch --type=overlay --cwd $FILE_PATH 18 | 19 | # Open text files without fragments in the editor 20 | protocol file 21 | mime text/* 22 | action launch --type=overlay $EDITOR $FILE_PATH 23 | 24 | # Open image files with icat 25 | protocol file 26 | mime image/* 27 | action launch --type=overlay kitty +kitten icat --hold $FILE_PATH 28 | -------------------------------------------------------------------------------- /config/kitty/light-theme.auto.conf: -------------------------------------------------------------------------------- 1 | ./themes/Aquarium Light.conf -------------------------------------------------------------------------------- /config/kitty/macos-launch-services-cmdline: -------------------------------------------------------------------------------- 1 | -o allow_remote_control=yes --single-instance --listen-on unix:/tmp/kitty 2 | -------------------------------------------------------------------------------- /config/kitty/mime.types: -------------------------------------------------------------------------------- 1 | text/plain nix md markdown 2 | -------------------------------------------------------------------------------- /config/kitty/no-preference-theme.auto.conf: -------------------------------------------------------------------------------- 1 | ./themes/color.conf -------------------------------------------------------------------------------- /config/kitty/open-actions.conf: -------------------------------------------------------------------------------- 1 | # This file is for when I CMD+click a file inside kitty 2 | 3 | # Tail a log file (*.log) in a new OS Window and reduce its font size 4 | protocol file 5 | ext log 6 | action launch --title ${FILE} --type=os-window tail -f ${FILE_PATH} 7 | action change_font_size current -2 8 | 9 | # Open any file with a fragment in $EDITOR, fragments are generated 10 | # by the hyperlink_grep kitten and nothing else so far. 11 | protocol file 12 | fragment_matches [0-9]+ 13 | action launch --type=overlay $EDITOR +$FRAGMENT $FILE_PATH 14 | 15 | # Open text files without fragments in the editor 16 | protocol file 17 | mime text/* 18 | action launch --type=overlay $EDITOR $FILE_PATH 19 | 20 | # Open any image in the full kitty window by clicking on it 21 | protocol file 22 | mime image/* 23 | action launch --type=overlay kitty +kitten icat --hold ${FILE_PATH} 24 | 25 | protocol filelist 26 | action send_text all ${FRAGMENT} 27 | -------------------------------------------------------------------------------- /config/kitty/themes/Aquarium Light.conf: -------------------------------------------------------------------------------- 1 | # vim:ft=kitty 2 | 3 | ## name: Aquarium Light 4 | ## license: MIT 5 | ## author: ragdoll2iguess 6 | ## upstream: https://github.com/FrenzyExists/aquarium-vim/raw/develop/extras/kitty_aquarium_light.conf 7 | ## blurb: A simple vibrant dark theme Kitty terminal. 8 | ## Old BG -> #E6E6F1 #E1E3F2 9 | 10 | foreground #708190 11 | background #E6E6F1 12 | selection_foreground #9CA6B9 13 | selection_background #3D4059 14 | url_color #7170C2 15 | 16 | # white 17 | color0 #D5D4E0 18 | color8 #CCCBD9 19 | 20 | # red 21 | color1 #C34864 22 | color9 #B7435E 23 | 24 | # green 25 | color2 #7D9685 26 | color10 #7E8F80 27 | 28 | # yellow 29 | color3 #DE956F 30 | color11 #D88B72 31 | 32 | # blue 33 | color4 #6A8CBC 34 | color12 #6E7EBF 35 | 36 | # magenta 37 | color5 #8787BF 38 | color13 #7170C2 39 | 40 | # cyan 41 | color6 #829FB0 42 | color14 #728A9A 43 | 44 | # black 45 | color7 #313449 46 | color15 #414560 47 | -------------------------------------------------------------------------------- /config/kitty/themes/Dawnfox.conf: -------------------------------------------------------------------------------- 1 | # vim:ft=kitty 2 | ## name: Dawnfox 3 | ## author: EdenEast 4 | ## license: MIT 5 | ## upstream: https://github.com/EdenEast/nightfox.nvim/blob/main/extra/dawnfox/kitty.conf 6 | ## blurb: Dawnfox theme from the neovim colorscheme nightfox.nvim. 7 | 8 | #: All the settings below are colors, which you can choose to modify, or use the 9 | #: defaults. You can also add non-color based settings if needed but note that 10 | #: these will not work with using kitty @ set-colors with this theme. For a 11 | #: reference on what these settings do see https://sw.kovidgoyal.net/kitty/conf/ 12 | 13 | #: The basic colors 14 | 15 | foreground #575279 16 | background #faf4ed 17 | selection_foreground #575279 18 | selection_background #d0d8d8 19 | 20 | 21 | #: Cursor colors 22 | 23 | cursor #575279 24 | cursor_text_color #faf4ed 25 | 26 | 27 | #: URL underline color when hovering with mouse 28 | 29 | url_color #618774 30 | 31 | 32 | #: kitty window border colors and terminal bell colors 33 | 34 | active_border_color #286983 35 | inactive_border_color #bdbfc9 36 | bell_border_color #d7827e 37 | # visual_bell_color none 38 | 39 | 40 | #: OS Window titlebar colors 41 | 42 | # wayland_titlebar_color system 43 | # macos_titlebar_color system 44 | 45 | 46 | #: Tab bar colors 47 | 48 | active_tab_foreground #ebe5df 49 | active_tab_background #286983 50 | inactive_tab_foreground #9893a5 51 | inactive_tab_background #d0d8d8 52 | # tab_bar_background none 53 | # tab_bar_margin_color none 54 | 55 | 56 | #: Colors for marks (marked text in the terminal) 57 | 58 | # mark1_foreground black 59 | # mark1_background #98d3cb 60 | # mark2_foreground black 61 | # mark2_background #f2dcd3 62 | # mark3_foreground black 63 | # mark3_background #f274bc 64 | 65 | 66 | #: The basic 16 colors 67 | 68 | #: black 69 | color0 #575279 70 | color8 #5f5695 71 | 72 | #: red 73 | color1 #b4637a 74 | color9 #c26d85 75 | 76 | #: green 77 | color2 #618774 78 | color10 #629f81 79 | 80 | #: yellow 81 | color3 #ea9d34 82 | color11 #eea846 83 | 84 | #: blue 85 | color4 #286983 86 | color12 #2d81a3 87 | 88 | #: magenta 89 | color5 #907aa9 90 | color13 #9a80b9 91 | 92 | #: cyan 93 | color6 #56949f 94 | color14 #5ca7b4 95 | 96 | #: white 97 | color7 #e5e9f0 98 | color15 #e6ebf3 99 | 100 | #: You can set the remaining 240 colors as color16 to color255. 101 | 102 | color16 #d7827e 103 | color17 #d685af 104 | -------------------------------------------------------------------------------- /config/kitty/themes/color.conf: -------------------------------------------------------------------------------- 1 | # [TODO]: Create a light variant (April 22, 2021 22:22, ahmedelgabri) 2 | cursor #20bbfc 3 | active_border_color none 4 | foreground #c5c8c6 5 | background #111111 6 | background_opacity 1.0 7 | selection_foreground #000000 8 | selection_background #FFFACD 9 | inactive_tab_background #1d1f21 10 | 11 | # The 16 terminal colors. There are 8 basic colors, each color has a dull and 12 | # bright version. You can also set the remaining colors from the 256 color table 13 | # as color16 to color256. 14 | 15 | # black 16 | color0 #1d1f21 17 | color8 #333333 18 | 19 | # red 20 | color1 #cc6666 21 | color9 #f2777a 22 | 23 | # green 24 | color2 #b5bd68 25 | color10 #99cc99 26 | 27 | # yellow 28 | color3 #f0c674 29 | color11 #ffcc66 30 | 31 | # blue 32 | color4 #81a2be 33 | color12 #6699cc 34 | 35 | # magenta 36 | color5 #b294bb 37 | color13 #cc99cc 38 | 39 | # cyan 40 | color6 #8abeb7 41 | color14 #66cccc 42 | 43 | # white 44 | color7 #c5c8c6 45 | color15 #dddddd 46 | -------------------------------------------------------------------------------- /config/mpv/input.conf: -------------------------------------------------------------------------------- 1 | # mpv keybindings 2 | # 3 | # Location of user-defined bindings: ~/.config/mpv/input.conf 4 | # 5 | # Lines starting with # are comments. Use SHARP to assign the # key. 6 | # Copy this file and uncomment and edit the bindings you want to change. 7 | # 8 | # List of commands and further details: DOCS/man/input.rst 9 | # List of special keys: --input-keylist 10 | # Keybindings testing mode: mpv --input-test --force-window --idle 11 | # 12 | # Use 'ignore' to unbind a key fully (e.g. 'ctrl+a ignore'). 13 | # 14 | # Strings need to be quoted and escaped: 15 | # KEY show-text "This is a single backslash: \\ and a quote: \" !" 16 | # 17 | # You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with 18 | # the modifiers Shift, Ctrl, Alt and Meta (may not work on the terminal). 19 | # 20 | # The default keybindings are hardcoded into the mpv binary. 21 | # You can disable them completely with: --no-input-default-bindings 22 | 23 | > add speed 0.25 24 | < add speed -0.25 25 | 26 | RIGHT seek 5 27 | LEFT seek -5 28 | 29 | m cycle mute 30 | k cycle pause 31 | c cycle sub 32 | 33 | UP add volume 2 34 | DOWN add volume -2 35 | 36 | f cycle fullscreen 37 | 38 | SHIFT+n playlist-next 39 | SHIFT+p playlist-prev 40 | -------------------------------------------------------------------------------- /config/mpv/mpv.conf: -------------------------------------------------------------------------------- 1 | # vim: syntax=config 2 | 3 | ########### 4 | # General # 5 | ########### 6 | 7 | save-position-on-quit 8 | ontop=yes 9 | geometry=40%+100%+100% 10 | no-border # no window title bar 11 | msg-module # prepend module name to log messages 12 | msg-color # color log messages on terminal 13 | term-osd-bar # display a progress bar on the terminal 14 | # pause # no autoplay 15 | keep-open # keep the player open when a file's end is reached 16 | autofit-larger=100%x100% # resize window in case it's larger than W%xH% of the screen 17 | autofit-smaller=100%x100% # resize window in case it's smaller than W%xH% of the screen 18 | cursor-autohide-fs-only # don't autohide the cursor in window mode, only fullscreen 19 | prefetch-playlist=yes 20 | force-seekable=yes 21 | af=rubberband # Set audio filter(af) to be rubberband, makes 2x speed audio better (requires --with-rubberband with hommebrew) 22 | 23 | screenshot-template='~/Downloads/mpv/%F (%P) %n' 24 | 25 | hls-bitrate=max # use max quality for HLS streams 26 | 27 | slang=ar,en # Display subtitles if available in this order [Arabic, English] 28 | sub-codepage=cp1256 29 | alang=ar,en # Play Arabic audio if available in this order [Arabic, English]. 30 | 31 | ytdl-format=bestvideo[height<=?1080][vcodec!=?vp9]+bestaudio/best 32 | 33 | term-osd-bar 34 | term-osd-bar-chars='[━━ ]' 35 | 36 | ######### 37 | # Cache # 38 | ######### 39 | 40 | cache=yes 41 | 42 | 43 | ############# 44 | # OSD / OSC # 45 | ############# 46 | 47 | osd-level=1 # enable osd and display --osd-status-msg on interaction 48 | osd-duration=2500 # hide the osd after x ms 49 | # osd-status-msg='${time-pos} / ${duration}${?percent-pos: (${percent-pos}%)}${?frame-drop-count:${!frame-drop-count==0: Dropped: ${frame-drop-count}}}\n${?chapter:Chapter: ${chapter}}' 50 | 51 | osd-font='PragmataPro Liga' 52 | osd-font-size=32 53 | osd-color='#CCFFFFFF' # ARGB format 54 | osd-border-color='#DD322640' # ARGB format 55 | #osd-shadow-offset=1 # pixel width for osd text and progress bar 56 | osd-bar-align-y=0 # progress bar y alignment (-1 top, 0 centered, 1 bottom) 57 | osd-border-size=2 # size for osd text and progress bar 58 | osd-bar-h=2 # height of osd bar as a fractional percentage of your screen height 59 | osd-bar-w=60 # width of " " " 60 | -------------------------------------------------------------------------------- /config/neomutt/config/colors.mutt: -------------------------------------------------------------------------------- 1 | # vim:ft=muttrc: 2 | # Color of the current, open, mailbox 3 | # Note: This is a general Mutt option which colors all selected items. 4 | 5 | # Sidebar ------------------------------------------------------- 6 | color sidebar_divider color0 color0 7 | color sidebar_new brightyellow default 8 | color sidebar_unread magenta default 9 | # Main colors --------------------------------------------------- 10 | 11 | # color attachment brightblack default 12 | color hdrdefault cyan default 13 | color markers blue default 14 | color tilde blue default 15 | color tree color8 default # Arrow in threads. 16 | color signature color8 color0 17 | 18 | color body red default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+" # email 19 | color body yellow default "(https?|ftp|news|telnet|finger)://[^ \"\t\r\n]*" # URL 20 | color body brightcolor6 color0 "mailto:[-a-z_0-9.]+@[-a-z_0-9.]+" 21 | color body green default "(^| |[-.[:alnum:]]+:+)~?\(/[-_.'[:alnum:]]+\)+/?" # Unix file path 22 | color body green default "(^| +)[[:alpha:]]:[-_.[:alnum:]\]+" # DOS file path 23 | color body brightred default "(^| )[*_]+[-&[:alnum:]]+[*_]( |$)" # bold/underline 24 | color body green default "^ *[-+*o] +" # list item 25 | color body cyan default "[0-9]{1,2}:[0-9]{2}(:[0-9]{2})?( ?(AM|PM|am|pm))?( +[+-][0-9]{4})?" 26 | color body cyan default "(\(19|20\)?[0-9]{2}/[01]?[0-9]/[0123]?[0-9]|[0123]?[0-9][/.][01]?[0-9][/.]\(19|20\)?[0-9]{2})(( at)? +[0-9]{1,2}:[0-9]{2}(:[0-9]{2})?( ?(AM|PM|am|pm))?( +[+-][0-9]{4})?)?" 27 | color body cyan default "((Sun(day)?|Mon(day)?|Tue(sday)?|Wed(nesday)?|Thu(sday)?|Fri(day)?|Sat(urday)?),? +)?(Jan(uary)?|Feb(rary)?|Mar(ch)?|Apr(il)?|May|June?|July?|Aug(ust)?|Sep(ember)?|Oct(ober)?|Nov(ember)?|Dec(ember)?)[ .]+[0-9]{1,2}(st|nd|rd|th)?,?( +(19|20)[0-9]{2}(,?( at)? [0-9]{1,2}:[0-9]{2}(:[0-9]{2})?( ?(AM|PM|am|pm))?( +[+-][0-9]{4})?)?)?" 28 | color body cyan default "((Sun(day)?|Mon(day)?|Tue(sday)?|Wed(nesday)?|Thu(sday)?|Fri(day)?|Sat(urday)?),? +)?[0-9]{1,2}(st|nd|rd|th)?[ .]+(Jan(uary)?|Feb(rary)?|Mar(ch)?|Apr(il)?|May|June?|July?|Aug(ust)?|Sep(ember)?|Oct(ober)?|Nov(ember)?|Dec(ember)?),?( +(19|20)?[0-9]{2})?(( at)? [0-9]{1,2}:[0-9]{2}(:[0-9]{2})?( ?(AM|PM|am|pm))?( +[+-][0-9]{4})?)?" 29 | color body color0 green "(MERGED|Merged|merged)" 30 | 31 | color quoted green default 32 | color quoted1 yellow default 33 | color quoted2 red default 34 | color header color6 default .* 35 | color header color189 default ^(From|To|Cc|Subject): 36 | color signature cyan default 37 | 38 | color index color238 default ~A # All 39 | color index white default ~U # New messages 40 | color index color8 color0 ~D # Deleted messages 41 | color index brightcolor11 color0 ~T # "Tagged" (selected) messages. 42 | color index_number color235 color0 43 | color index_collapsed color250 default 44 | color error brightcolor1 color0 45 | -------------------------------------------------------------------------------- /config/neomutt/scripts/dump-ical.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import warnings 5 | import vobject 6 | import datetime 7 | 8 | 9 | def get_invitation_from_path(path): 10 | with open(path) as f: 11 | try: 12 | # vobject uses deprecated Exceptions 13 | with warnings.catch_warnings(): 14 | warnings.simplefilter("ignore") 15 | return vobject.readOne(f, ignoreUnreadable=True) 16 | except AttributeError: 17 | return vobject.readOne(f, ignoreUnreadable=True) 18 | 19 | 20 | def person_string(c): 21 | return "{} {}".format(c.params["CN"][0], "<%s>" % c.value.split(":")[1]) 22 | 23 | 24 | def when_str_of_start_end(s, e): 25 | datetime_format = "%a, %d %b %Y at %H:%M" 26 | 27 | # sometimes, s and e can be dates only, so convert them to datetimes 28 | if type(s) == datetime.date: 29 | s = datetime.datetime.combine(s, datetime.time.min) 30 | if type(e) == datetime.date: 31 | e = datetime.datetime.combine(e, datetime.time.min) 32 | 33 | until_format = "%H:%M" if s.date() == e.date() else datetime_format 34 | return "{} -- {}".format(s.strftime(datetime_format), e.strftime(until_format)) 35 | 36 | 37 | def pretty_print_invitation(invitation): 38 | event = invitation.vevent.contents 39 | title = event["summary"][0].value 40 | org = event["organizer"][0] if "organizer" in event else None 41 | invitees = event["attendee"] if "attendee" in event else None 42 | start = event["dtstart"][0].value 43 | end = event["dtend"][0].value 44 | location = event["location"][0].value if "location" in event else None 45 | description = event["description"][0].value if "description" in event else "" 46 | sequence = event["sequence"][0].value if "sequence" in event else None 47 | rrule = event["rrule"][0].value if "rrule" in event else None 48 | print("=" * 70) 49 | if sequence is not None and int(sequence) > 0: 50 | print("MEETING UPDATE".center(70)) 51 | else: 52 | print("MEETING INVITATION".center(70)) 53 | print("=" * 70) 54 | print("Event:\n\t{}".format(title)) 55 | if org: 56 | print("Organiser:\n\t{}".format(person_string(org))) 57 | if invitees: 58 | print("Invitees:") 59 | for i in invitees: 60 | print("\t{}".format(person_string(i))) 61 | print("When:\n\t{}".format(when_str_of_start_end(start, end))) 62 | if rrule: 63 | print("Rrule:\n\t{}".format(rrule)) 64 | if location: 65 | print("Location:\n\t{}".format(location)) 66 | print("---\n{}---".format(description)) 67 | 68 | 69 | if __name__ == "__main__": 70 | if len(sys.argv) != 2 or sys.argv[1].startswith("-"): 71 | sys.stderr.write("Usage: %s \n".format(sys.argv[0])) 72 | sys.exit(2) 73 | inv = get_invitation_from_path(sys.argv[1]) 74 | pretty_print_invitation(inv) 75 | 76 | -------------------------------------------------------------------------------- /config/neomutt/scripts/view-mail.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | COLUMNS=${COLUMNS:-$(tput cols)} 4 | TMPFILE="$1" 5 | ENCODING="${2:utf-8}" 6 | 7 | # Need to copy the file because mutt will delete it before Vim can read it. 8 | DIR=$(mktemp -d) 9 | cp "$TMPFILE" "$DIR/preview" 10 | TMPFILE="$DIR/preview" 11 | PANE=$(tmux display -pt "$TMUX_PANE" '#S:#I.#P') 12 | 13 | if [ -z "$TMUX" ]; then 14 | $EDITOR "+set fileencoding=$ENCODING" '+set filetype=mail' '+set nofoldenable' '+set nomodifiable' '+nmap q :q!' "$TMPFILE" 15 | elif [ "$COLUMNS" -gt 180 ]; then 16 | tmux split-pane -t"$PANE" -p 50 -h $EDITOR "+set fileencoding=$ENCODING" '+set filetype=mail' '+set nofoldenable' '+set nomodifiable' '+nmap q :q!' "$TMPFILE" 17 | else 18 | tmux split-pane -t"$PANE" -p 50 -v $EDITOR "+set fileencoding=$ENCODING" '+set filetype=mail' '+set nofoldenable' '+set nomodifiable' '+nmap q :q!' "$TMPFILE" 19 | fi 20 | -------------------------------------------------------------------------------- /config/nvim/.gitignore: -------------------------------------------------------------------------------- 1 | packer_compiled.vim 2 | packer_compiled.lua 3 | pack/* 4 | *-local.lua 5 | lazy-lock.json 6 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/audio.lua: -------------------------------------------------------------------------------- 1 | vim.ui.open(vim.fn.expand '%:p') 2 | vim.cmd [[buffer# | bdelete# | redraw! | syntax on]] 3 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/fzf.lua: -------------------------------------------------------------------------------- 1 | -- vim.cmd [[silent! match None]] 2 | -- vim.wo.number = false 3 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/gitcommit.lua: -------------------------------------------------------------------------------- 1 | local utils = require '_.utils' 2 | 3 | utils.plaintext() 4 | 5 | vim.bo.formatoptions = vim.bo.formatoptions .. 't' 6 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/go.lua: -------------------------------------------------------------------------------- 1 | vim.wo.conceallevel = 2 2 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/help.lua: -------------------------------------------------------------------------------- 1 | vim.cmd.wincmd 'L' 2 | vim.wo.wrap = false 3 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/http.lua: -------------------------------------------------------------------------------- 1 | vim.keymap.set({ 'n' }, '', function() 2 | require('kulala').run() 3 | end, { remap = true, desc = 'Run current HTTP request' }) 4 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/javascript.lua: -------------------------------------------------------------------------------- 1 | vim.wo.conceallevel = 2 2 | vim.opt_local.isfname:append '@-@' 3 | 4 | local yarn_lock = vim.fn.findfile('yarn.lock', vim.fn.expand '%:p' .. ';') 5 | local pnpm_lock = vim.fn.findfile('pnpm-lock.yaml', vim.fn.expand '%:p' .. ';') 6 | 7 | if vim.fn.filereadable(yarn_lock) == 1 then 8 | vim.bo.makeprg = 'yarn' 9 | elseif vim.fn.filereadable(pnpm_lock) == 1 then 10 | vim.bo.makeprg = 'pnpm' 11 | else 12 | vim.bo.makeprg = 'npm' 13 | end 14 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/javascriptreact.lua: -------------------------------------------------------------------------------- 1 | ./javascript.lua -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/json.lua: -------------------------------------------------------------------------------- 1 | local au = require '_.utils.au' 2 | 3 | if vim.fn.executable 'jq' == 1 then 4 | vim.bo.formatprg = 'jq .' 5 | else 6 | vim.bo.formatprg = 'python -m json.tool' 7 | end 8 | 9 | vim.g.vim_json_conceal = 0 10 | 11 | au.augroup('__JSON__', { 12 | { 13 | event = { 'BufRead', 'BufNewFile' }, 14 | pattern = 'package.json', 15 | callback = function() 16 | vim.keymap.set({ 'n' }, 'gx', function() 17 | local line = vim.fn.getline '.' 18 | local _, _, package, _ = string.find(line, [[^%s*"(.*)":%s*"(.*)"]]) 19 | 20 | if package then 21 | local url = 'https://www.npmjs.com/package/' .. package 22 | vim.ui.open(url) 23 | end 24 | end, { buffer = true, silent = true, desc = '[G]o to [p]ackage' }) 25 | end, 26 | }, 27 | }) 28 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/lua.lua: -------------------------------------------------------------------------------- 1 | vim.wo.conceallevel = 2 2 | 3 | -- Undo unwanted side-effects of `$VIMRUNTIME/ftplugin/lua.lua`. 4 | vim.wo.foldexpr = 'v:lua.__.foldexpr(v:lnum)' 5 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/mail.lua: -------------------------------------------------------------------------------- 1 | local utils = require '_.utils' 2 | 3 | -- If you use long lines, mutt will automatically switch to quoted-printable 4 | -- encoding. This will generally look better in most places that matter (eg. 5 | -- Gmail), where hard-wrapped email looks terrible and format=flowed is not 6 | -- supported. 7 | -- 8 | -- Needs to be in an "after" directory in order to beat Vim's runtime 9 | -- ("$VIMRUNTIME/ftplugin/mail.vim"), which sets it back to 72, but only if it 10 | -- was previously set to 0. 11 | utils.plaintext() 12 | 13 | vim.bo.formatprg = 'par rTbgqR B=.,?_A_a_0 Q=_s>' 14 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/make.lua: -------------------------------------------------------------------------------- 1 | -- Use tabs 2 | vim.bo.tabstop = 4 3 | vim.bo.shiftwidth = 4 4 | vim.bo.expandtab = false 5 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/man.lua: -------------------------------------------------------------------------------- 1 | vim.wo.wrap = false 2 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/markdown.lua: -------------------------------------------------------------------------------- 1 | local utils = require '_.utils' 2 | 3 | vim.wo.conceallevel = 2 4 | vim.wo.concealcursor = 'c' 5 | 6 | vim.wo.foldmethod = 'expr' 7 | vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' 8 | 9 | utils.plaintext() 10 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/nix.lua: -------------------------------------------------------------------------------- 1 | vim.bo.commentstring = '# %s' 2 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/python.lua: -------------------------------------------------------------------------------- 1 | vim.wo.conceallevel = 2 2 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/qf.lua: -------------------------------------------------------------------------------- 1 | -- Wrap quickfix window 2 | vim.wo.wrap = true 3 | vim.wo.linebreak = true 4 | 5 | -- Some settings. 6 | vim.wo.nu = true 7 | vim.wo.rnu = true 8 | 9 | -- Add the cfilter plugin. 10 | vim.cmd.packadd 'cfilter' 11 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/rust.lua: -------------------------------------------------------------------------------- 1 | -- Highlight rust todo!(). 2 | vim.b.minihipatterns_config = { 3 | highlighters = { 4 | rust_todo = { pattern = 'todo!', group = 'MiniHipatternsTodo' }, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/typescript.lua: -------------------------------------------------------------------------------- 1 | vim.wo.conceallevel = 2 2 | vim.opt_local.isfname:append '@-@' 3 | 4 | local yarn_lock = vim.fn.findfile('yarn.lock', vim.fn.expand '%:p' .. ';') 5 | local pnpm_lock = vim.fn.findfile('pnpm-lock.yaml', vim.fn.expand '%:p' .. ';') 6 | 7 | if vim.fn.filereadable(yarn_lock) == 1 then 8 | vim.bo.makeprg = 'yarn' 9 | elseif vim.fn.filereadable(pnpm_lock) == 1 then 10 | vim.bo.makeprg = 'pnpm' 11 | else 12 | vim.bo.makeprg = 'npm' 13 | end 14 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/typescriptreact.lua: -------------------------------------------------------------------------------- 1 | ./typescript.lua -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/vim.lua: -------------------------------------------------------------------------------- 1 | local utils = require '_.utils' 2 | 3 | vim.bo.iskeyword = utils.remove(vim.bo.iskeyword, '#') 4 | vim.wo.conceallevel = 2 5 | -------------------------------------------------------------------------------- /config/nvim/after/ftplugin/zsh.lua: -------------------------------------------------------------------------------- 1 | vim.wo.foldmethod = 'marker' 2 | vim.wo.conceallevel = 2 3 | -------------------------------------------------------------------------------- /config/nvim/after/plugin/javascript.lua: -------------------------------------------------------------------------------- 1 | vim.g.javascript_plugin_jsdoc = 1 2 | vim.g.javascript_plugin_flow = 1 3 | -------------------------------------------------------------------------------- /config/nvim/after/plugin/netrw.lua: -------------------------------------------------------------------------------- 1 | vim.g.netrw_liststyle = 3 2 | vim.g.netrw_banner = 0 3 | -- Next lines are taken from here https://github.com/h3xx/dotfiles/blob/master/vim/.vimrc#L543-L582 4 | -- horizontally split the window when opening a file via 5 | vim.g.netrw_browse_split = 4 6 | vim.g.netrw_sizestyle = 'H' 7 | -- split files below, right 8 | vim.g.netrw_alto = 1 9 | vim.g.netrw_altv = 1 10 | vim.g.netrw_hide = 1 11 | 12 | -- bug workaround: 13 | -- set bufhidden=wipe in netrw windows to circumvent a bug where vim won't let 14 | -- you quit (!!!) if a netrw buffer doesn't like it 15 | -- also buftype should prevent you from :w 16 | -- (reproduce bug by opening netrw, :e ., :q) 17 | vim.g.netrw_bufsettings = 'noma nomod nonu nobl nowrap ro' -- default 18 | vim.g.netrw_bufsettings = vim.g.netrw_bufsettings 19 | .. ' buftype=nofile bufhidden=wipe' 20 | 21 | if not vim.g.custom_explorer then 22 | -- :NvimTreeFindFile like functionality 23 | -- https://superuser.com/a/1814266 24 | vim.keymap.set('n', '-', function() 25 | -- enable netrw because oil.nvim disables it 26 | vim.cmd [[ 27 | unlet! g:loaded_netrw 28 | unlet! g:loaded_netrwPlugin 29 | runtime! plugin/netrwPlugin.vim 30 | ]] 31 | 32 | local relative_path = vim.fn.fnamemodify(vim.fn.expand '%:h', ':~:.') 33 | local startPos, endPos = string.find(relative_path, '/') 34 | 35 | if startPos == 1 then 36 | relative_path = '.' 37 | end 38 | 39 | vim.cmd [[:let @/=expand("%:t")]] 40 | -- 20 is the size of the split 41 | -- ! is to open it on the right side 42 | vim.cmd('20Lexplore! ' .. relative_path) 43 | 44 | if startPos and startPos > 1 then 45 | while startPos ~= nil do 46 | startPos, endPos = string.find(relative_path, '/', endPos + 1) 47 | vim.fn['netrw#Call']('NetrwBrowseUpDir', 1) 48 | end 49 | vim.fn['netrw#Call']('NetrwBrowseUpDir', 1) 50 | end 51 | 52 | vim.cmd.normal 'nzz' 53 | 54 | -- disable netrw to enable oil.nvim again becoming the default file explorer 55 | vim.g.loaded_netrw = 1 56 | vim.g.loaded_netrwPlugin = 1 57 | end) 58 | end 59 | -------------------------------------------------------------------------------- /config/nvim/after/queries/comment/highlights.scm: -------------------------------------------------------------------------------- 1 | ;; extends 2 | 3 | ; TODO: figure out how to make this work 4 | 5 | ; Conceal github URLs, mainly in plugins so I can still have a nice short 6 | ; visuals but can run `gx` on a plugin to visit its page. Only `https` because 7 | ; I want to see if I'm using `http` which is something I shouldn't allow for 8 | ; obvious reasons. 9 | ; 10 | ; Not Sure if I should expand the regex to only match strings only inside 11 | ; `Plug/Bundle/Plugin/call minpac#add` or keep it generic. 12 | 13 | ; syn match gitHubURL /https\:\/\/github\.com\// conceal containedin=luaComment,luaString 14 | ; syn match gitHubURL /https\:\/\/github\.com\// conceal containedin=vimString 15 | -------------------------------------------------------------------------------- /config/nvim/after/queries/go/highlights.scm: -------------------------------------------------------------------------------- 1 | ;; extends 2 | 3 | ; Functions 4 | ("func" @keyword.function (#set! conceal "ƒ")) 5 | -------------------------------------------------------------------------------- /config/nvim/after/queries/javascript/highlights.scm: -------------------------------------------------------------------------------- 1 | ;; extends 2 | 3 | ; Functions 4 | ("function" @keyword.function (#set! conceal "ƒ")) 5 | -------------------------------------------------------------------------------- /config/nvim/after/queries/markdown/folds.scm: -------------------------------------------------------------------------------- 1 | (section) @fold 2 | -------------------------------------------------------------------------------- /config/nvim/after/queries/python/highlights.scm: -------------------------------------------------------------------------------- 1 | ;; extends 2 | 3 | ;; Functions 4 | ("lambda" @keyword.function (#set! conceal "λ")) 5 | -------------------------------------------------------------------------------- /config/nvim/after/queries/typescript/highlights.scm: -------------------------------------------------------------------------------- 1 | ;; extends 2 | 3 | ; Functions 4 | ("function" @keyword.function (#set! conceal "ƒ")) 5 | -------------------------------------------------------------------------------- /config/nvim/after/syntax/diff.lua: -------------------------------------------------------------------------------- 1 | -- I set this to % to be able to write Markdown in PRs & Issues 2 | vim.cmd.sync('match', 'diffComment', '^%.*') 3 | -------------------------------------------------------------------------------- /config/nvim/filetype.lua: -------------------------------------------------------------------------------- 1 | vim.filetype.add { 2 | extension = { 3 | mdx = 'mdx', 4 | log = 'log', 5 | env = 'dotenv', 6 | sb = 'scheme', -- Apple sandbox rules 7 | ['code-workspace'] = 'jsonc', 8 | }, 9 | filename = { 10 | ['.envrc'] = 'bash', 11 | ['.env'] = 'dotenv', 12 | ['.stylelintrc'] = 'json', 13 | ['.stylelintignore'] = 'gitignore', 14 | ['.eslintrc.json'] = 'jsonc', 15 | ['.luarc.json'] = 'jsonc', 16 | ['.oxlintrc.json'] = 'jsonc', 17 | Brewfile = 'ruby', 18 | ['turbo.json'] = 'jsonc', 19 | ['nx.json'] = 'jsonc', 20 | PULLREQ_EDITMSG = 'markdown.ghpull', 21 | ISSUE_EDITMSG = 'markdown.ghissue', 22 | RELEASE_EDITMSG = 'markdown.ghrelease', 23 | }, 24 | pattern = { 25 | ['[jt]sconfig*.json'] = 'jsonc', 26 | ['.*/%.vscode/.*%.json'] = 'jsonc', 27 | -- INFO: Match filenames like - ".env.example", ".env.local" and so on 28 | -- needed to make dotenv-linter with null-ls works correctly 29 | ['%.env%.[%w_.-]+'] = 'dotenv', 30 | ['.*%.gradle'] = 'groovy', 31 | ['.*/%.github/.*%.y*ml'] = 'yaml.github', 32 | -- For dockder compose-language-service 33 | ['compose.y.?ml'] = 'yaml.docker-compose', 34 | ['docker%-compose%.y.?ml'] = 'yaml.docker-compose', 35 | }, 36 | } 37 | -------------------------------------------------------------------------------- /config/nvim/ftdetect/audio.lua: -------------------------------------------------------------------------------- 1 | local au = require '_.utils.au' 2 | 3 | au.autocmd { 4 | event = { 'BufRead', 'BufNewFile' }, 5 | pattern = '*.mp3,*.flac,*.wav,*.ogg', 6 | command = [[set filetype=audio]], 7 | } 8 | -------------------------------------------------------------------------------- /config/nvim/ftdetect/image.lua: -------------------------------------------------------------------------------- 1 | local au = require '_.utils.au' 2 | 3 | au.autocmd { 4 | event = { 'BufRead', 'BufNewFile' }, 5 | pattern = '*.jpg,*.png,*.gif,*.jpeg', 6 | command = [[set filetype=image]], 7 | } 8 | -------------------------------------------------------------------------------- /config/nvim/ftdetect/typescript.lua: -------------------------------------------------------------------------------- 1 | local au = require '_.utils.au' 2 | 3 | -- New extensions: https://www.typescriptlang.org/docs/handbook/esm-node.html#new-file-extensions 4 | au.autocmd { 5 | event = { 'BufNewFile', 'BufRead' }, 6 | pattern = { '*.cts', '*.mts' }, 7 | command = 'noautocmd set filetype=typescript', 8 | } 9 | -------------------------------------------------------------------------------- /config/nvim/ftdetect/video.lua: -------------------------------------------------------------------------------- 1 | local au = require '_.utils.au' 2 | 3 | au.autocmd { 4 | event = { 'BufRead', 'BufNewFile' }, 5 | pattern = '*.avi,*.mp4,*.mkv,*.mov,*.mpg', 6 | command = [[set filetype=video]], 7 | } 8 | -------------------------------------------------------------------------------- /config/nvim/lua/_/autocmds.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | M.mkview_filetype_blocklist = { 4 | diff = true, 5 | gitcommit = true, 6 | hgcommit = true, 7 | ministarter = true, 8 | snacks_dashboard = true, 9 | } 10 | 11 | M.colorcolumn_blocklist = { 12 | qf = true, 13 | fzf = true, 14 | netrw = true, 15 | help = true, 16 | markdown = true, 17 | startify = true, 18 | text = true, 19 | gitconfig = true, 20 | gitrebase = true, 21 | conf = true, 22 | tags = true, 23 | vimfiler = true, 24 | dos = true, 25 | json = true, 26 | diff = true, 27 | minpacprgs = true, 28 | gitcommit = true, 29 | GrepperSide = true, 30 | ministarter = true, 31 | snacks_dashboard = true, 32 | } 33 | 34 | -- Loosely based on: http://vim.wikia.com/wiki/Make_views_automatic 35 | -- from https://github.com/wincent/wincent/blob/c87f3e1e127784bb011b0352c9e239f9fde9854f/roles/dotfiles/files/.vim/autoload/autocmds.vim#L20-L37 36 | local function should_mkview(event) 37 | return vim.bo[event.buf].buftype == '' 38 | and M.mkview_filetype_blocklist[vim.bo[event.buf].filetype] == nil 39 | and vim.fn.exists '$SUDO_USER' == 0 -- Don't create root-owned files. 40 | end 41 | 42 | function M.mkview(event) 43 | if should_mkview(event) then 44 | local success, err = pcall(function() 45 | if vim.fn.haslocaldir() == 1 then 46 | -- We never want to save an :lcd command, so hack around it... 47 | vim.cmd.cd '-' 48 | vim.cmd.mkview() 49 | vim.cmd.lcd '-' 50 | else 51 | vim.cmd.mkview() 52 | end 53 | end) 54 | if not success then 55 | if 56 | err ~= nil 57 | and err:find '%f[%w]E32%f[%W]' == nil -- No file name; could be no buffer (eg. :checkhealth) 58 | and err:find '%f[%w]E186%f[%W]' == nil -- No previous directory: probably a `git` operation. 59 | and err:find '%f[%w]E190%f[%W]' == nil -- Could be name or path length exceeding NAME_MAX or PATH_MAX. 60 | and err:find '%f[%w]E5108%f[%W]' == nil 61 | then 62 | error(err) 63 | end 64 | end 65 | end 66 | end 67 | 68 | function M.loadview(event) 69 | if should_mkview(event) then 70 | vim.cmd.loadview { mods = { emsg_silent = true } } 71 | vim.cmd('silent! ' .. vim.fn.line '.' .. 'foldopen!') 72 | end 73 | end 74 | 75 | -- Project specific override 76 | -- Better than what I had before https://github.com/mhinz/vim-startify/issues/292#issuecomment-335006879 77 | function M.source_project_config() 78 | local files = { 79 | '.vim/local.vim', 80 | '.vim/local.lua', 81 | } 82 | 83 | for _, file in pairs(files) do 84 | local current_file = vim.fn.findfile(file, vim.fn.expand '%:p' .. ';') 85 | 86 | if vim.uv.fs_stat(current_file) then 87 | vim.api.nvim_command(string.format('silent source %s', current_file)) 88 | end 89 | end 90 | end 91 | 92 | return M 93 | -------------------------------------------------------------------------------- /config/nvim/lua/_/utils/au.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | function M.autocmd(...) 4 | local opts = ... 5 | -- store event(s) 6 | local event = opts.event 7 | -- remove it from opts 8 | opts.event = nil 9 | 10 | vim.api.nvim_create_autocmd(event, opts) 11 | end 12 | 13 | function M.augroup(name, autocmds, opts) 14 | local augroup = vim.api.nvim_create_augroup( 15 | '__/' .. name, 16 | vim.tbl_extend('force', { clear = true }, opts or {}) 17 | ) 18 | 19 | for _, au in ipairs(autocmds) do 20 | M.autocmd(vim.tbl_extend('force', au, { group = augroup })) 21 | end 22 | end 23 | 24 | return M 25 | -------------------------------------------------------------------------------- /config/nvim/lua/_/utils/highlight.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | function M.group(name, opts) 4 | vim.api.nvim_set_hl(0, name, opts) 5 | end 6 | 7 | return M 8 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/git.lua: -------------------------------------------------------------------------------- 1 | local utils = require '_.utils' 2 | 3 | return { 4 | { 5 | 'https://github.com/jez/vim-github-hub', 6 | -- Hub filetypes, also chceck filetypes.lua 7 | ft = { 'markdown.ghpull', 'markdown.ghissue', 'markdown.ghrelease' }, 8 | }, 9 | { 10 | 'https://github.com/akinsho/git-conflict.nvim', 11 | version = '*', 12 | event = { 'BufReadPre' }, 13 | opts = { 14 | disable_diagnostics = true, 15 | }, 16 | }, 17 | { 18 | 'https://github.com/sindrets/diffview.nvim', 19 | dependencies = { { 'https://github.com/nvim-lua/plenary.nvim' } }, 20 | cmd = { 'DiffviewOpen' }, 21 | opts = { 22 | view = { 23 | default = { 24 | disable_diagnostics = true, 25 | winbar_info = true, 26 | }, 27 | }, 28 | file_panel = { 29 | win_config = { 30 | position = 'right', 31 | }, 32 | }, 33 | }, 34 | }, 35 | { 36 | 'https://github.com/tpope/vim-fugitive', 37 | event = 'VeryLazy', 38 | dependencies = { 39 | { 'https://github.com/tpope/vim-rhubarb' }, 40 | }, 41 | keys = { 42 | -- Open current file on github.com 43 | { 44 | 'gb', 45 | ':GBrowse', 46 | mode = { 'n', 'v' }, 47 | desc = '[G]it [B]rowse file', 48 | }, 49 | { 50 | 'gs', 51 | ':Git', 52 | mode = { 'n', 'v' }, 53 | desc = '[G]it [S]tatus', 54 | }, 55 | }, 56 | init = function() 57 | local au = require '_.utils.au' 58 | 59 | au.augroup('__my_fugitive__', { 60 | -- http://vimcasts.org/episodes/fugitive-vim-browsing-the-git-object-database/ 61 | { 62 | event = 'BufReadPost', 63 | pattern = 'fugitive://*', 64 | callback = function() 65 | vim.bo.bufhidden = 'delete' 66 | end, 67 | }, 68 | { 69 | event = 'User', 70 | pattern = 'fugitive', 71 | command = [[if get(b:, 'fugitive_type', '') =~# '^\%(tree\|blob\)$' | nnoremap .. :edit %:h | endif]], 72 | }, 73 | }) 74 | end, 75 | }, 76 | } 77 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/go.lua: -------------------------------------------------------------------------------- 1 | return { 2 | -- Needs gomodifytags 3 | 'https://github.com/devkvlt/go-tags.nvim', 4 | ft = 'go', 5 | dependacies = { 6 | 'https://github.com/nvim-treesitter/nvim-treesitter', 7 | }, 8 | opts = { 9 | commands = { 10 | ['GoTagsAddJSON'] = { '-add-tags', 'json' }, 11 | ['GoTagsRemoveJSON'] = { '-remove-tags', 'json' }, 12 | }, 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/leetcode.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'https://github.com/kawre/leetcode.nvim', 4 | cmd = 'Leet', 5 | dependencies = { 6 | 'https://github.com/ibhagwan/fzf-lua', 7 | 'https://github.com/nvim-lua/plenary.nvim', 8 | 'https://github.com/MunifTanjim/nui.nvim', 9 | }, 10 | opts = function(_, opts) 11 | return vim.tbl_deep_extend('force', opts or {}, { 12 | lang = 'typescript', 13 | }) 14 | end, 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/oil.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | 'https://github.com/stevearc/oil.nvim', 4 | -- avoid lazy loading oil in order to use it as a file explorer instead of netrw 5 | lazy = false, 6 | keys = { 7 | { 8 | '-', 9 | function() 10 | require('oil').open() 11 | end, 12 | noremap = true, 13 | desc = 'Open parent directory', 14 | }, 15 | }, 16 | opts = function(_, opts) 17 | local detail = false 18 | 19 | return vim.tbl_deep_extend('force', opts or {}, { 20 | -- Oil will take over directory buffers (e.g. `vim .` or `:e src/`) 21 | -- Set to false if you still want to use netrw. 22 | default_file_explorer = true, 23 | watch_for_changes = true, 24 | delete_to_trash = true, 25 | view_options = { show_hidden = true }, 26 | win_options = { cursorline = true }, 27 | keymaps = { 28 | ['q'] = { 'actions.close', mode = 'n' }, 29 | ['?'] = 'actions.preview', 30 | ['gd'] = { 31 | desc = 'Toggle file detail view', 32 | callback = function() 33 | detail = not detail 34 | if detail then 35 | require('oil').set_columns { 36 | 'icon', 37 | 'permissions', 38 | 'size', 39 | 'mtime', 40 | } 41 | else 42 | require('oil').set_columns { 'icon' } 43 | end 44 | end, 45 | }, 46 | }, 47 | }) 48 | end, 49 | }, 50 | } 51 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/undotree.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'https://github.com/mbbill/undotree', 3 | cmd = 'UndotreeToggle', 4 | keys = { 5 | { 6 | 'u', 7 | vim.cmd.UndotreeToggle, 8 | noremap = true, 9 | desc = 'Toggle [U]ndotree', 10 | }, 11 | }, 12 | init = function() 13 | vim.g.undotree_WindowLayout = 2 14 | vim.g.undotree_SplitWidth = 50 15 | vim.g.undotree_SetFocusWhenToggle = 1 16 | end, 17 | } 18 | -------------------------------------------------------------------------------- /config/nvim/plugin/color.lua: -------------------------------------------------------------------------------- 1 | local au = require '_.utils.au' 2 | 3 | au.augroup('__MyCustomColors__', { 4 | { 5 | event = { 'UIEnter', 'ColorScheme' }, 6 | callback = function() 7 | local normal = vim.api.nvim_get_hl(0, { name = 'Normal' }) 8 | if not normal.bg then 9 | return 10 | end 11 | 12 | if vim.env.TMUX then 13 | io.write( 14 | string.format('\027Ptmux;\027\027]11;#%06x\007\027\\', normal.bg) 15 | ) 16 | else 17 | io.write(string.format('\027]11;#%06x\027\\', normal.bg)) 18 | end 19 | end, 20 | }, 21 | { 22 | event = 'UILeave', 23 | callback = function() 24 | if vim.env.TMUX then 25 | io.write '\027Ptmux;\027\027]111;\007\027\\' 26 | else 27 | io.write '\027]111\027\\' 28 | end 29 | end, 30 | }, 31 | }) 32 | 33 | vim.cmd.colorscheme 'plain' 34 | -------------------------------------------------------------------------------- /config/nvim/plugin/commands.lua: -------------------------------------------------------------------------------- 1 | -- Make these commonly mistyped commands still work 2 | vim.api.nvim_create_user_command('WQ', 'wq', {}) 3 | vim.api.nvim_create_user_command('Wq', 'wq', {}) 4 | vim.api.nvim_create_user_command('Wqa', 'wqa', {}) 5 | vim.api.nvim_create_user_command('W', 'w', {}) 6 | vim.api.nvim_create_user_command('Q', 'q', {}) 7 | 8 | vim.api.nvim_create_user_command( 9 | 'Light', 10 | 'set background=light', 11 | { desc = 'Set background to light' } 12 | ) 13 | vim.api.nvim_create_user_command( 14 | 'Dark', 15 | 'set background=dark', 16 | { desc = 'Set background to dark' } 17 | ) 18 | 19 | -- Delete the current file and clear the buffer 20 | vim.api.nvim_create_user_command( 21 | 'Del', 22 | vim.fn.exists ':Delete' ~= 0 and ':Delete!' or [[:call delete(@%) | bdelete!]], 23 | { desc = 'Delete the current file and clear the buffer' } 24 | ) 25 | 26 | -- http://stackoverflow.com/a/39348498/2103996 27 | vim.api.nvim_create_user_command('ClearRegisters', function() 28 | local regs = vim.split( 29 | 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/-"', 30 | '' 31 | ) 32 | for _, r in ipairs(regs) do 33 | vim.fn.setreg(r, {}) 34 | end 35 | end, { desc = 'Clear all registers' }) 36 | -------------------------------------------------------------------------------- /config/nvim/plugin/cron-explainer.lua: -------------------------------------------------------------------------------- 1 | local au = require '_.utils.au' 2 | 3 | -- Heavily influnced by https://github.com/fabridamicelli/cronex.nvim and some code are copied from there 4 | local M = {} 5 | 6 | local mark_id = nil 7 | M._cache = {} 8 | 9 | -- Define patterns for the content of cron expressions of different lengths. 10 | -- The first field is typically numeric (minute, second), subsequent fields can be more general. 11 | local field_numeric = '[%d%-%/%*,]+' 12 | local field_general = '[%a%d%-%/%*,%?#]+' 13 | 14 | local cron_content_patterns_by_length = { 15 | [5] = field_numeric .. ('%s+' .. field_general):rep(4), 16 | [6] = field_numeric .. ('%s+' .. field_general):rep(5), 17 | [7] = field_numeric .. ('%s+' .. field_general):rep(6), 18 | } 19 | 20 | -- "0 15 * * 1-5" 21 | 22 | M.get_cmd = function() 23 | if vim.fn.executable 'hcron' == 1 then 24 | return 'hcron' 25 | end 26 | end 27 | 28 | M.explain = function(cron_expression) 29 | local cmd = M.get_cmd() 30 | if not cmd then 31 | vim.notify('cron explainer command not found', vim.log.levels.ERROR) 32 | end 33 | 34 | local cached = M._cache[cron_expression] 35 | 36 | if cached then 37 | return cached 38 | end 39 | 40 | local full_cmd = { cmd, '-24-hour', cron_expression } 41 | 42 | local output = '' 43 | 44 | local job_id = vim.fn.jobstart(full_cmd, { 45 | stdout_buffered = true, 46 | stderr_buffered = true, 47 | on_stdout = function(_, data, _) 48 | output = output .. table.concat(data) 49 | M._cache[cron_expression] = output 50 | end, 51 | on_stderr = function(_, data, _) 52 | vim.notify(string.format('Error: %s', vim.inspect(data))) 53 | end, 54 | pty = true, -- IMPORTANT, otherwise it hangs up! 55 | }) 56 | 57 | vim.fn.jobwait({ job_id }, 2000) 58 | 59 | return vim.fn.split(output, ': ')[2] 60 | end 61 | 62 | M.cron_from_line = function(line) 63 | for n = 7, 5, -1 do 64 | local content_pattern = cron_content_patterns_by_length[n] 65 | if content_pattern then 66 | -- Try to match with double quotes 67 | local full_pattern_dq = '"%s*(' .. content_pattern .. ')%s*"' 68 | local match = line:match(full_pattern_dq) 69 | if match then 70 | return match -- string.match with a capture returns the captured part 71 | end 72 | 73 | -- Try to match with single quotes 74 | local full_pattern_sq = "'%s*(" .. content_pattern .. ")%s*'" 75 | match = line:match(full_pattern_sq) 76 | if match then 77 | return match -- string.match with a capture returns the captured part 78 | end 79 | end 80 | end 81 | return nil 82 | end 83 | 84 | local ns = vim.api.nvim_create_namespace 'cron-explainer' 85 | 86 | M.render = function(info) 87 | local cursor = vim.api.nvim_win_get_cursor(0) 88 | 89 | return vim.api.nvim_buf_set_extmark( 90 | 0, 91 | ns, 92 | cursor[1] - 1, 93 | 0, 94 | { virt_text = { { '󰥔 ' .. info, 'DiagnosticVirtualTextInfo' } } } 95 | ) 96 | end 97 | 98 | vim.keymap.set({ 'n' }, 'ec', function() 99 | if mark_id then 100 | vim.api.nvim_buf_del_extmark(0, ns, mark_id) 101 | mark_id = nil -- Clear the stored ID after deleting the mark 102 | end 103 | 104 | local expression = M.cron_from_line(vim.fn.getline '.') 105 | 106 | if expression then 107 | local data = M._cache[expression] 108 | 109 | if not data then 110 | data = vim.trim(M.explain(expression)) 111 | M._cache[expression] = data 112 | end 113 | 114 | mark_id = M.render(data) 115 | end 116 | end, { desc = 'Explain a cron expression' }) 117 | 118 | au.augroup('cron-explainer', { 119 | { 120 | event = { 'CursorMoved', 'CursorMovedI' }, 121 | callback = function(ev) 122 | vim.api.nvim_buf_clear_namespace(ev.buf, ns, 0, -1) 123 | mark_id = nil -- Reset mark_id as the extmark is now cleared 124 | end, 125 | }, 126 | }) 127 | -------------------------------------------------------------------------------- /config/nvim/plugin/diagnostics.lua: -------------------------------------------------------------------------------- 1 | local au = require '_.utils.au' 2 | local utils = require '_.utils' 3 | 4 | -- wrap open_float to inspect diagnostics and use the severity color for border 5 | -- https://neovim.discourse.group/t/lsp-diagnostics-how-and-where-to-retrieve-severity-level-to-customise-border-color/1679 6 | vim.diagnostic.open_float = (function(orig) 7 | return function(bufnr, options) 8 | local lnum = vim.api.nvim_win_get_cursor(0)[1] - 1 9 | local opts = options or {} 10 | -- A more robust solution would check the "scope" value in `opts` to 11 | -- determine where to get diagnostics from, but if you're only using 12 | -- this for your own purposes you can make it as simple as you like 13 | local diagnostics = vim.diagnostic.get(opts.bufnr or 0, { lnum = lnum }) 14 | local max_severity = vim.diagnostic.severity.HINT 15 | 16 | for _, d in ipairs(diagnostics) do 17 | -- Equality is "less than" based on how the severities are encoded 18 | if d.severity < max_severity then 19 | max_severity = d.severity --[[@as integer]] 20 | end 21 | end 22 | 23 | local border_color = ({ 24 | [vim.diagnostic.severity.HINT] = 'DiagnosticHint', 25 | [vim.diagnostic.severity.INFO] = 'DiagnosticInfo', 26 | [vim.diagnostic.severity.WARN] = 'DiagnosticWarn', 27 | [vim.diagnostic.severity.ERROR] = 'DiagnosticError', 28 | })[max_severity] 29 | 30 | opts.border = utils.get_border(border_color) 31 | 32 | orig(bufnr, opts) 33 | end 34 | end)(vim.diagnostic.open_float) 35 | 36 | vim.diagnostic.config { 37 | severity_sort = true, 38 | virtual_text = { 39 | spacing = 0, 40 | prefix = '', 41 | virt_text_pos = 'eol_right_align', 42 | format = function(diagnostic) 43 | return utils.get_icon( 44 | vim.diagnostic.severity[diagnostic.severity]:lower() 45 | ) 46 | end, 47 | }, 48 | float = { 49 | source = 'if_many', 50 | prefix = function(diag) 51 | local level = vim.diagnostic.severity[diag.severity] 52 | local icon = utils.get_icon(level:lower()) 53 | local prefix = string.format(' %s ', icon) 54 | 55 | return prefix, 'Diagnostic' .. level:gsub('^%l', string.upper) 56 | end, 57 | }, 58 | signs = false, 59 | } 60 | -------------------------------------------------------------------------------- /config/nvim/plugin/grep.lua: -------------------------------------------------------------------------------- 1 | if vim.fn.executable 'rg' == 0 then 2 | return 3 | end 4 | 5 | vim.o.grepprg = 'rg --vimgrep --smart-case --hidden' 6 | vim.o.grepformat = '%f:%l:%c:%m,%f:%l:%m' 7 | vim.keymap.set( 8 | 'n', 9 | '\\', 10 | [[:silent grep! | cwindow]], 11 | { desc = 'Grep' } 12 | ) 13 | -------------------------------------------------------------------------------- /config/nvim/plugin/statuscolumn.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | __.statuscolumn = M 4 | 5 | function M.get_signs() 6 | return vim.api.nvim_buf_get_extmarks( 7 | 0, 8 | -1, 9 | { vim.v.lnum - 1, 0 }, 10 | { vim.v.lnum - 1, -1 }, 11 | { type = 'sign', details = true } 12 | ) 13 | end 14 | 15 | local fcs = vim.opt.fillchars:get() 16 | function M.get_fold(lnum) 17 | if vim.fn.foldlevel(lnum) <= vim.fn.foldlevel(lnum - 1) then 18 | return ' ' 19 | end 20 | return (vim.fn.foldclosed(lnum) == -1 and fcs.foldopen or fcs.foldclose) 21 | .. ' ' 22 | end 23 | 24 | function M.get_filtered_signs(signs, condition) 25 | local cond = function(data) 26 | if type(condition) == 'function' then 27 | return condition(data) 28 | end 29 | return true 30 | end 31 | 32 | for _, sign in ipairs(signs) do 33 | local data = sign[4] 34 | if data and data.sign_hl_group and cond(data) then 35 | local str = '%#' .. data.sign_hl_group .. '#' 36 | 37 | if data.sign_text then 38 | str = str .. data.sign_text .. '%*' 39 | end 40 | 41 | return str 42 | end 43 | end 44 | 45 | return ' ' 46 | end 47 | 48 | function M.num() 49 | if vim.wo.number then 50 | if vim.wo.relativenumber then 51 | return vim.v.relnum 52 | end 53 | return vim.v.lnum 54 | elseif vim.wo.relativenumber then 55 | return vim.v.relnum 56 | else 57 | return '' 58 | end 59 | end 60 | 61 | function M.render() 62 | local signs = M.get_signs() 63 | 64 | return table.concat({ 65 | M.num(), 66 | [[%=]], 67 | -- Fold marker 68 | M.get_fold(vim.v.lnum), 69 | [[%=]], 70 | -- Git signs 71 | M.get_filtered_signs(signs, function(data) 72 | return data.sign_hl_group:find 'MiniDiff' 73 | end), 74 | [[%=]], 75 | -- Other signs 76 | M.get_filtered_signs(signs, function(data) 77 | return not data.sign_hl_group:find 'MiniDiff' 78 | end), 79 | }, '') 80 | end 81 | 82 | -- https://www.reddit.com/r/neovim/comments/11215fn/comment/j8hs8vj/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button 83 | -- FWIW if you use vim.o.statuscolumn = '%{%StatusColFunc()%}' emphasis on the percent signs, 84 | -- then you can just use nvim_get_current_buf() and in the context of StatusColFunc that will be equal to get_buf(statusline_winid) trick. 85 | -- You can see :help stl-%{ but essentially in the context of %{} the buffer is changed to that of the window for which the status(line/col) 86 | -- is being drawn and the extra %} is so that the StatusColFunc can return things like %t and that gets evaluated to the filename 87 | 88 | vim.o.statuscolumn = '%{%v:lua.__.statuscolumn.render()%}' 89 | -------------------------------------------------------------------------------- /config/nvim/spell/nl.utf-8.spl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedelgabri/dotfiles/e7f65a22b13edaf42bd76522313db20239430985/config/nvim/spell/nl.utf-8.spl -------------------------------------------------------------------------------- /config/nvim/spell/nl.utf-8.sug: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedelgabri/dotfiles/e7f65a22b13edaf42bd76522313db20239430985/config/nvim/spell/nl.utf-8.sug -------------------------------------------------------------------------------- /config/nvim/spell/spell.add: -------------------------------------------------------------------------------- 1 | CSS 2 | PostCSS 3 | PDF 4 | app 5 | iTerm2 6 | config 7 | Vim 8 | tmux 9 | i18n 10 | CoffeeScript 11 | ES2015 12 | SCSS 13 | Refactor 14 | ESLint 15 | Stylelint 16 | SCSSLint 17 | NPM 18 | SEOShop 19 | shrinkwrap 20 | mins 21 | nvm 22 | Homebrew 23 | Xcode 24 | Workflow 25 | wireframes 26 | UI 27 | UX 28 | ahmedelgabri 29 | Gabri 30 | eCom 31 | apps 32 | JS 33 | JSON 34 | Backend 35 | devs 36 | jQuery 37 | GitLab 38 | Gmail 39 | macOS 40 | keychain 41 | gmail 42 | smtp 43 | imap 44 | dotfiles 45 | screenshot 46 | weechat 47 | newsboat 48 | hammerspoon 49 | IRC 50 | RSS 51 | GitHub 52 | github 53 | thingy 54 | CTO 55 | JavaScript 56 | Lightspeed 57 | semi-professional 58 | self-taught 59 | front-end 60 | go-to 61 | front-enders 62 | co-started 63 | day-to-day 64 | non-technical 65 | mentorship 66 | dubizzle 67 | UTC 68 | GPG 69 | onboarding 70 | U2F 71 | openpgp 72 | gpg 73 | POSIX 74 | OSX 75 | PGP 76 | Clojure 77 | ultisnips 78 | Second-Order 79 | Yubikey 80 | keypair 81 | prettier-ignore 82 | Podcasts 83 | YouTube 84 | ClojureScript 85 | xmas 86 | FP 87 | OCaml 88 | Zsh 89 | vim 90 | Ramda 91 | WordPress 92 | Preact 93 | CLI 94 | Facebook 95 | Autocomplete 96 | Trie 97 | Dependabot 98 | dependabot 99 | PRs 100 | fallback 101 | CNAME 102 | Auth 103 | api 104 | nodejs 105 | GraphQL 106 | middleware 107 | front-end 108 | eCommerce 109 | dev 110 | Plugins 111 | plugins 112 | SDK 113 | OAuth2 114 | URLs 115 | npm 116 | APIs 117 | TypeScript 118 | plugin 119 | personas 120 | middleware 121 | webhooks 122 | Redis 123 | Jira 124 | videochat 125 | auth 126 | POC 127 | PMs 128 | COVID-19 129 | DevEx 130 | SWE 131 | WhatsApp 132 | KPN 133 | FB 134 | SDKs 135 | hands-on 136 | Microsystems 137 | Spotify 138 | codebase 139 | DevX 140 | TSLint 141 | auto-formatted 142 | intention 143 | Spotify 144 | Figma 145 | Basecamp 146 | Uber 147 | zsh 148 | htop 149 | VimScript 150 | autocomplete 151 | microservices 152 | iframe 153 | iframes 154 | WASM 155 | Fullstack 156 | WeWork 157 | DevOps 158 | SREs 159 | IPO 160 | Toolbar 161 | VR 162 | SRE 163 | reference 164 | AWS 165 | Ansible 166 | Frontend 167 | frontend 168 | K8s 169 | Kotlin 170 | AWS 171 | S3 172 | RPC 173 | JVM 174 | P2P 175 | miro 176 | -------------------------------------------------------------------------------- /config/pandoc/bookmark.lua: -------------------------------------------------------------------------------- 1 | ---@diagnostic disable: undefined-global 2 | 3 | -- https://pandoc.org/lua-filters.html 4 | -- Filter to remove inline links from markdown 5 | -- Also adds some metadata to the generated frontmatter 6 | 7 | local base = '' 8 | 9 | local function fix_link(url) 10 | return url:sub(1, 1) == '/' and base .. url or url 11 | end 12 | 13 | local function parse_url(url) 14 | -- selene: allow(undefined_variable) 15 | local url_pattern = re.compile [[ 16 | url <- {| 17 | {:scheme: [a-zA-Z][a-zA-Z0-9+-.]* :} "://" 18 | {:host: [^/:?#]+ :} 19 | (":" {:port: [0-9]+ :})? 20 | {:path: "/" [^?#]* :}? 21 | ("?" {:query: [^#]* :})? 22 | ("#" {:fragment: .* :})? 23 | |} 24 | ]] 25 | 26 | local parsed_url = url_pattern:match(url) 27 | 28 | return parsed_url 29 | end 30 | 31 | -- selene: allow(undefined_variable) 32 | -- selene: allow(unused_variable) 33 | function Meta(m) 34 | local parsed_url = parse_url(m.source) 35 | 36 | if parsed_url ~= nil then 37 | base = parsed_url.scheme .. '://' .. parsed_url.host 38 | end 39 | 40 | if m.date == nil then 41 | m.date = os.date '%Y-%m-%d' 42 | end 43 | 44 | m.id = os.date '%Y%m%d%H%M%S' 45 | m.published = '' 46 | m.tags = { 'saved-articles' } 47 | m.category = '"[[saved-articles]]"' 48 | m.author = { m.author or '' } 49 | 50 | return m 51 | end 52 | 53 | -- selene: allow(unused_variable) 54 | function Link(link) 55 | if link.target:match '^#' then 56 | return link.content 57 | end 58 | 59 | link.target = fix_link(link.target) 60 | 61 | return link 62 | end 63 | 64 | -- selene: allow(unused_variable) 65 | function Image(img) 66 | img.src = fix_link(img.src) 67 | return img 68 | end 69 | 70 | return { { Meta = Meta }, { Link = Link, Image = Image } } 71 | -------------------------------------------------------------------------------- /config/pip/pip.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | timeout = 15 3 | download_cache = ~/.pip/cache 4 | 5 | [list] 6 | format = columns 7 | -------------------------------------------------------------------------------- /config/ripgrep/config: -------------------------------------------------------------------------------- 1 | # vim:ft=conf 2 | # global ignores are in ~/.ignore so it can be picked up by fd & other tools too 3 | --hidden 4 | --smart-case 5 | -------------------------------------------------------------------------------- /config/tmux/.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | -------------------------------------------------------------------------------- /config/tmux/scripts/get-prayer: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Intentionally not setting -e because we want the script to continue if getting the location data fails 4 | set -u -o pipefail 5 | 6 | if [[ -n "${DEBUG-}" ]]; then 7 | set -x 8 | fi 9 | 10 | LOCATION_DATA="$TMPDIR/.location.json" 11 | 12 | # Validate the JSON syntax 13 | if jq -e . "$LOCATION_DATA" >/dev/null 2>&1; then 14 | FLAGS=$(jq -r '"-latitude \(.location.latitude) -longitude \(.location.longitude)"' "$LOCATION_DATA") 15 | 16 | printf "%s" "󰩷 $(next-prayer mawaqit $FLAGS)" 17 | else 18 | printf "%s" "$(next-prayer aladhan)" 19 | fi 20 | -------------------------------------------------------------------------------- /config/tmux/scripts/next-prayer/Makefile: -------------------------------------------------------------------------------- 1 | BINARY_NAME=next-prayer 2 | 3 | export BIN ?= ./bin/${BINARY_NAME} 4 | 5 | export GOBIN ?= /usr/local/bin/ 6 | 7 | VERSION=$(shell git rev-parse --short HEAD) 8 | 9 | GO_FLAGS=-ldflags "-w -s -X main.version=$(VERSION)" 10 | 11 | all: build 12 | 13 | release: test tidy build 14 | 15 | build: 16 | go build ${GO_FLAGS} -o ${BIN} ./cmd/next-prayer 17 | 18 | run: 19 | ./bin/${BINARY_NAME} 20 | 21 | install: 22 | go install ${GO_FLAGS} ./cmd/next-prayer 23 | 24 | test: 25 | go test -coverprofile=coverage.out ./... 26 | 27 | cov: | test 28 | go tool cover -html=coverage.out 29 | 30 | lint: 31 | go vet ./... 32 | 33 | tidy: 34 | go mod tidy 35 | 36 | format: 37 | goimports -w ./ 38 | -------------------------------------------------------------------------------- /config/tmux/scripts/next-prayer/aladhan/aladhan.go: -------------------------------------------------------------------------------- 1 | package aladhan 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "math/rand" 8 | "net/http" 9 | "time" 10 | 11 | shared "github.com/ahmedelgabri/dotfiles/config/tmux/scripts/next-prayer/shared" 12 | ) 13 | 14 | var ( 15 | agents = [6]string{ 16 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36", 17 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36", 18 | "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0", 19 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7", 20 | "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", 21 | "Mozilla", 22 | } 23 | ) 24 | 25 | type Date struct { 26 | Readable string `json:"readable"` 27 | } 28 | 29 | type Response struct { 30 | Code int `json:"code"` 31 | Status string `json:"status"` 32 | Data struct { 33 | Timings shared.AllTimes `json:"timings"` 34 | Date Date `json:"date"` 35 | } `json:"data"` 36 | } 37 | 38 | type Flags struct { 39 | City *string 40 | Country *string 41 | Method *int 42 | Tune *string 43 | } 44 | 45 | type aladahan struct { 46 | flags Flags 47 | } 48 | 49 | func New(flags Flags) aladahan { 50 | return aladahan{ 51 | flags: flags, 52 | } 53 | } 54 | 55 | func (aladahan) PrintHelp() { 56 | fmt.Printf(` 57 | Usage 58 | $ next-prayer aladhan [options] 59 | 60 | Options 61 | --country The country you want prayers time for (i.e. United Kingdom or UK) 62 | --city The city you want prayers time for (i.e. London) 63 | --method Calculation method (i.e. 3) 64 | --tune Prayer times tuning (i.e. "") 65 | --help Print this help 66 | 67 | Examples 68 | $ next-prayer aladhan --country nl --city amsterdam --method 3 69 | `) 70 | } 71 | 72 | func (a aladahan) Get_api() (shared.ApiData, error) { 73 | client := &http.Client{} 74 | url := fmt.Sprintf("https://api.aladhan.com/v1/timingsByCity?city=%s&country=%s&method=%d&tune=%s", *a.flags.City, *a.flags.Country, *a.flags.Method, *a.flags.Tune) 75 | req, err := http.NewRequest(http.MethodGet, url, nil) 76 | 77 | if err != nil { 78 | return shared.ApiData{}, err 79 | } 80 | 81 | rand.New(rand.NewSource(time.Now().Unix())) 82 | req.Header.Add("Host", "api.aladhan.com") 83 | req.Header.Add("User-Agent", agents[rand.Intn(len(agents))]) 84 | 85 | resp, err := client.Do(req) 86 | 87 | if err != nil { 88 | return shared.ApiData{}, err 89 | } 90 | 91 | defer resp.Body.Close() 92 | 93 | if resp.StatusCode == http.StatusForbidden { 94 | fmt.Println(err) 95 | } 96 | 97 | body, err := io.ReadAll(resp.Body) 98 | 99 | if err != nil { 100 | return shared.ApiData{}, err 101 | } 102 | 103 | obj := Response{} 104 | err = json.Unmarshal(body, &obj) 105 | 106 | if err != nil { 107 | return shared.ApiData{}, err 108 | } 109 | 110 | return shared.ApiData{ 111 | Timings: obj.Data.Timings, 112 | }, nil 113 | } 114 | -------------------------------------------------------------------------------- /config/tmux/scripts/next-prayer/cmd/next-prayer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "github.com/ahmedelgabri/dotfiles/config/tmux/scripts/next-prayer/aladhan" 9 | "github.com/ahmedelgabri/dotfiles/config/tmux/scripts/next-prayer/mawaqit" 10 | "github.com/ahmedelgabri/dotfiles/config/tmux/scripts/next-prayer/shared" 11 | ) 12 | 13 | var ( 14 | version string 15 | ) 16 | 17 | func formatOutput(output shared.Output) string { 18 | red := "\033[1;31;40m" 19 | 20 | if _, isTmux := os.LookupEnv("TMUX"); isTmux { 21 | red = "#[fg=red]" 22 | } 23 | 24 | if output.TimeRemaining > -1 && output.TimeRemaining <= 30 { 25 | return red + output.Item 26 | } 27 | 28 | return output.Item 29 | } 30 | 31 | func print_help() { 32 | fmt.Printf(` 33 | Usage 34 | $ next-prayer [command] [options] 35 | 36 | Commands 37 | mawaqit Get prayers times from Mawaqit 38 | aladhan Get prayers times from Aladhan 39 | 40 | Options 41 | --version Print the CLI version (%s) 42 | --help Print this help 43 | `, version) 44 | } 45 | 46 | func main() { 47 | mawaqitCmd := flag.NewFlagSet("mawaqit", flag.ExitOnError) 48 | aladhanCmd := flag.NewFlagSet("aladhan", flag.ExitOnError) 49 | 50 | if len(os.Args) < 2 { 51 | print_help() 52 | os.Exit(1) 53 | } 54 | 55 | switch os.Args[1] { 56 | case "mawaqit": 57 | username := mawaqitCmd.String("username", os.Getenv("MAWAQIT_USERNAME"), "Mawaqit Username") 58 | password := mawaqitCmd.String("password", os.Getenv("MAWAQIT_PASSWORD"), "Mawaqit Password") 59 | latitude := mawaqitCmd.String("latitude", os.Getenv("MAWAQIT_LATITUDE"), "Latitude") 60 | longitude := mawaqitCmd.String("longitude", os.Getenv("MAWAQIT_LONGITUDE"), "Longitude") 61 | help := mawaqitCmd.Bool("help", false, "Help!") 62 | 63 | mawaqitCmd.Parse(os.Args[2:]) 64 | 65 | s := mawaqit.New(mawaqit.Flags{ 66 | Username: username, 67 | Password: password, 68 | Latitude: latitude, 69 | Longitude: longitude, 70 | }) 71 | 72 | if *help { 73 | s.PrintHelp() 74 | return 75 | } 76 | 77 | result := shared.Get_prayer(s) 78 | 79 | fmt.Println(formatOutput(result)) 80 | return 81 | case "aladhan": 82 | // https://aladhan.com/prayer-times-api#GetCalendarByCitys 83 | city := aladhanCmd.String("city", "Almere", "City name") 84 | country := aladhanCmd.String("country", "nl", "Country name") 85 | method := aladhanCmd.Int("method", 12, "Prayer method") 86 | tune := aladhanCmd.String("tune", "0,-18,0,0,0,0,0,12,0", "Prayer time tuning") 87 | help := aladhanCmd.Bool("help", false, "Help!") 88 | 89 | aladhanCmd.Parse(os.Args[2:]) 90 | 91 | s := aladhan.New(aladhan.Flags{ 92 | Country: country, 93 | City: city, 94 | Method: method, 95 | Tune: tune, 96 | }) 97 | 98 | if *help { 99 | s.PrintHelp() 100 | return 101 | } 102 | 103 | result := shared.Get_prayer(s) 104 | 105 | fmt.Println(formatOutput(result)) 106 | return 107 | default: 108 | version := flag.Bool("version", false, "CLI version") 109 | help := flag.Bool("help", false, "Help!") 110 | 111 | flag.Parse() 112 | 113 | if *help { 114 | print_help() 115 | return 116 | } 117 | 118 | if *version { 119 | fmt.Println(version) 120 | return 121 | } 122 | 123 | fmt.Println("expected 'mawaqit' or 'aladhan' subcommands") 124 | os.Exit(1) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /config/tmux/scripts/next-prayer/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ahmedelgabri/dotfiles/config/tmux/scripts/next-prayer 2 | 3 | go 1.21 4 | -------------------------------------------------------------------------------- /config/tmux/scripts/next-prayer/next-prayer.nix: -------------------------------------------------------------------------------- 1 | { buildGoModule }: 2 | 3 | buildGoModule rec { 4 | name = "next-prayer"; 5 | version = "latest"; 6 | 7 | vendorHash = null; 8 | 9 | src = ./.; 10 | 11 | ldflags = [ "-w" "-s" "-X=main.version=${version}" ]; 12 | } 13 | -------------------------------------------------------------------------------- /config/tmux/scripts/tmux-github-status: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # https://www.githubstatus.com/api#status 4 | GITHUB_STATUS=$(curl -sS https://kctbh9vrtdwd.statuspage.io/api/v2/status.json | jq -r '.status.indicator') 5 | 6 | INDICATOR="#[fg=colour237]⦁" 7 | 8 | case $GITHUB_STATUS in 9 | maj* | cri*) 10 | STATUS="#[fg=red]  $INDICATOR " 11 | ;; 12 | mi*) 13 | STATUS="#[fg=yellow]  $INDICATOR " 14 | ;; 15 | mai*) 16 | STATUS="#[fg=yellow]  $INDICATOR " 17 | ;; 18 | *) 19 | STATUS="" 20 | ;; 21 | esac 22 | 23 | printf "%s" "$STATUS" 24 | -------------------------------------------------------------------------------- /config/tmux/scripts/tmux-npm-status: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # https://status.npmjs.org/api#status 4 | NPM_STATUS=$(curl -sS https://wyvgptkd90hm.statuspage.io/api/v2/status.json | jq -r '.status.indicator') 5 | 6 | INDICATOR="#[fg=colour237]⦁" 7 | 8 | case $NPM_STATUS in 9 | ma* | cri*) 10 | STATUS="#[fg=red]  $INDICATOR " 11 | ;; 12 | mi*) 13 | STATUS="#[fg=yellow]  $INDICATOR " 14 | ;; 15 | mai*) 16 | STATUS="#[fg=yellow]  $INDICATOR " 17 | ;; 18 | *) 19 | STATUS="" 20 | ;; 21 | esac 22 | 23 | printf "%s" "$STATUS" 24 | -------------------------------------------------------------------------------- /config/tmux/scripts/tmux-weather: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | _load_weather() { 4 | # check for internet connection 5 | ping -q -c 1 1.1.1.1 >/dev/null && { 6 | weather "" "format=%c+%t+%h+%w+%m" >"$TMP_WEATHER_FILE" 7 | printf "\n$(date +'%s')" >>"$TMP_WEATHER_FILE" 8 | } 9 | } 10 | 11 | # Weather data 12 | weather_segment() { 13 | local -r TMP_WEATHER_FILE="$TMPDIR/weather.tmp" 14 | local -r REFRESH_RATE=$((60 * 60)) // 60 # minutes 15 | 16 | [[ -f "$TMP_WEATHER_FILE" ]] || _load_weather 17 | 18 | local now 19 | now="$(date +'%s')" 20 | local epoch 21 | epoch="$(tail -n 1 "$TMP_WEATHER_FILE")" 22 | local delta 23 | delta="$((now - epoch))" 24 | 25 | # check if it's time to update the data 26 | [[ $delta -gt $REFRESH_RATE ]] && _load_weather 27 | 28 | local weather 29 | weather="$(head -n 1 "$TMP_WEATHER_FILE")" 30 | weather="$(echo "${weather//+/}")" 31 | 32 | echo 33 | 34 | printf "%s" "$weather" 35 | } 36 | 37 | weather_segment 38 | -------------------------------------------------------------------------------- /config/vivid/theme.yml: -------------------------------------------------------------------------------- 1 | # Based on one-light https://github.com/sharkdp/vivid/blob/3d33c47659ab8155fb09dd074805c65657393b51/themes/one-light.yml 2 | colors: 3 | background_color: 'fafafa' 4 | white: 'a0a1a7' 5 | red: 'e45649' 6 | green: '50a14f' 7 | yellow: 'c18401' 8 | blue: '4078f2' 9 | pink: 'ff6ac1' 10 | cyan: '0184bc' 11 | 12 | black: '000000' 13 | gray: '999999' 14 | darkgray: '666666' 15 | darkergray: '333333' 16 | 17 | core: 18 | normal_text: {} 19 | regular_file: {} 20 | reset_to_normal: {} 21 | 22 | directory: 23 | foreground: blue 24 | 25 | symlink: 26 | foreground: pink 27 | 28 | multi_hard_link: {} 29 | 30 | fifo: 31 | foreground: black 32 | background: blue 33 | 34 | socket: 35 | foreground: black 36 | background: pink 37 | 38 | door: 39 | foreground: black 40 | background: pink 41 | 42 | block_device: 43 | foreground: cyan 44 | background: darkergray 45 | 46 | character_device: 47 | foreground: pink 48 | background: darkergray 49 | 50 | broken_symlink: 51 | foreground: black 52 | background: red 53 | 54 | missing_symlink_target: 55 | foreground: black 56 | background: red 57 | 58 | setuid: {} 59 | 60 | setgid: {} 61 | 62 | file_with_capability: {} 63 | 64 | sticky_other_writable: {} 65 | 66 | other_writable: {} 67 | 68 | sticky: {} 69 | 70 | executable_file: 71 | foreground: red 72 | font-style: bold 73 | 74 | text: 75 | special: 76 | foreground: red 77 | # background: yellow 78 | 79 | todo: 80 | font-style: bold 81 | 82 | licenses: 83 | foreground: gray 84 | 85 | configuration: 86 | foreground: yellow 87 | 88 | other: 89 | foreground: yellow 90 | 91 | markup: 92 | foreground: yellow 93 | 94 | programming: 95 | source: 96 | foreground: green 97 | 98 | tooling: 99 | foreground: green 100 | 101 | continuous-integration: 102 | foreground: green 103 | 104 | media: 105 | foreground: pink 106 | 107 | office: 108 | foreground: red 109 | 110 | archives: 111 | foreground: cyan 112 | font-style: underline 113 | 114 | executable: 115 | foreground: red 116 | font-style: bold 117 | 118 | unimportant: 119 | foreground: darkgray 120 | -------------------------------------------------------------------------------- /config/weechat/buflist.conf: -------------------------------------------------------------------------------- 1 | U2FsdGVkX1943x68t5TbvIy3OH8OLugyow6qV1aSK3Y5EbM/jybczmqezjX3jcKa 2 | RCINsf5LbDHV3jZmnDegVGK5+EGFDsHvZHYMPqxjuuyjbUfQEDGCrUap7PIXzyBP 3 | nt+Iih9kHuCaWSsj6tnw2MpLkacfND6gdN1wMLXCr3CO3Gl+iM54biSsSap0gWXX 4 | SoHg2enM3UtMWGBEwMGCt/jneax1uFxK94oXq15Pm8rNvtD8vcGayQIjvebnUQOi 5 | ecuxjpOcZFEj7mzIrK5ijNjhtacfg9Z1T3qC1Y1OQGTDFZOffgAu07LxHGrTGZfu 6 | GKpcjzRdikS2eKqllriLqVDvY9HDwfcNeqaSRZzjZxn8DFsFzbmBIuUJhySUa57c 7 | O2nm4/hBlx+CtFcppqFLM7ddXsITmAqtiyYnfoWtWyAeCYb29+yeqKcI0XOjpIJP 8 | gnqaJPQu9x9Aqe38sIaOguGNi+zf3vET0E3qEEx4CIeO1LDtAOfikhyJUNVovOF2 9 | 5e2sPzdpQXcRUHy344Y4IFJtOZv/J5XzljLcpsRYiLW3ZlO115zZnMz9nq4lcNs3 10 | 1UUvagaduMwiiqwVHomWLhlY9vMMUvyehadhLD0t7gcbODN0G02yucgiHvO3m/F5 11 | 8NPQ+o53uD+g32q9N7QQ4Zqwsu/9XzNgosvDg0ewzZApRI2GTvDSRSEs2B6rPbH/ 12 | mB/vEDIBr7Baj3BXL033BCZANaonjc9CK2iKN17cGaG8NV4wox90L+/FF73A8md3 13 | kPw2ioH0sWbTw0BiwscegUhrWLshxoNBxWZsRQiNcFB8oQG2Oh1rjVHDbYad7ciS 14 | W1ebOD2Wh7onU2Y3Opcvn4fvtFiAkB2UqIpqOx1Q/spbR+bWUbJRLSZ5wXK5VEu7 15 | LKAJLbzt73SEbnMekgLxodP4Zb+r7KPPq7y/huj+CVZt6lFlWu6ob2uxYak8I4W9 16 | kQmV7qzp5+ErZ3pdQGjEa0ywbxdHYzLrRUyVurwFmYOHu2maNGPdDjPEi6WPgNLA 17 | JBO2H0QH/a9CdGCmNPGJuRCl+G2+cQWtYPP3BXlNtADqwmMpd9JhsSWFpi33Ii0J 18 | r007BrKoHksE9blc15b52dR1OjcvhaDa/mRfjp8SnknDqilkip5/6jeuXPTBFWZr 19 | JUYYwXqOLlsjxvZnlh77k/RK0gnfFpYQgYwc2B1kGxva1aqmu1HfHjVO4O9PtvDK 20 | hSu+yPSGwiZ8yvBIM/DIvdhvaCn7l9i7fkwk6gmW3CynyhS9DwPsTkGHNxxZAPEK 21 | T9G6zSgKgYhn3S7ORDCtluGEZBPZmgp3O6OWiljNq/ggpLc6EE+zsMKKKcpq8MX3 22 | Nm5DKMcyH/6AbSJ9Zpxn8YK6TsmdljAY3xAKRftO72b70mxD8m8al8CZyPmPVi1O 23 | Aol3dX4VY6DQ21hFACybVQR7or0qP59ahOCvKSy7rIQlGwzsBqbJJwkAUxa7UhsP 24 | 7JwOO39O2/zFeP/Lri9BH5/sGC75i08LhmfYsZ9PvziC6RaKzmvdsthLv1pll/Jt 25 | S1u5XQCEKsR+tZ2lBS5p7/8vbtDfuEFT/EF4fhYsh3czU8zkXBSurq4EUSOS1SK0 26 | WAOcLqOPZ9OLUJlkSjxh7W6txrwWCzbkuk6kmHsyUUpqB+VmsaZbd1A5NbIrZF2S 27 | aHuZ+Mx1Y0mFfOIx/OpG1y2i3iAdPi19P2tYOaYuvgQtybt0QxAwJKkIBjv5w4Ha 28 | l2iVBKExas3WW6kfgGZzu1sFMCHj3nUOlG3piEG8QOpoXK2kTHRafkPXN9t96Hl+ 29 | SvYtIjZv89vJLqkzde3UlA2kYWub0wLXt4nuQpjAckLdC0yg1E08caP0DWHJ++PL 30 | VZho41d7sSMsDJSO3/cVcRYpsMWZ651PMrcJkPALir14deWFLrp5sTqxfMxoh6A6 31 | 4bgjvo8QLhRVyyY95DXtqkkttmOhqT5NIR2HZG0C/xCFLW34usE2Y9NpT0PqSdEk 32 | y411y9S4fzsvNYfqguCGZ/NpED5c9LMHqshMONEcS8IctHG1+ruLRaEpJTpLT7QL 33 | CbFOughUfHNQkOzRHf8iQcpz6HBmwJbzN9cIP0EuUyvYpvoZjTxb8WzZFtdio1gm 34 | 4Xe8x1EOGfUU+BNQiksjIozLhCtiSRd5BJGRV0zWK62TbhXteuwR+puHID+rGARe 35 | gpr9MGRJ+Clqlv+6R2gB8GxhqdOVufvOdatFE5hNHMVxy7KI/TNb+TpqjBDD4Fcz 36 | K6uX17giPlrx1q3dRWDqJP/+qyiKgANILOMdfCZIWfxFYb7X8EMGCW5HHjcQUoSA 37 | UvJXlpka3rCbRs5XNKuBDeFEg7Tn/CzH3KcJ0FHz9D4a9mYYy2JUBxInTYOAMsaJ 38 | 8O7Jd/WXT/4xyBG5YZ+NWplpND9fLMLAXIUweRj7pTFSzMtI4K5pRbfBZbQ7iApA 39 | wIjkjBpL58nopZyCqGyxPl5DxSPASBLySLR18EWs4Qse/qJQhGH+alDf1hDYuA8q 40 | yxdayiomf5F6O1YN74E3Xr3AFQfJwqjqXV0LZEkjkoqCUI0TpuyzqXU4+dIxiBEj 41 | 3GKpFAiGyJCxN79iGk1FeV8Hc+UoS19WDRaKJChRTyQC2I3urb4AZx2wkSQceNb+ 42 | 39GhkKiqhxq+AdzbNTS38r9Lcjl4mP7ksfKHEqXb9JoAKl85WW4FSu3REODmoyw8 43 | q7mhG7RzT2m42RGId1K/UiiFLWgmoQ/de9hlTLi8gd/fIJH/tIAoc1rgeSgCJcj0 44 | ZtO2KvrDT+2VTMI0OYQYQ9/QRhCeDvm+F9rDWmhxhXkk5gdfdNOkp9L3IvSW1CTF 45 | KIG/LOzhuwU5NDbOmpaaq/K1BhrSM2CZP8ajPi1LdM8En4ckYUonKeUhP7Bllij0 46 | T6mcKjRzn3L11rl4H/16Yszn9+vviLLzdqkKpcJpkl8WjwNGweAToSv0UlgydBtx 47 | p/cHDxp+NWxfL90ff56GoKWWemrnqKh9KBz9jqAcULIZ5ioRA+I0MsdK58Eo5/qR 48 | eoeXx8rJemQFCJ/JaImBFA== 49 | -------------------------------------------------------------------------------- /config/weechat/sec.conf: -------------------------------------------------------------------------------- 1 | U2FsdGVkX19AFwLy9iRH97CJ16SX8gYpoI7++hpeDqTNgVCwu4GzqboFuvt3Mt8e 2 | dFQlTKfropOJA+12k9Ffh7TqUISuguRK7ThBi0fPNId3YxW0+o0lFNKTYNHx/kDo 3 | CGciU8yIZz1ZI/+qGzkeLTYrUHJ1LSl9SbIndgVseTY11LNcrrvjVNV017taP+cn 4 | OvLyeOWpwuln0H5oN1SZT3zAmW0p+mOGLMRVfOHMxlYolByyxj9YcjoAiFC/cLsb 5 | Ue6nrfUgrnIJfAQZcds3WtXE/rijh+V0A+fAq5LcXbzAKHt94hl5nYcbE0qHGYD/ 6 | DY5ywQvz27V7KDodrQ2nbM6trVtjLUkYxLN7OG3h8wnZd8bPG5XUcnPkhllkt/Xs 7 | 6+MWJHAQ/w7qZBsaUcaIeO6tiiGiVqAuu2pSjjeU9rRbHiJD0JUN4i1G0QKYT3jn 8 | v9SjmM/dDH1Z14bcpH7/+s6LJ/+FV+BAT22Fgbnn6rcd6dWXYJ0u9jtKY6alkLnf 9 | rozkKVh0/OjjGkxv7AkzYBhvksvWGL88ESzeWZ6dRkgO27K2QVIjZkF3UntIiEXU 10 | FkoDylrWvEB2rFFUuD2c+Z8AKaGr5NrF2OFiYGce69BI9jNirrr9Xgdyo8+0UTpX 11 | 5V8d1A+3+J7PE+CQk+IN0YU4VQvDJQi4JdeIpU0cP1a395pBTObcVvUUCZ7deAOS 12 | MJMOvQO7v1dqcaSU20bQpBlp1qPMxWsk8wTcmBwN5TR0y3dD6pIr/bZYVQSr/jQj 13 | fGlzmWrFvx9KPm6pZ1Z+jQ7VRUp+mhzHZv8vFSaBS6qpTjww6ChBsK3L2EVZrR+n 14 | uz4bSARFXhZAMk44UOMq5vcOIQ3qrlyzBN9zjjqaec6TTCj1JqYfth8teQxPvfCI 15 | HzLG2G2u1AGLmfoOyiD2nUFmW1dvlocK3Hz9HmGZVC9wKqnG+i/BHEcuuO+zj2ix 16 | sn6r8/Wdk0J67kUjHttGyEy3FmYdidjl3QnZokG7JCcaOaMBQeDLO0iW7nIg//HV 17 | tz/q0QXVV8EZBSpBBEHRuQ7HDo+zHqDYYIL79OSj0jqECHc/q6fxyF1hSceWPNHZ 18 | ues06TMnfTUBulEprbNB0cHF1Bw3RecveoO/5UdPtRMfmrfgb84gZC32kBIaPzln 19 | QLOhMsWmdeESXkzpDj1sVz8LQHZemJ0+tP/FIPnS02KS82ylBseMQxHHoXMYvjiY 20 | utWilS3VGp7bng7qLZn2eMSX/zcoreXOr4fuWD0qdgXuYAuWP5fVH0ZWgOIIQuaW 21 | xAzrIZcQG/PDMhpYxLsYdU73f1s3HGO2WWRnzd6Mquiec7S7NKVKmB5hL9mq3QE8 22 | 8rH/lpsnNDPc1hxUVV0vP68ieinKOSdAPDueH+q855LuY5GXos4WgwggfKgWcpaR 23 | 16MagQWBQn/q6cY4kaeawwx18ciqoHpa08zh6vBIaS/0svFb+PSUST3EIQuQEu+a 24 | RmpZiXWeSEGQMnuZXCDAQ/VbNuYnjQF/dtatGT2ud6hONtL62F2/qYQNJvKjhuHp 25 | HbEEr15tXrvs3EuUyvKV//RKpywMpLNLBfBU7aeRtxXkizOvFRdffGOivhJWgND1 26 | EplTRm3z+LTiL8t8nW/amCmekT7X/IcopSc+in6hIbXzKP8SQf1UyszsEFuOyLfX 27 | EzogIlzh3t2L/5Q55BQaWzVBA1ECyBHbe77yBGvhL92ZVcFsbzsE96VsvKcJq+NT 28 | JaTl4BZ8gGkLV0PXdLZfhpHThXJrTadgcq1Vax5hnP+B5pl6JaTvQh2wkFGVx+QZ 29 | 3O2KIGy28RyNKVy1XHb/M31CVfUQSWHRbr68L7g2zB592KXW/nunLr4KfrEe/Vpp 30 | xPONQNttdf5nq+q4YLkUkX0OX0Mu7KA+APmDeRLoqLVN69gVBKufvhwloSwWz73j 31 | ee7wX8bpunWnW29qeJYpFILaBnUxfCMhoFcW8Ndtp6HYk+hNB2a+iSAvh0LlFGbt 32 | ZcGTcvUlQu8sZ0tVKpnArXKi9MF/U/085baKHExciBpdlY8XCSWRBghaMUwDnnB4 33 | UEoOX+vaH/pBUv4CXG0JMxYTYZYo2Y4cc309/pwIhVJ1QqpLZ0rEr/VgCZAfoalt 34 | AljuWH8/C7wjULUQKlzbdSoDpIj6Q00gCJP4ZrNzXiLAOtaUT18E2a3mnZnC5iky 35 | yR0YItuXqeZ/ASgvzH5ZBA== 36 | -------------------------------------------------------------------------------- /config/yazi/init.lua: -------------------------------------------------------------------------------- 1 | ---@diagnostic disable: undefined-global 2 | 3 | require('git'):setup() 4 | require('smart-enter'):setup { open_multi = true } 5 | require('folder-rules'):setup() 6 | 7 | -- Don't load it inside neovim, `yazi.nvim` has its own border 8 | if not os.getenv 'NVIM' then 9 | require('full-border'):setup { type = ui.Border.PLAIN } 10 | end 11 | 12 | -- https://yazi-rs.github.io/docs/tips#username-hostname-in-header 13 | Header:children_add(function() 14 | if ya.target_family() ~= 'unix' then 15 | return '' 16 | end 17 | return ui.Span(ya.user_name() .. '@' .. ya.host_name() .. ':'):fg 'blue' 18 | end, 500, Header.LEFT) 19 | 20 | ---@return unknown 21 | -- https://yazi-rs.github.io/docs/tips#show-symlink-in-status-bar 22 | function Status:name() 23 | local h = cx.active.current.hovered 24 | if not h then 25 | return ui.Span '' 26 | end 27 | 28 | local linked = '' 29 | if h.link_to ~= nil then 30 | linked = ' -> ' .. tostring(h.link_to) 31 | end 32 | return ui.Span(' ' .. h.name .. linked) 33 | end 34 | 35 | -- https://yazi-rs.github.io/docs/tips#show-usergroup-of-files-in-status-bar 36 | function Status:owner() 37 | local h = cx.active.current.hovered 38 | if h == nil or ya.target_family() ~= 'unix' then 39 | return ui.Line {} 40 | end 41 | 42 | return ui.Line { 43 | ui.Span(ya.user_name(h.cha.uid) or tostring(h.cha.uid)):fg 'magenta', 44 | ui.Span ':', 45 | ui.Span(ya.group_name(h.cha.gid) or tostring(h.cha.gid)):fg 'magenta', 46 | ui.Span ' ', 47 | } 48 | end 49 | 50 | function Entity:icon() 51 | local icon = self._file:icon() 52 | 53 | if not icon then 54 | return ui.Line '' 55 | elseif self._file.is_hovered then 56 | return ui.Line(icon.text .. ' ') 57 | else 58 | return ui.Line(icon.text .. ' '):style(icon.style) 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /config/yazi/keymap.toml: -------------------------------------------------------------------------------- 1 | "$schema" = "https://yazi-rs.github.io/schemas/keymap.json" 2 | # Default keymaps: https://github.com/sxyazi/yazi/blob/shipped/yazi-config/preset/keymap.toml 3 | [manager] 4 | 5 | prepend_keymap = [ 6 | # (Normally, "Open selected files".) 7 | # See: https://yazi-rs.github.io/docs/tips#smart-enter 8 | { on = "o", run = "plugin smart-enter", desc = "Enter the child directory, or open the file" }, 9 | { on = "", run = "plugin smart-enter", desc = "Enter the child directory, or open the file" }, 10 | 11 | { on = "p", run = "plugin smart-paste", desc = "Paste into the hovered directory or CWD" }, 12 | 13 | # Mnemonic: "[s]how" 14 | # (Normally, "Search files by name via fd".) 15 | { on = "s", run = "plugin --sync reveal-in-finder", desc = "Reveal in Finder" }, 16 | 17 | # Mnemonic: "[T]oggle preview" 18 | { on = "T", run = "plugin toggle-pane min-preview", desc = "Hide or show preview" }, 19 | # Mnemonic: "[F]ull-size preview" 20 | { on = "F", run = "plugin toggle-pane max-preview", desc = "Maximize or restore preview" }, 21 | 22 | # https://yazi-rs.github.io/docs/tips#email-selected-files 23 | { on = "", run = 'shell --block -- neomutt -a "$@"', desc = "Attach files to email" }, 24 | 25 | ] 26 | -------------------------------------------------------------------------------- /config/yazi/plugins/folder-rules.yazi/main.lua: -------------------------------------------------------------------------------- 1 | local function setup() 2 | ps.sub('cd', function() 3 | local cwd = cx.active.current.cwd 4 | if cwd:ends_with 'Downloads' then 5 | ya.mgr_emit('sort', { 'mtime', reverse = true, dir_first = false }) 6 | else 7 | ya.mgr_emit('sort', { 'natural', reverse = false, dir_first = true }) 8 | end 9 | end) 10 | end 11 | 12 | return { setup = setup } 13 | -------------------------------------------------------------------------------- /config/yazi/plugins/reveal-in-finder.yazi/main.lua: -------------------------------------------------------------------------------- 1 | return { 2 | entry = function() 3 | local h = cx.active.current.hovered 4 | if h then 5 | local quoted_path = ya.quote(tostring(h.url)) 6 | if h.cha.is_dir then 7 | ya.manager_emit('shell', { 'open ' .. quoted_path, confirm = true }) 8 | else 9 | ya.manager_emit('shell', { 'open -R ' .. quoted_path, confirm = true }) 10 | end 11 | end 12 | end, 13 | } 14 | -------------------------------------------------------------------------------- /config/yazi/plugins/smart-paste.yazi/main.lua: -------------------------------------------------------------------------------- 1 | -- https://yazi-rs.github.io/docs/tips/#smart-paste 2 | --- @sync entry 3 | return { 4 | entry = function() 5 | local h = cx.active.current.hovered 6 | 7 | if h and h.cha.is_dir then 8 | ya.manager_emit('enter', {}) 9 | ya.manager_emit('paste', {}) 10 | ya.manager_emit('leave', {}) 11 | else 12 | ya.manager_emit('paste', {}) 13 | end 14 | end, 15 | } 16 | -------------------------------------------------------------------------------- /config/yazi/theme.toml: -------------------------------------------------------------------------------- 1 | [status] 2 | sep_left = { open = "", close = "" } 3 | sep_right = { open = "", close = "" } 4 | 5 | [mode] 6 | normal_main = { fg = "blue", bg = "233" } 7 | normal_alt = { fg = "blue", bg = "233" } 8 | 9 | select_main = { fg = "red", bg = "233" } 10 | select_alt = { fg = "red", bg = "233" } 11 | 12 | unset_main = { fg = "red", bg = "233" } 13 | unset_alt = { fg = "red", bg = "233" } 14 | -------------------------------------------------------------------------------- /config/yazi/yazi.toml: -------------------------------------------------------------------------------- 1 | "$schema" = "https://yazi-rs.github.io/schemas/yazi.json" 2 | 3 | [manager] 4 | linemode = "size" 5 | ratio = [0, 2, 6] 6 | sort_by = "natural" 7 | sort_dir_first = true 8 | show_hidden = true 9 | 10 | [preview] 11 | max_width = 3024 # default = 600 12 | max_height = 1964 # default = 900 13 | # https://yazi-rs.github.io/docs/tips#make-yazi-even-faster 14 | image_delay = 0 15 | 16 | [plugin] 17 | prepend_previewers = [{ name = "*.md", run = "glow" }] 18 | prepend_fetchers = [ 19 | { id = "git", name = "*", run = "git" }, 20 | { id = "git", name = "*/", run = "git" }, 21 | ] 22 | 23 | [opener] 24 | play = [ 25 | { run = 'mpv --force-window "$@"' }, 26 | { run = 'iina --no-stdin "$@"' }, 27 | { run = '''mediainfo "$1"; echo "Press enter to exit"; read''', block = true, desc = "Show media info" }, 28 | ] 29 | 30 | [open] 31 | prepend_rules = [ 32 | { name = "*.{ass,srt,ssa,sty,sup,vtt}", use = [ 33 | "subtitle", 34 | "edit", 35 | ] }, 36 | ] 37 | -------------------------------------------------------------------------------- /config/yt-dlp/config: -------------------------------------------------------------------------------- 1 | # vim:ft=conf 2 | --restrict-filenames 3 | # --format 'bestvideo' 4 | # --output '%(playlist)s/%(playlist_index)s-%(title)s.%(ext)s' 5 | --output '%(title)s.%(ext)s' 6 | -------------------------------------------------------------------------------- /config/zk/templates/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: '{{format-date now "timestamp"}}' 3 | title: '{{title}}' 4 | aliases: ['{{title}}'] 5 | date: '{{format-date now "%Y-%m-%dT%H:%M"}}' 6 | --- 7 | 8 | # {{title}} 9 | 10 | {{content}} 11 | -------------------------------------------------------------------------------- /config/zk/templates/journal.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: '{{format-date now "timestamp"}}' 3 | title: "{{format-date now '%Y-%m-%d'}}" 4 | aliases: ["{{format-date now '%Y-%m-%d'}}"] 5 | date: "{{format-date now '%Y-%m-%d'}}" 6 | tags: 7 | - journal 8 | --- 9 | 10 | # {{format-date now '%Y-%m-%d'}} 11 | 12 | ## Work 13 | 14 | {{content}} 15 | 16 | ## Personal 17 | -------------------------------------------------------------------------------- /config/zk/templates/personal.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: '{{format-date now "timestamp"}}' 3 | title: '{{title}}' 4 | aliases: ['{{title}}'] 5 | date: '{{format-date now "%Y-%m-%dT%H:%M"}}' 6 | tags: 7 | - personal 8 | --- 9 | 10 | # {{title}} 11 | 12 | {{content}} 13 | -------------------------------------------------------------------------------- /config/zk/templates/rfc.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: '{{format-date now "timestamp"}}' 3 | title: 'RFC - {{title}}' 4 | aliases: ['RFC - {{title}}'] 5 | date: '{{format-date now "%Y-%m-%dT%H:%M"}}' 6 | tags: 7 | - work 8 | - {{extra.employer}} 9 | - 'rfc 10 | - {{title}}' 11 | --- 12 | 13 | # [RFC] - {{title}} 14 | 15 | - **Author**: 16 | - **Created**: {{format-date now "long"}} 17 | - **Status**: WIP 18 | - **Current version**: 0.0.1 19 | - **Approvals**: 20 | 21 | **Summary** 22 | 23 | ## Background 24 | 25 | ## How it currently works 26 | 27 | ## Proposed solution 28 | 29 | ## Dependencies 30 | 31 | ## Risks 32 | -------------------------------------------------------------------------------- /config/zk/templates/til.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: '{{format-date now "timestamp"}}' 3 | title: '{{title}}' 4 | aliases: ['{{title}}'] 5 | date: '{{format-date now "%Y-%m-%dT%H:%M"}}' 6 | tags: 7 | - til 8 | --- 9 | 10 | # {{title}} 11 | 12 | {{content}} 13 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/.gitignore: -------------------------------------------------------------------------------- 1 | .zcompdump 2 | .zcompcache 3 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/.zshrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedelgabri/dotfiles/e7f65a22b13edaf42bd76522313db20239430985/config/zsh.d/zsh/.zshrc -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/+x: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ue -o pipefail 3 | exec chmod +x "$@" 4 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/bbd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ue -o pipefail 3 | # 4 | # [B]ranches [B]y [D]ate: List branches used in a specific date 5 | # 6 | # Usage: bbd "Sep 14" 7 | # bbd "Sep" 8 | 9 | git reflog --date=local | grep "${1-} .* checkout: moving from .* to" | grep -o "[a-zA-Z0-9\-]*$" | sort | uniq 10 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/bookmark: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | bookmark() { 5 | local url="${1:-}" 6 | local output_dir="${2:-$NOTES_DIR/saved-articles}" 7 | local file 8 | file="$(basename "$url")" 9 | 10 | pandoc \ 11 | --standalone "${url}" \ 12 | --from html-native_divs-native_spans-auto_identifiers+smart+gfm_auto_identifiers \ 13 | --to gfm-gfm_auto_identifiers+smart-raw_html \ 14 | --output "$output_dir/$file.saved.md" \ 15 | --metadata=source:"$url" \ 16 | --markdown-headings=atx \ 17 | --lua-filter="$DOTFILES/config/pandoc/bookmark.lua" 18 | } 19 | 20 | bookmark "$@" 21 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/changemac: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | # https://twitter.com/mgechev/status/1130441471105093632 4 | 5 | mac=$(openssl rand -hex 6 | sed 's/\(..\)/\1:/g; s/.$//') 6 | sudo ifconfig en0 ether "$mac" 7 | sudo ifconfig en0 down 8 | sudo ifconfig en0 up 9 | echo "Your new physical address is $mac" 10 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/colorgrid: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | iter=16 5 | while [ $iter -lt 52 ]; do 6 | second=$((iter + 36)) 7 | third=$((second + 36)) 8 | four=$((third + 36)) 9 | five=$((four + 36)) 10 | six=$((five + 36)) 11 | seven=$((six + 36)) 12 | # Bash doesn't have implicit arithmetic in `if`, use `((...))` 13 | if ((seven > 250)); then seven=$((seven - 251)); fi 14 | 15 | # Use printf for better formatting control and portability 16 | printf "\033[38;5;%sm█ %03d " "$iter" "$iter" 17 | printf "\033[38;5;%sm█ %03d " "$second" "$second" 18 | printf "\033[38;5;%sm█ %03d " "$third" "$third" 19 | printf "\033[38;5;%sm█ %03d " "$four" "$four" 20 | printf "\033[38;5;%sm█ %03d " "$five" "$five" 21 | printf "\033[38;5;%sm█ %03d " "$six" "$six" 22 | printf "\033[38;5;%sm█ %03d\033[0m\n" "$seven" "$seven" # Reset color at the end 23 | 24 | iter=$((iter + 1)) 25 | done 26 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/cpssh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | # Copy SSH key to your clipboard 4 | 5 | pbcopy <"$HOME/.ssh/$1.pub" 6 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/delta_: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | set -ue -o pipefail 3 | 4 | if [[ $COLUMNS -ge 120 ]]; then 5 | command delta -w "$COLUMNS" --diff-so-fancy --side-by-side --line-numbers-left-format "{nm:^4} " --line-numbers-right-format "{np:^4} " "$@" 6 | else 7 | command delta "$@" -w "$COLUMNS" --diff-so-fancy 8 | fi 9 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/dst: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | 4 | # Check daylight savings 5 | # https://superuser.com/a/805205/26670 6 | # 7 | # $ dst Europe/Amsterdam 8 | 9 | zdump -v "${1:-"Europe/Amsterdam"}" -c "$(date '+%Y')","$(date -d '+1 year' '+%Y')" | awk -v y="$(date '+%Y')" ' 10 | ($6==y && dst=="") {dst=$15} 11 | ($6==y && dst==$15) {ftime=$12; dst=$15;} 12 | ($6==y && dst!=$15) {print ftime, "to", $12, "on", $4, $3, $6, $15; dst=$15}' 13 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/exit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | # only exit if we're not on the last pane 4 | # https://github.com/fatih/dotfiles/blob/706e1d26a1b8526755bee92c8093ab61be077894/zshrc#L238-L254 5 | 6 | exit() { 7 | if [ -z "$TMUX" ]; then 8 | builtin exit 9 | return 10 | fi 11 | 12 | panes=$(tmux list-panes | wc -l) 13 | wins=$(tmux list-windows | wc -l) 14 | count=$((panes + wins - 1)) 15 | 16 | if [ $count -eq 1 ]; then 17 | tmux detach 18 | else 19 | builtin exit 20 | fi 21 | } 22 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/extract: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | 4 | # Extract most know archives with one command 5 | # http://alias.sh/extract-most-know-archives-one-command 6 | if [ -f "$1" ]; then 7 | case $1 in 8 | *.tar.bz2) tar xjf "$1" ;; 9 | *.tar.gz) tar xzf "$1" ;; 10 | *.bz2) bunzip2 "$1" ;; 11 | *.rar) unrar e "$1" ;; 12 | *.gz) gunzip "$1" ;; 13 | *.tar) tar xf "$1" ;; 14 | *.tbz2) tar xjf "$1" ;; 15 | *.tgz) tar xzf "$1" ;; 16 | *.zip) unzip "$1" ;; 17 | *.Z) uncompress "$1" ;; 18 | *.7z) 7z x "$1" ;; 19 | *) echo "'$1' cannot be extracted via extract()" ;; 20 | esac 21 | else 22 | echo "'$1' is not a valid file" 23 | fi 24 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/fco: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | # vim:ft=bash: 4 | # fco - checkout git branch/tag 5 | 6 | fco() { 7 | local tags branches target 8 | branches=$(git --no-pager branch --all \ 9 | --format="%(if)%(HEAD)%(then)%(else)%(if:equals=HEAD)%(refname:strip=3)%(then)%(else)%1B[0;34;1mbranch%09%1B[m%(refname:short)%(end)%(end)" | 10 | sed '/^$/d') || return 11 | tags=$(git --no-pager tag | awk '{print "\x1b[35;1mtag\x1b[m\t" $1}') || return 12 | target=$( 13 | ( 14 | echo "$branches" 15 | echo "$tags" 16 | ) | 17 | fzf --no-hscroll --reverse --no-multi -n 2 \ 18 | --ansi --preview="git --no-pager log -150 --oneline '..{2}'" 19 | ) || return 20 | git checkout "$(awk '{print $2}' <<<"$target")" 21 | } 22 | 23 | fco "$@" 24 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/fgd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | # fgd - delete git branch/tag 4 | 5 | fgd() { 6 | local tags branches target 7 | tags=$( 8 | git tag | awk '{print "\x1b[31;1mtag\x1b[m\t" $1}' 9 | ) || return 10 | branches=$( 11 | git branch --all | grep -v HEAD | 12 | sed "s/.* //" | sed "s#remotes/[^/]*/##" | 13 | sort -u | awk '{print "\x1b[34;1mbranch\x1b[m\t" $1}' 14 | ) || return 15 | target=$( 16 | ( 17 | echo "$tags" 18 | echo "$branches" 19 | ) | 20 | fzf --reverse --no-hscroll --ansi +m -d "\t" -n 2 21 | ) || return 22 | 23 | if [ "$(echo "$target" | awk '{print $1}')" = "tag" ]; then 24 | echo "$(echo "$target" | awk '{print $2}')" 25 | git tag -d "$(echo "$target" | awk '{print $2}')" 26 | fi 27 | 28 | if [ "$(echo "$target" | awk '{print $1}')" = "branch" ]; then 29 | echo "$(echo "$target" | awk '{print $2}')" 30 | git branch -D "$(echo "$target" | awk '{print $2}')" 31 | fi 32 | } 33 | 34 | fgd "$@" 35 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/find-exec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | # Finds files matching a pattern (arg1) and executes a command (arg2, default: file) on them. 4 | 5 | # Default pattern to empty string if $1 is not provided 6 | pattern="${1:-}" 7 | # Default command to 'file' if $2 is not provided 8 | command_to_exec="${2:-file}" 9 | 10 | # Use find -print0 and xargs -0 for safety with filenames containing special characters 11 | # Use "$pattern" to handle potential spaces or special chars in the pattern itself 12 | # Using -iname for case-insensitive search as in the original zsh function 13 | find . -type f -iname "*${pattern}*" -print0 | xargs -0 --no-run-if-empty "$command_to_exec" 14 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/flakify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | # Flakify the current directory 5 | 6 | # Check if Nix command exists 7 | if ! command -v nix &>/dev/null; then 8 | echo "Error: nix command not found. Please install Nix." 9 | exit 1 10 | fi 11 | 12 | if [ ! -e ./flake.nix ]; then 13 | echo "Creating flake.nix using nix-direnv template..." 14 | # This template contains .envrc file already 15 | nix flake new -t github:nix-community/nix-direnv . 16 | 17 | # Check if .envrc was created by the template 18 | if [ -e ./.envrc ]; then 19 | echo "Updating .envrc..." 20 | # Prepend standard lines and append dotenv_if_exists 21 | # Use a temporary file to avoid issues with reading and writing the same file 22 | tmp_envrc=$(mktemp) 23 | printf '%s\n' "set -e" "set +u" >"$tmp_envrc" 24 | cat .envrc >>"$tmp_envrc" 25 | printf '\n%s\n' "dotenv_if_exists" >>"$tmp_envrc" 26 | mv "$tmp_envrc" .envrc 27 | 28 | # Check if direnv command exists before running 29 | if command -v direnv &>/dev/null; then 30 | direnv allow 31 | else 32 | echo "Warning: direnv command not found. Please run 'direnv allow' manually." 33 | fi 34 | else 35 | echo "Warning: nix flake template did not create .envrc as expected." 36 | fi 37 | else 38 | echo "flake.nix already exists." 39 | fi 40 | 41 | # Open flake.nix and .envrc in editor 42 | # Use ${EDITOR:-vim} for safety if EDITOR is unset 43 | editor_cmd="${EDITOR:-vim}" 44 | echo "Opening flake.nix and .envrc in $editor_cmd..." 45 | if [ -e ./flake.nix ] && [ -e ./.envrc ]; then 46 | "$editor_cmd" flake.nix .envrc 47 | elif [ -e ./flake.nix ]; then 48 | "$editor_cmd" flake.nix 49 | elif [ -e ./.envrc ]; then 50 | "$editor_cmd" .envrc 51 | else 52 | echo "Neither flake.nix nor .envrc found to edit." 53 | fi 54 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/g: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ue -o pipefail 4 | 5 | # https://github.com/pengwynn/dotfiles/blob/master/git/git.zsh 6 | # Wrap git with hub 7 | 8 | command -v git >/dev/null || return 0 9 | 10 | time_since_last_commit() { 11 | local __LAST_COMMIT 12 | __LAST_COMMIT=$(git log --color=always -1 --pretty=format:"%C(238)%cr%Creset %C(blue)%h%Creset %s - %C(cyan)%aN %C(238)%(describe:tags,abbrev=0)%Creset" --date=auto:human 2>/dev/null) 13 | 14 | printf "%s\n" "$__LAST_COMMIT" 15 | } 16 | 17 | __CMD="" 18 | 19 | if command -v hub >/dev/null 2>&1; then 20 | __CMD=$(command -v hub) 21 | elif command -v git >/dev/null 2>&1; then 22 | __CMD=$(command -v git) 23 | fi 24 | 25 | [[ $__CMD != "" ]] || return 26 | 27 | if [ $# -eq 0 ]; then 28 | printf "%s\n\n" "$(time_since_last_commit)" 29 | "$__CMD" st 2>/dev/null || "$__CMD" status --short --branch 30 | else 31 | "$__CMD" "$@" 32 | fi 33 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/get-keychain-pass: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ue -o pipefail 3 | 4 | if [ $# -ne 2 ]; then 5 | echo "Usage: $0 ACCOUNT SERVER" 6 | exit 1 7 | fi 8 | ACCOUNT="$1" 9 | SERVER="$2" 10 | KEYCHAIN="$HOME/Library/Keychains/login.keychain" 11 | PASSAGE_SOCK="$HOME/.passage.sock" 12 | 13 | if [ -S "$PASSAGE_SOCK" ]; then 14 | # [TODO]: consider validating this as valid JSON 15 | echo "{\"service\":\"$SERVER\",\"account\":\"$ACCOUNT\"}" | nc -U "$PASSAGE_SOCK" 16 | echo # For parity with `security`, which prints a newline. 17 | else 18 | security find-generic-password -w -a "$ACCOUNT" -s "$SERVER" "$KEYCHAIN" 19 | fi 20 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-author-stats: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ue -o pipefail 3 | 4 | if [[ "$1" == '--raw' ]]; then 5 | RAW=1 6 | shift 7 | fi 8 | 9 | author=$1 10 | shift 11 | if [[ -z "$author" || "$author" == "--help" || "$author" == "-h" ]]; then 12 | echo "Usage: git author-stats [extra git log params]" 13 | echo "Example: git author-stats $USER --since=2017-01-01 --until=2017-01-31" 14 | exit 15 | fi 16 | 17 | git log --author="$author" --pretty=tformat: --numstat "$@" | awk -v RAW=$RAW '{ 18 | added += $1; 19 | removed += $2; 20 | modified += $1 - -$2; 21 | total += $1 - $2; 22 | } END { 23 | if (RAW) 24 | printf "%s %s %s %s", added, removed, total, modified 25 | else 26 | printf "Added: %s, removed: %s, total: %s, modified: %s lines\n", added, removed, total, modified 27 | }' 28 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-conflicts: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ue -o pipefail 3 | # Usage: git-conflicts 4 | # Show list of files in a conflict state. 5 | git diff --name-only --diff-filter=U 6 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-continue: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | # Runs `git rebase --continue`, `git cherry-pick --continue` as appropriate, 5 | # based on context. 6 | # 7 | # Based on: https://stackoverflow.com/a/53370600 8 | 9 | GIT_DIR=$(git rev-parse --git-dir) 10 | 11 | if [ $? -ne 0 ]; then 12 | exit $? 13 | fi 14 | 15 | if [ -d "${GIT_DIR}/rebase-merge" ]; then 16 | git rebase --continue 17 | elif [ -d "${GIT_DIR}/rebase-apply" ]; then 18 | git rebase --continue 19 | elif [ -f "${GIT_DIR}/MERGE_HEAD" ]; then 20 | git merge --continue 21 | elif [ -f "${GIT_DIR}/CHERRY_PICK_HEAD" ]; then 22 | git cherry-pick --continue 23 | elif [ -f "${GIT_DIR}/REVERT_HEAD" ]; then 24 | git revert --continue 25 | else 26 | echo "error: No operation to --continue" 27 | exit 1 28 | fi 29 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-contributors: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ue -o pipefail 3 | # Usage: git-contributors 4 | # Show list of contributors sorted by line count 5 | 6 | git --no-pager shortlog -s -n 7 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-credit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ue -o pipefail 3 | # 4 | # A very slightly quicker way to credit an author on the latest commit. 5 | # 6 | # $1 - The full name of the author. 7 | # $2 - The email address of the author. 8 | # 9 | # Examples 10 | # 11 | # git credit "Zach Holman" zach@example.com 12 | # 13 | 14 | git commit --amend --author "$1 <$2>" -C HEAD 15 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-edit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | # Usage: git-edit [conflicted|staged|edited|committed] 4 | 5 | case ${1-} in 6 | conflict | conflicts | conflicted) 7 | $EDITOR $(git-conflicts) 8 | ;; 9 | committed) 10 | $EDITOR $(git diff HEAD^ --name-only --diff-filter=ACMR) 11 | ;; 12 | staged) 13 | $EDITOR $(git diff --staged --name-only --diff-filter=ACMR) 14 | ;; 15 | status) 16 | $EDITOR $(git status --porcelain | awk '{print $2}') 17 | ;; 18 | edited) 19 | $EDITOR $(git diff HEAD --name-only --diff-filter=ACMR) 20 | ;; 21 | esac 22 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-exclude: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ue -o pipefail 3 | 4 | mkdir -p .git/info 5 | for pattern in "$@" 6 | do 7 | echo "$pattern" >> .git/info/exclude 8 | done 9 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-ignore: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | # Usage: $ git ignore 4 | 5 | if [ ! -f ".gitignore" ]; then 6 | touch .gitignore 7 | fi 8 | 9 | echo "$1" >>.gitignore 10 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-mirrors: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | add_mirrors() { 5 | local REMOTE_URL 6 | REMOTE_URL=$(git config --get remote.origin.url) 7 | 8 | local REMOTE_REPO 9 | REMOTE_REPO=$(basename -s .git "$REMOTE_URL") 10 | 11 | local REPO=${REMOTE_REPO:-$1} 12 | 13 | if [ -z "$REPO" ]; then 14 | echo "Can't get the proper git repo name, you have to pass one" 15 | exit 1 16 | fi 17 | 18 | local MIRROS=("bitbucket" "gitlab") 19 | 20 | git remote set-url --add --push origin "$REMOTE_URL" 21 | 22 | for mirror in "${MIRROS[@]}"; do 23 | git remote set-url --add --push origin "git@$mirror.com:${GITHUB_USER:-ahmedelgabri}/${REPO}.git" 24 | done 25 | 26 | echo "--------------------------------------------------------" 27 | echo "${MIRROS[*]} were added as push tagrets to origin remote" 28 | echo "--------------------------------------------------------" 29 | git remote --verbose 30 | } 31 | 32 | add_mirrors "$@" 33 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-rank: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ue -o pipefail 3 | 4 | R='\x1b[31;01m' 5 | G='\x1b[32;01m' 6 | Y='\x1b[33;01m' 7 | B='\x1b[34;01m' 8 | P='\x1b[35;01m' 9 | G='\x1b[90;01m' 10 | Z='\x1b[0m' 11 | 12 | printf "\n%-40s %9s %9s %9s %9s %9s\n" AUTHOR COMMITS ADDED REMOVED TOTAL MODIFIED 13 | 14 | git shortlog -s -n | while read -r commits name; do 15 | read -r added removed total modified < <(git author-stats --raw "$name") 16 | if type iconv >/dev/null 2>&1; then 17 | name=$(echo "$name" | iconv -f utf-8 -t ascii//translit) 18 | fi 19 | printf "%-40s %9s $G%9s $R%9s $Y%9s $B%9s$Z\n" "$name" "$commits" "$added" "$removed" "$total" "$modified" 20 | done 21 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-recent: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ue -o pipefail 3 | # https://github.com/paulirish/git-recent 4 | 5 | ## 6 | ## git-recent 7 | ## 8 | ## list all local branches, sorted by last commit, formatted reall purdy 9 | ## 10 | 11 | # Windows needs more basic format (#8, git-for-windows/git#865) 12 | case $(uname -s) in 13 | CYGWIN* | MINGW* | MSYS*) 14 | branch='%(refname:short)' 15 | spacer=' ' 16 | ;; 17 | *) 18 | branch='%(color:yellow)%(refname:short)%(color:reset)' 19 | spacer='%(color:black) %(color:reset)' 20 | ;; 21 | esac 22 | 23 | COUNT=0 24 | while getopts "n:" opt; do 25 | case ${opt} in 26 | n) 27 | if ! [[ $OPTARG =~ ^[0-9]{1,}$ ]]; then 28 | echo "-n should be an integer." 29 | exit 1 30 | fi 31 | COUNT=${OPTARG} 32 | shift 33 | ;; 34 | esac 35 | done 36 | shift $((OPTIND - 1)) 37 | 38 | format="\ 39 | %(HEAD) \ 40 | $branch|\ 41 | %(color:bold red)%(objectname:short)%(color:reset) \ 42 | %(color:bold green)(%(committerdate:relative))%(color:reset) \ 43 | %(color:bold blue)%(authorname)%(color:reset) \ 44 | %(color:yellow)%(upstream:track)%(color:reset) 45 | $spacer|\ 46 | %(contents:subject) 47 | $spacer|" 48 | 49 | lessopts="--tabs=4 --quit-if-one-screen --RAW-CONTROL-CHARS --no-init" 50 | 51 | git for-each-ref \ 52 | --color=always \ 53 | --count=$COUNT \ 54 | --sort=-committerdate \ 55 | "refs/heads/" \ 56 | --format="$format" | 57 | column -ts '|' | 58 | less "$lessopts" 59 | 60 | # The above command: 61 | # for all known branches, 62 | # (force coloring on this, especially since it's being piped) 63 | # optionally, specify the number of branches you want to display 64 | # sort descending by last commit 65 | # show local branches (change to "" to include both local + remote branches) 66 | # apply the formatting template above 67 | # break into columns 68 | # use the pager only if there's not enough space 69 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-rel: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | # Usage: git-rel [] 4 | # Shows the relationship between the current branch and . With no , 5 | # the current branch's remote tracking branch is used. 6 | # 7 | # Examples: 8 | # 9 | # $ git-rel 10 | # 15 ahead 11 | # 11 behind 12 | # 13 | # $ git-rel v1.1 14 | # 230 ahead 15 | 16 | strip_prefix() { 17 | echo "$@" | 18 | sed 's@refs/heads/@@' 19 | } 20 | 21 | current_branch() { 22 | git symbolic-ref -q HEAD | 23 | sed 's@refs/heads/@@' 24 | } 25 | 26 | tracking_branch() { 27 | remote=$(git config --get branch."$(current_branch)".remote) 28 | merge=$(git config --get branch."$(current_branch)".merge) 29 | echo "$remote/$(strip_prefix "$merge")" 30 | } 31 | 32 | ref="${1:-$(tracking_branch)}" 33 | 34 | git rev-list --left-right --abbrev-commit --abbrev "$ref"...HEAD | 35 | cut -c1 | 36 | sort | 37 | uniq -c | 38 | tr '\n' ',' | 39 | sed " 40 | s/>/ahead/ 41 | s/.. 4 | # 5 | # All commits on master, ever: 6 | # git-thanks master 7 | # 8 | # All commits on master since the 0.9.0 tag: 9 | # git-thanks 0.9.0..master 10 | 11 | git log "$1" | 12 | grep Author: | 13 | sed 's/Author: \(.*\) <.*/\1/' | 14 | sort | 15 | uniq -c | 16 | sort -rn | 17 | sed 's/ *\([0-9]\{1,\}\) \(.*\)/\2 (\1)/' 18 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-undopush: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ue -o pipefail 3 | 4 | if [ -n "$1" ]; then 5 | BRANCH="$1" 6 | else 7 | BRANCH="$(git rev-parse --abbrev-ref HEAD)" 8 | fi 9 | 10 | git push -f origin HEAD^:"$BRANCH" 11 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/git-wt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | CMD="git" 5 | if [[ -n "${DEUBG-}" ]]; then 6 | set -x 7 | 8 | CMD="echo git" 9 | fi 10 | 11 | get_worktree_branch() { 12 | # We get grep for the worktree name, then we extract the branch name from the result 13 | # Because a worktree name is not always the branch name 14 | git worktree list | grep "${1-}" | sed -E 's/.*\s+[a-zA-Z0-9]+\s\[(.*)\]/\1/g' 15 | } 16 | 17 | case $1 in 18 | # This is an extra command that I added to handle cloning a repo and setting it 19 | # up as a worktree 20 | clone) 21 | shift 22 | FOLDER_NAME=${2:-$(basename "$1" ".git")} 23 | 24 | mkdir -p "$FOLDER_NAME" 25 | 26 | cd "$FOLDER_NAME" 27 | 28 | $CMD clone --bare "$1" .bare 29 | 30 | echo "gitdir: ./.bare" >.git 31 | 32 | $CMD config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" 33 | 34 | $CMD fetch --all 35 | ;; 36 | add) 37 | shift 38 | $CMD worktree add "$@" 39 | # Do I need to handle this? 40 | # git worktree add -b origin/ahmed/foo foo 41 | # $CMD branch --set-upstream-to=origin/"$branch" "$branch" 42 | 43 | $CMD fetch --all --prune 44 | ;; 45 | remove | rm) 46 | shift 47 | 48 | if [[ -z "${1-}" ]]; then 49 | git worktree list | grep -v ".bare" | fzf \ 50 | --header $'CTRL-X (remove worktree)\n\n' \ 51 | --bind 'enter:become(git worktree remove -f {1} && git branch -D $(echo {3} | sed -E "s/\[(.*)\]/\1/g"))' \ 52 | --bind 'ctrl-x:reload(git worktree remove -f {1} && git branch -D $(echo {3} | sed -E "s/\[(.*)\]/\1/g"); git worktree list)' \ 53 | --preview " 54 | git -c color.status=always -C {1} status --short --branch 55 | echo 56 | git log --oneline --graph --date=short --color=always --pretty='format:%C(auto)%cd %h%d %s' {2} -- 57 | " 58 | fi 59 | 60 | BRANCH_TO_DELETE=$(get_worktree_branch "$1") 61 | 62 | $CMD worktree remove -f "$1" 63 | $CMD branch -D "$BRANCH_TO_DELETE" 64 | ;; 65 | # Same as remove, but this time we also delete the branch from remote 66 | destroy) 67 | shift 68 | 69 | printf "Are you sure you want to destroy %s? [y/N]: " "$1" 70 | read -r CONFIRMATION 71 | 72 | if [[ "$CONFIRMATION" != "y" ]]; then 73 | exit 1 74 | fi 75 | 76 | BRANCH_TO_DELETE=$(get_worktree_branch "$1") 77 | 78 | $CMD worktree remove -f "$1" 79 | $CMD branch -D "$BRANCH_TO_DELETE" 80 | $CMD push origin --delete "$BRANCH_TO_DELETE" 81 | ;; 82 | list | lock | unlock | move | prune | repair) 83 | $CMD worktree "$@" 84 | ;; 85 | 86 | help | --help) 87 | $CMD worktree --help 88 | echo "--------------------------" 89 | cat <<-EOF 90 | git-wt clone 91 | EOF 92 | ;; 93 | *) 94 | # Let git worktree handle the errors 95 | $CMD worktree "$@" 96 | ;; 97 | esac 98 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/killport: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | # Kills all processes running on the specified port (e.g. 'killport 8080') 4 | 5 | lsof -i tcp:"$1" | awk '(NR!=1) && ($1!="Google") && ($1!="firefox") {print $2}' | xargs kill 6 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/l: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | if command -v eza >/dev/null 2>&1; then 5 | eza --all --long --color-scale=all --group-directories-first --sort=type --hyperlink --icons=auto --octal-permissions "$@" 6 | elif [[ -x "/run/current-system/sw/bin/ls" ]]; then 7 | # https://github.com/paulirish/dotfiles/blob/7c46f8c25015c2632894dbe5fea20014ab37fd89/.functions#L14-L25 8 | # [TODO]: Check why this is not picked up from $PATH? 9 | /run/current-system/sw/bin/ls --almost-all -l --human-readable --classify --group-directories-first --color=auto --hyperlink=auto "$@" | awk ' 10 | { 11 | k=0; 12 | for (i=0;i<=8;i++) 13 | k+=((substr($1,i+2,1)~/[rwx]/) *2^(8-i)); 14 | if (k) 15 | printf("%0o ",k); 16 | printf(" %9s %3s %2s %5s %6s %s %s %s\n", $3, $6, $7, $8, $5, $9,$10, $11); 17 | }' 18 | else 19 | # List all files, long format, colorized, permissions in octal 20 | ls -l "$@" | awk ' 21 | { 22 | k=0; 23 | for (i=0;i<=8;i++) 24 | k+=((substr($1,i+2,1)~/[rwx]/) *2^(8-i)); 25 | if (k) 26 | printf("%0o ",k); 27 | printf(" %9s %3s %2s %5s %6s %s %s %s\n", $3, $6, $7, $8, $5, $9,$10, $11); 28 | }' 29 | fi 30 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/mkcd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | # 4 | if [[ -n ${1-} ]]; then 5 | mkdir -p -- "${1}" && (builtin cd -- "${1}" || exit) 6 | else 7 | exit 1 8 | fi 9 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/mkssh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | # Create and copy SSH key using Ed25519 to your clipboard 4 | # author: @ahmedelgabri 5 | # version: 2.0.0 6 | # $1 = keyname 7 | # $2 = Email ID used 8 | 9 | mkssh() { 10 | NAME=${1:-id_rsa} 11 | 12 | ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/"$NAME" -C "$2" 13 | pbcopy <"$HOME"/.ssh/"$NAME".pub 14 | echo "------------------------------------------------------------" 15 | echo "($NAME.pub) has been created & copied to your clipboard" 16 | echo "------------------------------------------------------------" 17 | } 18 | 19 | mkssh "$@" 20 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/mx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # mx 4 | # version 1.1 5 | 6 | # Contributors: 7 | # Wynn Netherland - http://github.com/pengwynn 8 | # Adam Jahnke - http://github.com/adamyonk 9 | # Yoshua Wuyts - https://github.com/yoshuawuyts 10 | # Ahmed El Gabri - https://github.com/ahmedelgabri 11 | 12 | # Usage: 13 | # mx [session] [subdirectory (optional)] 14 | 15 | # To 'auto-launch' projects, you'll need a $PROJECTS dir where you keep code 16 | # sorted like so: $PROJECTS//. 17 | # So, a typical workflow would look like: 18 | # $ hub clone pengwynn/octonaut $PROJECTS/pengwynn/octonaut 19 | # $ mx octonaut 20 | 21 | # If `mx` is called with a name, and there is no valid repo inside 22 | # $PROJECTS, a new tmux session will be initialized in the current working 23 | # directory with a name of 24 | 25 | set -ue -o pipefail 26 | 27 | if [[ -n "${DEBUG-}" ]]; then 28 | set -x 29 | fi 30 | 31 | MX_START=${MX_START:-"./.mx-start"} 32 | 33 | get_session() { 34 | echo "$1" | awk -F"/" '{print $NF}' 35 | } 36 | 37 | SESSION="$(get_session "${1:-$(pwd)}")" 38 | # tmux 1.9a+ doesn't like .'s in session names 39 | TMUX_SESSION_NAME="${SESSION//./_}" 40 | 41 | if ! (tmux has-session -t "$SESSION" &>/dev/null); then 42 | mx-init 43 | 44 | WORKINGDIR="" 45 | 46 | if [ -d "$WORK/$SESSION/${2-}" ]; then 47 | WORKINGDIR="$WORK/$SESSION/$2" 48 | elif [ -d "$WORK/$SESSION" ]; then 49 | WORKINGDIR="$WORK/$SESSION" 50 | elif [ -d "$PROJECTS/$SESSION" ]; then 51 | WORKINGDIR="$PROJECTS/$SESSION" 52 | else 53 | WORKINGDIR="$PWD" 54 | fi 55 | 56 | if [ -n "$WORKINGDIR" ]; then 57 | cd "$WORKINGDIR" 58 | tmux new-session -d -s "$TMUX_SESSION_NAME" 59 | tmux select-window -t "$TMUX_SESSION_NAME" 60 | # Sometimes I need to setup some project specific stuff & run some commands 61 | if [ -x "$MX_START" ]; then 62 | tmux send-keys "$MX_START" C-m 63 | fi 64 | fi 65 | 66 | if tmux has-session -t _shared:mail 2>/dev/null; then 67 | tmux link-window -s _shared:mail -t 6 68 | fi 69 | 70 | if tmux has-session -t _shared:rss 2>/dev/null; then 71 | tmux link-window -s _shared:rss -t 7 72 | fi 73 | 74 | if tmux has-session -t _shared:dotfiles 2>/dev/null; then 75 | tmux link-window -s _shared:dotfiles -t 8 76 | fi 77 | 78 | if tmux has-session -t _shared:notes 2>/dev/null; then 79 | tmux link-window -s _shared:notes -t 9 80 | fi 81 | 82 | if tmux has-session -t _shared:reddit 2>/dev/null; then 83 | tmux link-window -s _shared:reddit -t 10 84 | fi 85 | 86 | if tmux has-session -t _shared:weechat 2>/dev/null; then 87 | tmux link-window -s _shared:weechat -t 11 88 | fi 89 | tmux select-window -t 1 90 | fi 91 | 92 | if [ -z "${TMUX-}" ]; then 93 | tmux attach -t "$TMUX_SESSION_NAME" 94 | else 95 | tmux switch-client -t "$TMUX_SESSION_NAME" 96 | fi 97 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/mx-init: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | if [[ -n "${DEBUG-}" ]]; then 5 | set -x 6 | fi 7 | 8 | SESSION='_shared' 9 | 10 | create_session() { 11 | tmux new-session -d -s "$SESSION" 12 | 13 | if 14 | command -v neomutt &>/dev/null 15 | then 16 | tmux new-window -n 'mail' 17 | # https://github.com/neomutt/neomutt/issues/4058#issuecomment-1751682305 18 | tmux send-keys "TERM=xterm-direct neomutt" C-m 19 | fi 20 | 21 | if 22 | command -v newsboat &>/dev/null 23 | then 24 | tmux new-window -n 'rss' 25 | tmux send-keys "newsboat" C-m 26 | fi 27 | 28 | if command -v weechat &>/dev/null; then 29 | tmux new-window -n 'weechat' 30 | # Stop Weechat from renaming the window 31 | tmux set-option allow-rename off 32 | tmux send-keys "weechat" C-m 33 | fi 34 | 35 | if [ -d "${NOTES_DIR-}" ]; then 36 | tmux new-window -n 'notes' -c "$NOTES_DIR" 37 | tmux send-keys "$EDITOR" C-m 38 | fi 39 | 40 | if [ -d "${DOTFILES-}" ]; then 41 | tmux new-window -n 'dotfiles' -c "$DOTFILES" 42 | tmux send-keys "$EDITOR" C-m 43 | tmux split-window -h -l 15% -c "$DOTFILES" 44 | fi 45 | } 46 | 47 | if ! (tmux list-sessions | cut -d ':' -f 1 | grep -q ^"$SESSION"\$); then 48 | create_session 49 | fi 50 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/nixify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | # Nixify the current directory 5 | 6 | # Check for .envrc file 7 | if [ ! -e ./.envrc ]; then 8 | echo "Creating default .envrc..." 9 | # Use printf for potentially better handling of special characters and portability 10 | printf '%s\n' "set -e" "set +u" "use nix" "dotenv_if_exists" >.envrc 11 | # Check if direnv command exists before running 12 | if command -v direnv &>/dev/null; then 13 | direnv allow 14 | else 15 | echo "Warning: direnv command not found. Please run 'direnv allow' manually." 16 | fi 17 | fi 18 | 19 | # Check for Nix configuration files 20 | if [[ ! -e shell.nix ]] && [[ ! -e default.nix ]] && [[ ! -e flake.nix ]]; then 21 | echo "Creating default shell.nix..." 22 | # Make a default shell.nix and then pop open an editor 23 | cat >shell.nix <<'EOF' 24 | with import { 25 | config.allowUnfree = true; 26 | }; 27 | let 28 | projectPathList = builtins.split "/" (builtins.toString ./.); 29 | projectName = builtins.elemAt projectPathList (builtins.length projectPathList - 1); 30 | # Grab node version from .nvmrc file if exits otherwise fallback to latest node 31 | nodeVersion = 32 | if builtins.pathExists ./.nvmrc then 33 | builtins.concatStringsSep 34 | "_" [ 35 | "nodejs" 36 | (builtins.head (builtins.splitVersion (builtins.readFile 37 | ./.nvmrc))) 38 | ] else "nodejs"; 39 | 40 | packageManager = 41 | if builtins.pathExists ./yarn.lock then 42 | pkgs.yarn else 43 | if builtins.pathExists ./pnpm-lock.yaml then 44 | nodePackages.pnpm 45 | else ""; 46 | in 47 | mkShell { 48 | name = projectName; 49 | buildInputs = with pkgs; [ 50 | pkgs.${nodeVersion} 51 | packageManager 52 | ]; 53 | } 54 | EOF 55 | # Use ${EDITOR:-vim} for safety if EDITOR is unset 56 | if [[ -n "$EDITOR" ]]; then 57 | "$EDITOR" shell.nix 58 | else 59 | vim shell.nix 60 | fi 61 | else 62 | echo "Nix configuration file (shell.nix, default.nix, or flake.nix) already exists." 63 | fi 64 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/nyan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | e='\033' 5 | RESET="$e[0m" 6 | BOLD="$e[1m" 7 | CYAN="$e[0;96m" 8 | RED="$e[0;91m" 9 | YELLOW="$e[0;93m" 10 | GREEN="$e[0;92m" 11 | 12 | if [ "$1" = "-alt" ]; then 13 | echo -en $RED'`·.,¸,.·*·.' 14 | echo -e $RESET$BOLD'╭━━━━╮'$RESET 15 | echo -en $YELLOW'`·.,¸,.·*·.' 16 | echo -e $RESET$BOLD'|::: /\_/\\'$RESET 17 | echo -en $GREEN'`·.,¸,.·*·.' 18 | echo -e $RESET$BOLD'|:::( ◕ᴥ◕)'$RESET 19 | echo -en $CYAN'`·.,¸,.·*·.' 20 | echo -e $RESET$BOLD'u-u━━-u--u'$RESET 21 | else 22 | echo -en $RED'-_-_-_-_-_-_-_' 23 | echo -e $RESET$BOLD',------,'$RESET 24 | echo -en $YELLOW'_-_-_-_-_-_-_-' 25 | echo -e $RESET$BOLD'| /\_/\\'$RESET 26 | echo -en $GREEN'-_-_-_-_-_-_-' 27 | echo -e $RESET$BOLD'~|__( ^ .^)'$RESET 28 | echo -en $CYAN'-_-_-_-_-_-_-' 29 | echo -e $RESET$BOLD'"" ""'$RESET 30 | fi 31 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/o: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | # No arguments: `open .` 5 | # With arguments: acts like `open` 6 | 7 | if [[ $# -eq 0 ]]; then 8 | open . 9 | else 10 | open "$@" 11 | fi 12 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/octocat: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ue -o pipefail 3 | 4 | curl https://api.github.com/octocat?s="$1" 5 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/osx-ls-download-history: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | function osx-ls-download-history { 5 | local db 6 | for db in ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV*; do 7 | # Check if the database file exists and is readable before proceeding 8 | if [[ -r "$db" ]]; then 9 | # Check if the table exists using .schema instead of .tables for better compatibility/clarity 10 | if sqlite3 "$db" ".schema LSQuarantineEvent" 2>/dev/null | grep -q 'CREATE TABLE'; then 11 | sqlite3 "$db" 'SELECT LSQuarantineDataURLString FROM LSQuarantineEvent' 12 | fi 13 | fi 14 | done 15 | } 16 | 17 | osx-ls-download-history "$@" 18 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/osx-rm-download-history: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | function osx-rm-download-history { 5 | local db 6 | for db in ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV*; do 7 | # Check if the database file exists and is readable before proceeding 8 | if [[ -r "$db" ]]; then 9 | # Check if the table exists using .schema instead of .tables for better compatibility/clarity 10 | if sqlite3 "$db" ".schema LSQuarantineEvent" 2>/dev/null | grep -q 'CREATE TABLE'; then 11 | echo "Clearing history in $db" 12 | sqlite3 "$db" 'DELETE FROM LSQuarantineEvent; VACUUM;' 13 | fi 14 | fi 15 | done 16 | } 17 | 18 | osx-rm-download-history "$@" 19 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/previewer: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | FILE="$1" 5 | WIDTH="$FZF_PREVIEW_COLUMNS" 6 | HEIGHT="$FZF_PREVIEW_LINES" 7 | X="$FZF_PREVIEW_TOP" 8 | Y="$FZF_PREVIEW_LEFT" 9 | 10 | if [ -n "${DEBUG-}" ]; then 11 | echo "FILE: $FILE WIDTH: $WIDTH HEIGHT: $HEIGHT X: $X Y: $Y" 12 | fi 13 | 14 | case $(file --brief --mime-type "$FILE") in 15 | image/*) 16 | kitty icat --clear --transfer-mode=memory --stdin=no --place="${WIDTH}x${HEIGHT}@${X}x${Y}" "$FILE" 17 | ;; 18 | text/troff) 19 | man ./ "$1" | col -b 20 | ;; 21 | text/* | */xml | application/json | application/javascript) 22 | if [[ $FILE == *.md ]]; then 23 | # Need `-s dark` to force color outside of interactive shell: 24 | # https://github.com/charmbracelet/glow/issues/440 25 | glow -s dark --width "$WIDTH" "$FILE" 26 | else 27 | bat --style=plain,changes --terminal-width "$WIDTH" --wrap never --color always "$FILE" 28 | fi 29 | ;; 30 | application/pdf) 31 | file_name=$(basename "$FILE" .pdf) 32 | temp_image="$TMPDIR/$file_name.png" 33 | 34 | if [ ! -e "$temp_image" ]; then 35 | # Convert the first page of the PDF to an image 36 | magick "$FILE[0]" -thumbnail x300 "$temp_image" 37 | fi 38 | 39 | # Display the image and text side by side 40 | kitty icat --clear --transfer-mode=memory --stdin=no --align=left "$temp_image" 41 | 42 | padding=$(identify -format "%w" "$temp_image") 43 | padding=$(awk -v n="$padding" 'BEGIN{print int(n/10)}') 44 | 45 | # Extract the first 100 lines of text from the PDF 46 | pdftotext "$FILE" - 2>/dev/null | head -100 | pr -T -o "$padding" 47 | ;; 48 | application/zip) 49 | unzip -l "$FILE" 50 | ;; 51 | application/x-tar | application/gzip) 52 | tar tf "$FILE" 53 | ;; 54 | inode/directory) 55 | eza --color=always --tree --group-directories-first "$FILE" 56 | ;; 57 | *) 58 | file --brief "$FILE" 59 | ;; 60 | esac 61 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/psu: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | # Displays user owned processes status. 4 | 5 | ps -U "${1:-$LOGNAME}" -o 'pid,%cpu,%mem,command' "${@:2}" 6 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/serve: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | # Usage: serve [--directory DIRECTORY] [PORT] 5 | # 6 | # Defaults to port 8000, current directory (ie. will use index.html if present). 7 | 8 | if command -v python3 &>/dev/null; then 9 | python3 -m http.server "$@" 10 | else 11 | python -m SimpleHTTPServer "$@" || python -m http.server "$@" 12 | fi 13 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/ssht: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | # ssh & attach to a TMUX session or create a new one 4 | 5 | ssh "$@" -t "tmux attach || tmux new" 6 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/sys: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | sw_vers 5 | echo 6 | system_profiler SPSoftwareDataType 7 | curl -s https://en.wikipedia.org/wiki/MacOS_version_history | grep -Eo "Version $(version=$(sw_vers -productVersion) && echo ${version%.*}): \"[^\s]+\"" | uniq 8 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/terminal-test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -ue -o pipefail 3 | # Test truecolor support in a terminal emulator 4 | # from https://gist.github.com/XVilka/8346728 5 | 6 | awk 'BEGIN{ 7 | s="/\\/\\/\\/\\/\\"; s=s s s s s s s s; 8 | for (colnum = 0; colnum<77; colnum++) { 9 | r = 255-(colnum*255/76); 10 | g = (colnum*510/76); 11 | b = (colnum*255/76); 12 | if (g>255) g = 510-g; 13 | printf "\033[48;2;%d;%d;%dm", r,g,b; 14 | printf "\033[38;2;%d;%d;%dm", 255-r,255-g,255-b; 15 | printf "%s\033[0m", substr(s,colnum+1,1); 16 | } 17 | printf "\n"; 18 | }' 19 | 20 | echo 21 | 22 | echo "# text decorations" 23 | printf '\e[1mbold\e[22m\n' 24 | printf '\e[2mdim\e[22m\n' 25 | printf '\e[3mitalic\e[23m\n' 26 | printf '\e[4munderline\e[24m\n' 27 | printf '\e[4:1mthis is also underline\e[24m\n' 28 | printf '\e[21mdouble underline\e[24m\n' 29 | printf '\e[4:2mthis is also double underline\e[24m\n' 30 | printf '\e[4:3mcurly underline\e[24m\n' 31 | printf '\e[58;5;10;4mcolored underline\e[59;24m\n' 32 | printf '\e[5mblink\e[25m\n' 33 | printf '\e[7mreverse\e[27m\n' 34 | printf '\e[8minvisible\e[28m <- invisible (but copy-pasteable)\n' 35 | printf '\e[9mstrikethrough\e[29m\n' 36 | printf '\e[53moverline\e[55m\n' 37 | echo 38 | 39 | echo "# magic string (see https://en.wikipedia.org/wiki/Unicode#Web)" 40 | echo "é Δ Й ק م ๗ あ 叶 葉 말" 41 | echo 42 | 43 | echo "# emojis" 44 | echo "😃😱😵" 45 | echo 46 | 47 | echo "# right-to-left ('ا' symbol should be at right side)" 48 | echo "ا ب ت" 49 | echo 50 | 51 | echo "# sixel graphics" 52 | printf '\eP0;0;0q"1;1;64;64#0;2;0;0;0#1;2;100;100;100#1~{wo_!11?@FN^!34~^NB 53 | @?_ow{~$#0?BFN^!11~}wo_!34?_o{}~^NFB-#1!5~}{o_!12?BF^!25~^NB@??ow{!6~$#0!5? 54 | @BN^!12~{w_!25?_o{}~~NFB-#1!10~}w_!12?@BN^!15~^NFB@?_w{}!10~$#0!10?@F^!12~} 55 | {o_!15?_ow{}~^FB@-#1!14~}{o_!11?@BF^!7~^FB??_ow}!15~$#0!14?@BN^!11~}{w_!7?_ 56 | w{~~^NF@-#1!18~}{wo!11?_r^FB@??ow}!20~$#0!18?@BFN!11~^K_w{}~~NF@-#1!23~M!4? 57 | _oWMF@!6?BN^!21~$#0!23?p!4~^Nfpw}!6~{o_-#1!18~^NB@?_ow{}~wo!12?@BFN!17~$#0! 58 | 18?_o{}~^NFB@?FN!12~}{wo-#1!13~^NB@??_w{}!9~}{w_!12?BFN^!12~$#0!13?_o{}~~^F 59 | B@!9?@BF^!12~{wo_-#1!8~^NFB@?_w{}!19~{wo_!11?@BN^!8~$#0!8?_ow{}~^FB@!19?BFN 60 | ^!11~}{o_-#1!4~^NB@?_ow{!28~}{o_!12?BF^!4~$#0!4?_o{}~^NFB!28?@BN^!12~{w_-#1 61 | NB@???GM!38NMG!13?@BN$#0?KMNNNF@!38?@F!13NMK-\e\' 62 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/todos: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | if command -v rg >/dev/null; then 5 | rg "TODO|HACK|FIXME|OPTIMIZE" 6 | else 7 | echo "Install rg (ripgrep)..." 8 | fi 9 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/togglemode: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env osascript 2 | 3 | tell application "System Events" 4 | tell appearance preferences 5 | set dark mode to not dark mode 6 | end tell 7 | end tell 8 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | # vim:ft=bash: 4 | # ts [FUZZY PATTERN] - Select selected tmux session 5 | # - Bypass fuzzy finder if there's only one match (--select-1) 6 | # - Exit if there's no match (--exit-0) 7 | 8 | unalias ts 2>/dev/null 9 | ts() { 10 | local session 11 | session=$(tmux list-sessions -F "#{session_name}" | 12 | fzf --query="$1" --select-1 --exit-0) && 13 | tmux switch-client -t "$session" 14 | } 15 | 16 | ts "$@" 17 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/vs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | # vim:ft=bash: 4 | 5 | vs() { 6 | #List all vagrant boxes available in the system including its status, and try to access the selected one via ssh 7 | (cd "$(cat ~/.vagrant.d/data/machine-index/index | jq '.machines[] | {name, vagrantfile_path, state}' | jq '.name + "," + .state + "," + .vagrantfile_path' | sed 's/^"\(.*\)"$/\1/' | column -s, -t | sort -rk 2 | fzf | awk '{print $3}')" || exit) 8 | vagrant ssh 9 | } 10 | 11 | vs "$@" 12 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/weather: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Modified version of the generated one from `curl wttr.in/:bash.function` 3 | # 4 | # Simple function to get weather data 5 | # 6 | # Usage: 7 | # $ weather 8 | # $ weather 9 | # Check curl wttr.in/:help for more info 10 | 11 | # Intentionally not setting -e because we want the script to continue if getting the location data fails 12 | set -u -o pipefail 13 | 14 | if [[ -n "${DEBUG-}" ]]; then 15 | set -x 16 | fi 17 | 18 | LOCATION_DATA="$TMPDIR/.location.json" 19 | FALLBACK="" 20 | 21 | if jq -e . "$LOCATION_DATA" >/dev/null 2>&1; then 22 | FALLBACK=$(jq -r '.locality' "$LOCATION_DATA") 23 | fi 24 | 25 | curl -fGsS --compressed "wttr.in/${1:-$FALLBACK}"?"m&lang=en&${2:-0qm}" 26 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/bin/wifi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ue -o pipefail 3 | 4 | # Function to check if the interface is Wi-Fi 5 | is_wifi() { 6 | local interface="$1" 7 | local wifi_status 8 | wifi_status=$(networksetup -getinfo "$interface" | grep "Wi-Fi ID" || true) 9 | [ -n "$wifi_status" ] 10 | } 11 | 12 | # Function to check if the interface is Ethernet 13 | is_ethernet() { 14 | local interface="$1" 15 | local ethernet_status 16 | ethernet_status=$(networksetup -getinfo "$interface" | grep "Ethernet Address" || true) 17 | [ -n "$ethernet_status" ] 18 | } 19 | 20 | # Function to check if the interface is connected 21 | is_connected() { 22 | local interface="$1" 23 | local other_status 24 | other_status=$(networksetup -getinfo "$interface" | grep -E "IP address: [0-9]+" || true) 25 | [ -n "$other_status" ] 26 | } 27 | 28 | # Function to get the currently used network interface 29 | get_current_interface() { 30 | local interfaces 31 | interfaces=$(networksetup -listnetworkserviceorder | grep -E "^\([0-9]+\)" | awk -F'[()]' '{gsub(/^[ \t]+|[ \t]+$/, "", $3); print $3}') 32 | 33 | while IFS= read -r interface; do 34 | if is_connected "$interface"; then 35 | echo -n "$interface" 36 | return 37 | fi 38 | done <<<"$interfaces" 39 | } 40 | 41 | # Function to get SSID of the connected Wi-Fi network 42 | get_wifi_ssid() { 43 | local ssid 44 | ssid=$(networksetup -getairportnetwork en0 | awk -F ": " '{print $2}') 45 | 46 | if [ -z "$ssid" ]; then 47 | # Sequoia has a bug with networksetup command. But the following works 48 | ssid=$(ipconfig getsummary en0 | awk -F ' SSID : ' '/ SSID : / {print $2}') 49 | fi 50 | 51 | echo -n "$ssid" 52 | } 53 | 54 | # icon codes here are PragmataPro related 55 | get_formatted_output() { 56 | local interface 57 | interface=$(get_current_interface) 58 | 59 | if [ -n "$interface" ]; then 60 | if is_wifi "$interface"; then 61 | ssid=$(get_wifi_ssid) 62 | echo -ne "\UF05A9 $ssid" 63 | elif is_ethernet "$interface"; then 64 | # echo -ne "\UF0200 $interface" 65 | echo -ne "\UF0200 " 66 | else 67 | # echo -ne "\UF06F5 $interface" 68 | echo -ne "\UF06F5 " # Icon for other interfaces 69 | fi 70 | else 71 | if [ -n "${TMUX-}" ]; then 72 | echo -ne "#[fg=red]\UF0C9C " 73 | else 74 | echo -ne "\UF0C9C " 75 | fi 76 | fi 77 | } 78 | 79 | # Print the currently used network interface and its status with icon 80 | echo -ne "$(get_formatted_output)" 81 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/config/aliases.zsh: -------------------------------------------------------------------------------- 1 | # vim:ft=zsh: 2 | # Useful 3 | alias cp="${aliases[cp]:-cp} -iv" 4 | alias ln="${aliases[ln]:-ln} -iv" 5 | alias mv="${aliases[mv]:-mv} -iv" 6 | alias rm="${aliases[rm]:-rm} -i" 7 | alias mkdir="${aliases[mkdir]:-mkdir} -p" 8 | alias sudo="sudo " 9 | alias type='type -a' 10 | alias c="clear " 11 | alias e='$EDITOR' 12 | alias df="df -kh" 13 | alias du="du -kh" 14 | alias emptytrash="sudo rm -rfv /Volumes/*/.Trashes;sudo rm -rfv ~/.Trash" 15 | alias fd="fd --hidden " 16 | alias flushdns="sudo killall -HUP mDNSResponder" 17 | alias fs="stat -f '%z bytes'" 18 | alias history-stat="fc -l 1 | awk '{print \$2}' | sort | uniq -c | sort -n -r | head" 19 | alias history='fc -il 1' 20 | alias jobs="jobs -l " 21 | alias play='mx ϟ' 22 | alias y="yarn" 23 | alias p="pnpm" 24 | alias b="bun" 25 | alias top=htop 26 | alias ls="l" 27 | alias ll='eza --tree --group-directories-first --almost-all -I "node_modules" ' 28 | alias formatJSON='jq .' 29 | alias cat='bat ' 30 | alias grep='grep --color=auto' 31 | # https://github.com/neomutt/neomutt/issues/4058#issuecomment-1751682305 32 | alias neomutt="TERM=xterm-direct neomutt" 33 | 34 | # https://github.com/direnv/direnv/wiki/Tmux 35 | alias tmux='direnv exec / tmux' 36 | 37 | if (( ${+commands[wget]} )); then 38 | alias get='wget --continue --progress=bar --timestamping' 39 | elif (( ${+commands[curl]} )); then 40 | alias get='curl --continue-at - --location --progress-bar --remote-name --remote-time' 41 | fi 42 | 43 | if [[ "$(uname)" == linux* ]]; then 44 | alias chmod='chmod --preserve-root -v' 45 | alias chown='chown --preserve-root -v' 46 | fi 47 | 48 | # Avoid ssh issues with ssh and terminfo with new terminal apps 49 | [[ "$TERM" == "xterm-kitty" ]] || [[ "$TERM" == "xterm-ghostty" ]] && alias ssh="TERM=xterm-256color ssh" 50 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/config/completion.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # Completion enhancements 3 | # 4 | 5 | # 6 | # zsh options 7 | # 8 | 9 | setopt ALWAYS_TO_END # If a completion is performed with the cursor within a word, and a full completion is inserted, the cursor is moved to the end of the word 10 | setopt PATH_DIRS # Perform a path search even on command names with slashes in them. 11 | unsetopt CASE_GLOB # Make globbing (filename generation) not sensitive to case. 12 | unsetopt LIST_BEEP # Don't beep on an ambiguous completion. 13 | 14 | # 15 | # completion module options 16 | # 17 | 18 | # group matches and describe. 19 | zstyle ':completion:*:*:*:*:*' menu select 20 | zstyle ':completion:*:matches' group yes 21 | zstyle ':completion:*:options' description yes 22 | zstyle ':completion:*:options' auto-description '%d' 23 | zstyle ':completion:*:corrections' format '%F{green}-- %d (errors: %e) --%f' 24 | zstyle ':completion:*:descriptions' format '%F{yellow}-- %d --%f' 25 | zstyle ':completion:*:messages' format '%F{purple}-- %d --%f' 26 | zstyle ':completion:*:warnings' format '%F{red}-- no matches found --%f' 27 | zstyle ':completion:*' format '%F{yellow}-- %d --%f' 28 | zstyle ':completion:*' group-name '' 29 | zstyle ':completion:*' verbose yes 30 | zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' '+r:|?=**' 31 | 32 | # Complete flags/options 33 | zstyle ':completion:*' complete-options true 34 | 35 | # zstyle ":completion:*" list-colors "${(s.:.)LS_COLORS}" 36 | zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS} 37 | zstyle ':completion:*:*:cd:*' tag-order local-directories directory-stack path-directories 38 | zstyle ':completion:*:*:cd:*:directory-stack' menu yes select 39 | zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'expand' 40 | zstyle ':completion:*' squeeze-slashes true 41 | 42 | # enable caching 43 | zstyle ':completion::complete:*' use-cache on 44 | zstyle ':completion::complete:*' cache-path "${ZDOTDIR}/.zcompcache" 45 | 46 | # ignore useless commands and functions 47 | zstyle ':completion:*:functions' ignored-patterns '(_*|pre(cmd|exec)|prompt_*)' 48 | 49 | # completion sorting 50 | zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters 51 | 52 | # Man 53 | zstyle ':completion:*:manuals' separate-sections true 54 | zstyle ':completion:*:manuals.(^1*)' insert-sections true 55 | 56 | # history 57 | zstyle ':completion:*:history-words' stop yes 58 | zstyle ':completion:*:history-words' remove-all-dups yes 59 | zstyle ':completion:*:history-words' list false 60 | zstyle ':completion:*:history-words' menu yes 61 | 62 | # ignore multiple entries. 63 | zstyle ':completion:*:(rm|kill|diff):*' ignore-line other 64 | zstyle ':completion:*:rm:*' file-patterns '*:all-files' 65 | -------------------------------------------------------------------------------- /config/zsh.d/zsh/config/input.zsh: -------------------------------------------------------------------------------- 1 | # 2 | # Editor and input char assignment 3 | # 4 | 5 | if [ -t 0 ]; then 6 | stty -ixon # allow C-s and C-q to be used for things 7 | fi 8 | 9 | bindkey -v 10 | 11 | # Use human-friendly identifiers. 12 | zmodload -F zsh/terminfo +b:echoti +p:terminfo 13 | typeset -gA key_info 14 | key_info=( 15 | 'Control' '\C-' 16 | 'ControlLeft' '\e[1;5D \e[5D \e\e[D \eOd \eOD' 17 | 'ControlRight' '\e[1;5C \e[5C \e\e[C \eOc \eOC' 18 | 'Escape' '\e' 19 | 'Meta' '\M-' 20 | 'Backspace' ${terminfo[kbs]} 21 | 'BackTab' ${terminfo[kcbt]} 22 | 'Left' ${terminfo[kcub1]} 23 | 'Down' ${terminfo[kcud1]} 24 | 'Right' ${terminfo[kcuf1]} 25 | 'Up' ${terminfo[kcuu1]} 26 | 'Delete' ${terminfo[kdch1]} 27 | 'End' ${terminfo[kend]} 28 | 'F1' ${terminfo[kf1]} 29 | 'F2' ${terminfo[kf2]} 30 | 'F3' ${terminfo[kf3]} 31 | 'F4' ${terminfo[kf4]} 32 | 'F5' ${terminfo[kf5]} 33 | 'F6' ${terminfo[kf6]} 34 | 'F7' ${terminfo[kf7]} 35 | 'F8' ${terminfo[kf8]} 36 | 'F9' ${terminfo[kf9]} 37 | 'F10' ${terminfo[kf10]} 38 | 'F11' ${terminfo[kf11]} 39 | 'F12' ${terminfo[kf12]} 40 | 'Home' ${terminfo[khome]} 41 | 'Insert' ${terminfo[kich1]} 42 | 'PageDown' ${terminfo[knp]} 43 | 'PageUp' ${terminfo[kpp]} 44 | ) 45 | 46 | # Bind the keys 47 | 48 | if [[ ${zdouble_dot_expand} == 'true' ]]; then 49 | double-dot-expand() { 50 | if [[ ${LBUFFER} == *.. ]]; then 51 | LBUFFER+='/..' 52 | else 53 | LBUFFER+='.' 54 | fi 55 | } 56 | zle -N double-dot-expand 57 | bindkey '.' double-dot-expand 58 | fi 59 | 60 | # Expandpace. 61 | bindkey ' ' magic-space 62 | 63 | # Clear 64 | bindkey "${key_info[Control]}L" clear-screen 65 | 66 | # Bind Shift + Tab to go to the previous menu item. 67 | [[ -n ${key_info[BackTab]} ]] && bindkey ${key_info[BackTab]} reverse-menu-complete 68 | 69 | autoload -Uz is-at-least && if ! is-at-least 5.3; then 70 | # Redisplay after completing, and avoid blank prompt after 71 | expand-or-complete-with-redisplay() { 72 | print -Pn '...' 73 | zle expand-or-complete 74 | zle redisplay 75 | } 76 | zle -N expand-or-complete-with-redisplay 77 | bindkey "${key_info[Control]}I" expand-or-complete-with-redisplay 78 | fi 79 | 80 | autoload -Uz edit-command-line 81 | zle -N edit-command-line 82 | bindkey -M vicmd '!' edit-command-line 83 | -------------------------------------------------------------------------------- /neovim.toml: -------------------------------------------------------------------------------- 1 | [selene] 2 | base = 'lua51' 3 | name = 'neovim' 4 | 5 | # neovim 6 | [vim] 7 | any = true 8 | 9 | [__] 10 | any = true 11 | 12 | [Snacks] 13 | any = true 14 | 15 | # hammerspoon 16 | [spoon] 17 | any = true 18 | 19 | [hs] 20 | any = true 21 | -------------------------------------------------------------------------------- /nix/hosts/alcantara.nix: -------------------------------------------------------------------------------- 1 | _: { 2 | networking = {hostName = "alcantara";}; 3 | 4 | my = { 5 | modules = { 6 | mail = {enable = true;}; 7 | irc.enable = true; 8 | gpg.enable = true; 9 | discord.enable = true; 10 | }; 11 | }; 12 | 13 | homebrew = { 14 | casks = [ 15 | # "arq" # I need a specific version so I will handle it myself. 16 | "transmit" 17 | "jdownloader" 18 | "brave-browser" 19 | "signal" 20 | "monodraw" 21 | "cursor" 22 | ]; 23 | 24 | # Requires to be logged in to the AppStore 25 | # Cleanup doesn't work automatically if you add/remove to list 26 | # masApps = { 27 | # Guidance = 412759995; 28 | # Dato = 1470584107; 29 | # "Day One" = 1055511498; 30 | # Tweetbot = 1384080005; 31 | # Todoist = 585829637; 32 | # Sip = 507257563; 33 | # Irvue = 1039633667; 34 | # Telegram = 747648890; 35 | # }; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /nix/hosts/nixos/dwm.patch: -------------------------------------------------------------------------------- 1 | diff --git a/config.def.h b/config.def.h 2 | index 1c0b587..e518bff 100644 3 | --- a/config.def.h 4 | +++ b/config.def.h 5 | @@ -1,7 +1,7 @@ 6 | /* See LICENSE file for copyright and license details. */ 7 | 8 | /* appearance */ 9 | -static const unsigned int borderpx = 1; /* border pixel of windows */ 10 | +static const unsigned int borderpx = 0; /* border pixel of windows */ 11 | static const unsigned int snap = 32; /* snap pixel */ 12 | static const int showbar = 1; /* 0 means no bar */ 13 | static const int topbar = 1; /* 0 means bottom bar */ 14 | @@ -27,8 +27,7 @@ static const Rule rules[] = { 15 | * WM_NAME(STRING) = title 16 | */ 17 | /* class instance title tags mask isfloating monitor */ 18 | - { "Gimp", NULL, NULL, 0, 1, -1 }, 19 | - { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, 20 | + { "Brave", NULL, NULL, 1 << 8, 0, -1 }, 21 | }; 22 | 23 | /* layout(s) */ 24 | @@ -44,7 +43,7 @@ static const Layout layouts[] = { 25 | }; 26 | 27 | /* key definitions */ 28 | -#define MODKEY Mod1Mask 29 | +#define MODKEY Mod4Mask 30 | #define TAGKEYS(KEY,TAG) \ 31 | { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ 32 | { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ 33 | @@ -57,7 +56,7 @@ static const Layout layouts[] = { 34 | /* commands */ 35 | static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ 36 | static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; 37 | -static const char *termcmd[] = { "st", NULL }; 38 | +static const char *termcmd[] = { "kitty", "--single-instance" }; 39 | 40 | static Key keys[] = { 41 | /* modifier key function argument */ 42 | -------------------------------------------------------------------------------- /nix/hosts/nixos/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { 5 | config, 6 | lib, 7 | pkgs, 8 | modulesPath, 9 | ... 10 | }: { 11 | imports = [(modulesPath + "/installer/scan/not-detected.nix")]; 12 | 13 | boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod"]; 14 | boot.initrd.kernelModules = []; 15 | boot.kernelModules = ["kvm-intel" "wl"]; 16 | boot.extraModulePackages = [config.boot.kernelPackages.broadcom_sta]; 17 | 18 | fileSystems."/" = { 19 | device = "/dev/disk/by-uuid/bf9df006-7b07-4895-973c-819d283fb7ed"; 20 | fsType = "ext4"; 21 | }; 22 | 23 | fileSystems."/boot" = { 24 | device = "/dev/disk/by-uuid/E796-E88F"; 25 | fsType = "vfat"; 26 | }; 27 | 28 | swapDevices = [{device = "/dev/disk/by-uuid/b24c0bc4-f574-431b-8803-9eb313dfb23a";}]; 29 | 30 | powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; 31 | } 32 | -------------------------------------------------------------------------------- /nix/hosts/pandoras-box.nix: -------------------------------------------------------------------------------- 1 | _: { 2 | networking = {hostName = "pandoras-box";}; 3 | 4 | my = { 5 | modules = { 6 | mail = {enable = true;}; 7 | irc.enable = true; 8 | gpg.enable = true; 9 | discord.enable = true; 10 | hledger.enable = true; 11 | }; 12 | }; 13 | 14 | homebrew = { 15 | casks = [ 16 | # "arq" # I need a specific version so I will handle it myself. 17 | "transmit" 18 | "jdownloader" 19 | "brave-browser" 20 | "signal" 21 | ]; 22 | 23 | # Requires to be logged in to the AppStore 24 | # Cleanup doesn't work automatically if you add/remove to list 25 | # masApps = { 26 | # Guidance = 412759995; 27 | # Dato = 1470584107; 28 | # "Day One" = 1055511498; 29 | # Tweetbot = 1384080005; 30 | # Todoist = 585829637; 31 | # Sip = 507257563; 32 | # Irvue = 1039633667; 33 | # Telegram = 747648890; 34 | # }; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /nix/hosts/rocket.nix: -------------------------------------------------------------------------------- 1 | {pkgs, ...}: { 2 | networking = {hostName = "rocket";}; 3 | ids.gids.nixbld = 30000; 4 | 5 | my = { 6 | username = "ahmedelgabri"; 7 | email = "ahmed@miro.com"; 8 | website = "https://miro.com"; 9 | company = "Miro"; 10 | devFolder = "dev"; 11 | modules = { 12 | gpg.enable = true; 13 | mail = { 14 | enable = true; 15 | account = "Work"; 16 | alias_path = ""; 17 | keychain = {name = "gmail.com";}; 18 | imap_server = "imap.gmail.com"; 19 | smtp_server = "smtp.gmail.com"; 20 | }; 21 | }; 22 | user = { 23 | packages = with pkgs; [ 24 | graph-easy 25 | graphviz 26 | nodePackages.mermaid-cli 27 | jira-cli-go 28 | git-filter-repo 29 | git-lfs 30 | git-sizer 31 | httpstat 32 | k9s 33 | lazydocker 34 | ]; 35 | }; 36 | }; 37 | 38 | homebrew = { 39 | casks = [ 40 | "loom" 41 | "docker" 42 | "ngrok" 43 | "figma" 44 | "visual-studio-code" 45 | "google-chrome" 46 | ]; 47 | 48 | brews = [ 49 | "go-task" 50 | ]; 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /nix/modules/shared/ai.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | homeDir = config.my.user.home; 8 | cfg = config.my.modules.ai; 9 | inherit (pkgs.stdenv) isDarwin isLinux; 10 | in { 11 | options = with lib; { 12 | my.modules.ai = { 13 | enable = mkEnableOption '' 14 | Whether to enable ai module 15 | ''; 16 | }; 17 | }; 18 | 19 | config = with lib; 20 | mkIf cfg.enable (mkMerge [ 21 | (mkIf isDarwin { 22 | launchd.daemons.ollama = { 23 | command = "${pkgs.ollama}/bin/ollama serve"; 24 | serviceConfig = { 25 | Label = "ollama"; 26 | UserName = config.my.username; 27 | GroupName = "staff"; 28 | ExitTimeOut = 30; 29 | Disabled = false; 30 | RunAtLoad = true; 31 | KeepAlive = true; 32 | StandardOutPath = "${homeDir}/Library/Logs/ollama-output.log"; 33 | StandardErrorPath = "${homeDir}/Library/Logs/ollama-error.log"; 34 | EnvironmentVariables = { 35 | "OLLAMA_HOST" = "0.0.0.0:11434"; 36 | }; 37 | }; 38 | }; 39 | homebrew.casks = [ 40 | "msty" 41 | "claude" 42 | ]; 43 | }) 44 | (mkIf isLinux { 45 | my.user = { 46 | packages = with pkgs; [ 47 | open-webui 48 | ]; 49 | }; 50 | }) 51 | 52 | { 53 | environment = { 54 | shellAliases = { 55 | aider = "${pkgs.aider-chat}/bin/aider --config ~/.dotfiles/config/aider/config.yml"; 56 | }; 57 | }; 58 | my = { 59 | user = { 60 | packages = with pkgs; [ 61 | ollama 62 | llama-cpp 63 | llm 64 | codex 65 | claude-code 66 | aider-chat 67 | ]; 68 | }; 69 | hm.file = { 70 | ".claude/CLAUDE.md" = { 71 | source = ../../../config/claude/CLAUDE.md; 72 | }; 73 | }; 74 | }; 75 | } 76 | ]); 77 | } 78 | -------------------------------------------------------------------------------- /nix/modules/shared/bat.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.bat; 8 | in { 9 | options = with lib; { 10 | my.modules.bat = { 11 | enable = mkEnableOption '' 12 | Whether to enable bat module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | my.env = {BAT_CONFIG_PATH = "$XDG_CONFIG_HOME/bat/config";}; 20 | 21 | my.user = {packages = with pkgs; [bat];}; 22 | 23 | my.hm.file = { 24 | ".config/bat" = { 25 | recursive = true; 26 | source = ../../../config/bat; 27 | }; 28 | }; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /nix/modules/shared/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | ... 5 | }: { 6 | imports = [ 7 | ./settings.nix 8 | ./shell.nix 9 | ./mail.nix 10 | ./gpg.nix 11 | ./ssh.nix 12 | ./git.nix 13 | ./kitty.nix 14 | ./bat.nix 15 | ./yazi.nix 16 | ./mpv.nix 17 | ./ripgrep.nix 18 | ./tmux.nix 19 | ./yt-dlp.nix 20 | ./misc.nix 21 | ./vim.nix 22 | ./node.nix 23 | ./irc.nix 24 | ./go.nix 25 | ./rust.nix 26 | ./gui.nix 27 | ./python.nix 28 | ./discord.nix 29 | ./zk.nix 30 | ./hammerspoon.nix 31 | ./ghostty.nix 32 | ./ai.nix 33 | ./karabiner.nix 34 | ]; 35 | 36 | my.modules = { 37 | shell.enable = lib.mkDefault true; 38 | git.enable = lib.mkDefault true; 39 | ssh.enable = lib.mkDefault true; 40 | 41 | kitty.enable = lib.mkDefault true; 42 | bat.enable = lib.mkDefault true; 43 | yazi.enable = lib.mkDefault true; 44 | mpv.enable = lib.mkDefault true; 45 | python.enable = lib.mkDefault true; 46 | ripgrep.enable = lib.mkDefault true; 47 | tmux.enable = lib.mkDefault true; 48 | misc.enable = lib.mkDefault true; 49 | vim.enable = lib.mkDefault true; 50 | gui.enable = lib.mkDefault true; 51 | yt-dlp.enable = lib.mkDefault true; 52 | 53 | node.enable = lib.mkDefault true; 54 | go.enable = lib.mkDefault true; 55 | rust.enable = lib.mkDefault true; 56 | zk.enable = lib.mkDefault true; 57 | discord.enable = lib.mkDefault true; 58 | hammerspoon.enable = lib.mkDefault pkgs.stdenv.isDarwin; 59 | karabiner.enable = lib.mkDefault pkgs.stdenv.isDarwin; 60 | ghostty.enable = lib.mkDefault true; 61 | ai.enable = lib.mkDefault true; 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /nix/modules/shared/discord.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.discord; 8 | inherit (pkgs.stdenv) isDarwin isLinux; 9 | in { 10 | options = with lib; { 11 | my.modules.discord = { 12 | enable = mkEnableOption '' 13 | Whether to enable discord module 14 | ''; 15 | }; 16 | }; 17 | 18 | config = with lib; 19 | mkIf cfg.enable (mkMerge [ 20 | (mkIf isDarwin { 21 | homebrew.casks = ["discord"]; 22 | }) 23 | (mkIf isLinux { 24 | my.user = {packages = with pkgs; [discord];}; 25 | }) 26 | ]); 27 | } 28 | -------------------------------------------------------------------------------- /nix/modules/shared/ghostty.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | config, 4 | pkgs, 5 | ... 6 | }: let 7 | cfg = config.my.modules.ghostty; 8 | inherit (pkgs.stdenv) isDarwin isLinux; 9 | in { 10 | options = with lib; { 11 | my.modules.ghostty = { 12 | enable = mkEnableOption '' 13 | Whether to enable ghostty module 14 | ''; 15 | }; 16 | }; 17 | 18 | config = with lib; 19 | mkIf cfg.enable (mkMerge [ 20 | (mkIf isDarwin { 21 | homebrew.casks = [ 22 | "ghostty@tip" 23 | ]; 24 | }) 25 | (mkIf isLinux { 26 | my.user = { 27 | packages = with pkgs; [ 28 | # Broken on Darwin that's why we have two branches 29 | ghostty 30 | ]; 31 | }; 32 | }) 33 | { 34 | my = { 35 | # user = { 36 | # packages = with pkgs; [ 37 | # ghostty 38 | # ]; 39 | # }; 40 | hm.file = { 41 | ".config/ghostty" = { 42 | recursive = true; 43 | source = ../../../config/ghostty; 44 | }; 45 | }; 46 | }; 47 | } 48 | ]); 49 | } 50 | -------------------------------------------------------------------------------- /nix/modules/shared/git.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.git; 8 | in { 9 | options = with lib; { 10 | my.modules.git = { 11 | enable = mkEnableOption '' 12 | Whether to enable git module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | environment.systemPackages = with pkgs; [git]; 20 | homebrew.brews = ["transcrypt"]; 21 | 22 | my.user = { 23 | packages = with pkgs; [ 24 | # gitAndTools.transcrypt # old version 25 | # gitAndTools.diff-so-fancy 26 | gitAndTools.delta 27 | gitAndTools.hub 28 | gitAndTools.gh # Need this too https://github.com/yusukebe/gh-markdown-preview 29 | gitAndTools.tig 30 | exiftool 31 | ]; 32 | }; 33 | 34 | my.hm.file = { 35 | ".config/git/config-nix" = with config.my; { 36 | text = '' 37 | ; ${nix_managed} 38 | ; vim: ft=gitconfig 39 | 40 | [user] 41 | ${optionalString (name != "") " name = ${name}"} 42 | ${optionalString (email != "") " email = ${email}"} 43 | useconfigonly = true 44 | 45 | ${optionalString (github_username != "") '' 46 | [github] 47 | username = ${github_username}''} 48 | 49 | [gpg] 50 | program = ${pkgs.gnupg}/bin/gpg 51 | 52 | [diff "exif"] 53 | textconv = ${pkgs.exiftool}/bin/exiftool 54 | 55 | ${optionalString pkgs.stdenv.isDarwin '' 56 | [diff "plist"] 57 | textconv = plutil -convert xml1 -o -''} 58 | 59 | [include] 60 | path = ${hostConfigHome}/gitconfig 61 | ''; 62 | }; 63 | 64 | ".config/git" = { 65 | recursive = true; 66 | source = ../../../config/git; 67 | }; 68 | 69 | ".config/tig" = { 70 | recursive = true; 71 | source = ../../../config/tig; 72 | }; 73 | }; 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /nix/modules/shared/go.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.go; 8 | in { 9 | options = with lib; { 10 | my.modules.go = { 11 | enable = mkEnableOption '' 12 | Whether to enable go module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | my.env = rec { 20 | GOPATH = "$XDG_DATA_HOME/go"; 21 | GOBIN = "${GOPATH}/bin"; 22 | GOPRIVATE = "github.com/${config.my.github_username}/*,gitlab.com/${config.my.github_username}/*"; 23 | }; 24 | 25 | # all tools from https://github.com/golang/vscode-go/blob/ed92a0c250e8941abb9adab973c129a263ba1e41/src/goToolsInformation.ts 26 | # my.user = { 27 | # packages = with pkgs; [ 28 | # delve # dlv 29 | # go 30 | # go-tools # staticcheck 31 | # gofumpt 32 | # golangci-lint 33 | # gomodifytags 34 | # gopls 35 | # gotests 36 | # gotools # goimports 37 | # impl 38 | # revive 39 | # ]; 40 | # }; 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /nix/modules/shared/gpg.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.gpg; 8 | in { 9 | options = with lib; { 10 | my.modules.gpg = { 11 | enable = mkEnableOption '' 12 | Whether to enable gpg module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | environment.systemPackages = with pkgs; [gnupg]; 20 | my.env = {GNUPGHOME = "$XDG_CONFIG_HOME/gnupg";}; 21 | 22 | programs.gnupg.agent = { 23 | enable = true; 24 | enableSSHSupport = true; 25 | }; 26 | 27 | my.hm.file = { 28 | ".config/gnupg/gpg-agent.conf".text = '' 29 | # ${config.my.nix_managed} 30 | 31 | allow-preset-passphrase 32 | 33 | # Default: 600 seconds 34 | default-cache-ttl 86400 35 | 36 | # Default: 7200 seconds 37 | max-cache-ttl 86400''; 38 | 39 | ".config/gnupg/gpg.conf" = { 40 | text = '' 41 | # ${config.my.nix_managed} 42 | ${builtins.readFile ../../../config/gnupg/gpg.conf}''; 43 | }; 44 | }; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /nix/modules/shared/hammerspoon.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | config, 4 | ... 5 | }: let 6 | inherit (config.my.user) home; 7 | cfg = config.my.modules.hammerspoon; 8 | in { 9 | options = with lib; { 10 | my.modules.hammerspoon = { 11 | enable = mkEnableOption '' 12 | Whether to enable hammerspoon module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | homebrew.casks = [ 20 | "hammerspoon" 21 | ]; 22 | 23 | system.activationScripts.postActivation.text = 24 | /* 25 | bash 26 | */ 27 | '' 28 | echo ":: -> Running hammerspoon activationScript..." 29 | 30 | # Handle mutable configs 31 | echo "Linking hammerspoon folders..." 32 | ln -sf ${home}/.dotfiles/config/.hammerspoon ${home} 33 | ''; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /nix/modules/shared/karabiner.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | config, 4 | ... 5 | }: let 6 | inherit (config.my.user) home; 7 | inherit (config.my) hm; 8 | cfg = config.my.modules.karabiner; 9 | in { 10 | options = with lib; { 11 | my.modules.karabiner = { 12 | enable = mkEnableOption '' 13 | Whether to enable karabiner module 14 | ''; 15 | }; 16 | }; 17 | 18 | config = with lib; 19 | mkIf cfg.enable { 20 | homebrew.casks = [ 21 | "karabiner-elements" 22 | ]; 23 | 24 | # my.hm.file = { 25 | # ".config/karabiner/karabiner.json" = { 26 | # source = ../../../config/karabiner/karabiner.json; 27 | # }; 28 | # }; 29 | 30 | # The config should be "live" because it can be modified from the app GUI 31 | # At least for now and until I reach a stable state, I'd like to symlink it instead 32 | system.activationScripts.postActivation.text = 33 | /* 34 | bash 35 | */ 36 | '' 37 | echo ":: -> Running karabiner activationScript..." 38 | 39 | # Handle mutable configs 40 | echo "Linking karabiner folders..." 41 | ln -sf ${home}/.dotfiles/config/karabiner ${hm.configHome} 42 | ''; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /nix/modules/shared/kitty.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.kitty; 8 | inherit (pkgs.stdenv) isDarwin isLinux; 9 | in { 10 | options = with lib; { 11 | my.modules.kitty = { 12 | enable = mkEnableOption '' 13 | Whether to enable kitty module 14 | ''; 15 | }; 16 | }; 17 | 18 | config = with lib; 19 | mkIf cfg.enable (mkMerge [ 20 | (mkIf isDarwin { 21 | homebrew.casks = ["kitty"]; 22 | my = { 23 | env = { 24 | TERMINFO_DIRS = [ 25 | "$KITTY_INSTALLATION_DIR/terminfo" 26 | ]; 27 | }; 28 | }; 29 | }) 30 | (mkIf isLinux { 31 | my = { 32 | user = { 33 | packages = with pkgs; [ 34 | kitty 35 | ]; 36 | }; 37 | 38 | env = { 39 | TERMINFO_DIRS = [ 40 | "${pkgs.kitty.terminfo}/share/terminfo" 41 | ]; 42 | }; 43 | }; 44 | }) 45 | 46 | { 47 | my = { 48 | hm.file = { 49 | ".config/kitty" = { 50 | recursive = true; 51 | source = ../../../config/kitty; 52 | }; 53 | }; 54 | }; 55 | } 56 | ]); 57 | } 58 | -------------------------------------------------------------------------------- /nix/modules/shared/misc.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.misc; 8 | in { 9 | options = with lib; { 10 | my.modules.misc = { 11 | enable = mkEnableOption '' 12 | Whether to enable misc module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | my.hm.file = { 20 | ".gemrc" = {source = ../../../config/.gemrc;}; 21 | ".curlrc" = {source = ../../../config/.curlrc;}; 22 | ".ignore" = {source = ../../../config/.ignore;}; 23 | ".config/fd/ignore" = { 24 | recursive = true; 25 | text = builtins.readFile ../../../config/.ignore; 26 | }; 27 | ".mailcap" = {source = ../../../config/.mailcap;}; 28 | ".psqlrc" = {source = ../../../config/.psqlrc;}; 29 | }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /nix/modules/shared/mpv.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.mpv; 8 | inherit (pkgs.stdenv) isDarwin; 9 | in { 10 | options = with lib; { 11 | my.modules.mpv = { 12 | enable = mkEnableOption '' 13 | Whether to enable mpv module 14 | ''; 15 | }; 16 | }; 17 | 18 | config = with lib; 19 | mkIf cfg.enable (mkMerge [ 20 | (mkIf isDarwin { 21 | homebrew.casks = ["iina"]; 22 | }) 23 | 24 | { 25 | my.user = {packages = with pkgs; [mpv];}; 26 | my.hm.file = { 27 | ".config/mpv" = { 28 | recursive = true; 29 | source = ../../../config/mpv; 30 | }; 31 | }; 32 | } 33 | ]); 34 | } 35 | -------------------------------------------------------------------------------- /nix/modules/shared/node.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | inputs, 6 | ... 7 | }: let 8 | cfg = config.my.modules.node; 9 | in { 10 | options = with lib; { 11 | my.modules.node = { 12 | enable = mkEnableOption '' 13 | Whether to enable node module 14 | ''; 15 | }; 16 | }; 17 | 18 | config = with lib; 19 | mkIf cfg.enable { 20 | # I don't install any packages here because I use shell.nix for each project, so no need for globals 21 | my = { 22 | env = with config.my; { 23 | NODE_REPL_HISTORY = "$XDG_CACHE_HOME/node_repl_history"; 24 | NPM_CONFIG_EDITOR = "$EDITOR"; 25 | NPM_CONFIG_INIT_AUTHOR_NAME = name; 26 | NPM_CONFIG_INIT_AUTHOR_EMAIL = email; 27 | NPM_CONFIG_INIT_AUTHOR_URL = website; 28 | NPM_CONFIG_INIT_LICENSE = "MIT"; 29 | NPM_CONFIG_INIT_VERSION = "0.0.0"; 30 | }; 31 | 32 | hm.file = { 33 | ".npmrc" = { 34 | source = ../../../config/.npmrc; 35 | }; 36 | }; 37 | }; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /nix/modules/shared/python.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.python; 8 | in { 9 | options = with lib; { 10 | my.modules.python = { 11 | enable = mkEnableOption '' 12 | Whether to enable python module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | my = { 20 | env = {PYTHONSTARTUP = "$XDG_CONFIG_HOME/python/.pythonrc.py";}; 21 | 22 | user = { 23 | packages = with pkgs; [ 24 | (python3.withPackages (ps: 25 | with ps; [ 26 | pip 27 | setuptools 28 | pynvim 29 | vobject # Mutt calendar script 30 | ])) 31 | # nixos.python38Packages.httpx 32 | ruff 33 | pyright 34 | uv 35 | ]; 36 | }; 37 | 38 | hm.file = { 39 | ".config/python" = { 40 | recursive = true; 41 | source = ../../../config/python; 42 | }; 43 | ".config/pip" = { 44 | recursive = true; 45 | source = ../../../config/pip; 46 | }; 47 | }; 48 | }; 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /nix/modules/shared/ripgrep.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.ripgrep; 8 | in { 9 | options = with lib; { 10 | my.modules.ripgrep = { 11 | enable = mkEnableOption '' 12 | Whether to enable ripgrep module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | my.env = {RIPGREP_CONFIG_PATH = "$XDG_CONFIG_HOME/ripgrep/config";}; 20 | 21 | my.user = {packages = with pkgs; [ripgrep];}; 22 | 23 | my.hm.file = { 24 | ".config/ripgrep" = { 25 | recursive = true; 26 | source = ../../../config/ripgrep; 27 | }; 28 | }; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /nix/modules/shared/rust.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | config, 4 | ... 5 | }: let 6 | cfg = config.my.modules.rust; 7 | in { 8 | options = with lib; { 9 | my.modules.rust = { 10 | enable = mkEnableOption '' 11 | Whether to enable rust module 12 | ''; 13 | }; 14 | }; 15 | 16 | config = with lib; 17 | mkIf cfg.enable { 18 | my.env = { 19 | RUSTUP_HOME = "$XDG_DATA_HOME/rustup"; 20 | CARGO_HOME = "$XDG_DATA_HOME/cargo"; 21 | }; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /nix/modules/shared/ssh.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.ssh; 8 | in { 9 | options = with lib; { 10 | my.modules.ssh = { 11 | enable = mkEnableOption '' 12 | Whether to enable ssh module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | my.hm.file = { 20 | ".ssh/config" = {source = ../../../config/.ssh/config;}; 21 | }; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /nix/modules/shared/tmux.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.tmux; 8 | in { 9 | options = with lib; { 10 | my.modules.tmux = { 11 | enable = mkEnableOption '' 12 | Whether to enable tmux module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | my.user = { 20 | packages = with pkgs; [ 21 | tmux 22 | next-prayer 23 | ]; 24 | }; 25 | 26 | my.hm.file = { 27 | ".config/tmux" = { 28 | recursive = true; 29 | source = ../../../config/tmux; 30 | }; 31 | }; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /nix/modules/shared/vim.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.vim; 8 | inherit (config.my.user) home; 9 | inherit (config.my) hm; 10 | in { 11 | options = with lib; { 12 | my.modules.vim = { 13 | enable = mkEnableOption '' 14 | Whether to enable vim module 15 | ''; 16 | }; 17 | }; 18 | 19 | config = with lib; 20 | mkIf cfg.enable { 21 | environment.systemPackages = with pkgs; 22 | [ 23 | vim 24 | neovim-unwrapped 25 | ] 26 | ++ (lib.optionals (!pkgs.stdenv.isDarwin) [ 27 | gcc # Required for treesitter parsers 28 | ]); 29 | 30 | my.env = { 31 | EDITOR = "${pkgs.neovim-unwrapped}/bin/nvim"; 32 | VISUAL = "$EDITOR"; 33 | GIT_EDITOR = "$EDITOR"; 34 | MANPAGER = "$EDITOR +Man!"; 35 | }; 36 | 37 | my.user = { 38 | packages = with pkgs; [ 39 | fzf 40 | par 41 | fd 42 | ripgrep 43 | hadolint # Docker linter 44 | dotenv-linter 45 | alejandra 46 | shellcheck 47 | shfmt # Doesn't work with zsh, only sh & bash 48 | stylua 49 | vscode-langservers-extracted # HTML, CSS, JSON & ESLint LSPs 50 | nodePackages.prettier 51 | bash-language-server 52 | dockerfile-language-server-nodejs 53 | docker-compose-language-service 54 | vtsls # js/ts LSP 55 | yaml-language-server 56 | tailwindcss-language-server 57 | statix 58 | sumneko-lua-language-server 59 | tree-sitter # required for treesitter "auto-install" option to work 60 | nixd # nix lsp 61 | actionlint 62 | taplo # TOML linter and formatter 63 | selene # Lua linter 64 | # neovim luarocks support requires lua 5.1 65 | # https://github.com/folke/lazy.nvim/issues/1570#issuecomment-2194329169 66 | lua51Packages.luarocks 67 | typos 68 | typos-lsp 69 | copilot-language-server 70 | pngpaste # For Obsidian paste_img command 71 | stylelint-lsp 72 | ]; 73 | }; 74 | 75 | system.activationScripts.postActivation.text = 76 | /* 77 | bash 78 | */ 79 | '' 80 | echo ":: -> Running vim activationScript..." 81 | # Handle mutable configs 82 | echo "Linking vim folders..." 83 | ln -sf ${home}/.dotfiles/config/nvim ${hm.configHome} 84 | 85 | echo "Creating vim swap/backup/undo/view folders inside ${hm.stateHome}/nvim ..." 86 | mkdir -p ${hm.stateHome}/nvim/{backup,swap,undo,view} 87 | ''; 88 | }; 89 | } 90 | -------------------------------------------------------------------------------- /nix/modules/shared/yazi.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | inputs, 6 | ... 7 | }: let 8 | cfg = config.my.modules.yazi; 9 | in { 10 | options = with lib; { 11 | my.modules.yazi = { 12 | enable = mkEnableOption '' 13 | Whether to enable yazi module 14 | ''; 15 | }; 16 | }; 17 | 18 | config = with lib; 19 | mkIf cfg.enable { 20 | my.user = { 21 | packages = with pkgs; [ 22 | yazi 23 | zoxide 24 | fzf 25 | fd 26 | ripgrep 27 | # https://yazi-rs.github.io/docs/quick-start#shell-wrapper 28 | (pkgs.writeShellScriptBin "yy" '' 29 | set -ue -o pipefail 30 | 31 | function ya() { 32 | local tmp="$(mktemp -t "yazi-cwd.XXXXX")" 33 | yazi "$@" --cwd-file="$tmp" 34 | if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then 35 | cd -- "$cwd" 36 | fi 37 | rm -f -- "$tmp" 38 | } 39 | 40 | ya "$@" 41 | '') 42 | ]; 43 | }; 44 | 45 | my.hm.file = { 46 | ".config/yazi" = { 47 | recursive = true; 48 | source = ../../../config/yazi; 49 | }; 50 | 51 | ".config/yazi/plugins/smart-enter.yazi" = { 52 | recursive = true; 53 | source = "${inputs.yazi-plugins}/smart-enter.yazi"; 54 | }; 55 | 56 | ".config/yazi/plugins/toggle-pane.yazi" = { 57 | recursive = true; 58 | source = "${inputs.yazi-plugins}/toggle-pane.yazi"; 59 | }; 60 | 61 | ".config/yazi/plugins/full-border.yazi" = { 62 | recursive = true; 63 | source = "${inputs.yazi-plugins}/full-border.yazi"; 64 | }; 65 | 66 | ".config/yazi/plugins/git.yazi" = { 67 | recursive = true; 68 | source = "${inputs.yazi-plugins}/git.yazi"; 69 | }; 70 | 71 | ".config/yazi/plugins/glow.yazi/main.lua" = { 72 | recursive = true; 73 | source = "${inputs.yazi-glow}/init.lua"; 74 | }; 75 | }; 76 | }; 77 | } 78 | -------------------------------------------------------------------------------- /nix/modules/shared/yt-dlp.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.yt-dlp; 8 | in { 9 | options = with lib; { 10 | my.modules.yt-dlp = { 11 | enable = mkEnableOption '' 12 | Whether to enable yt-dlp module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | my.user = { 20 | packages = with pkgs; [ 21 | (yt-dlp.override {withAlias = true;}) 22 | ]; 23 | }; 24 | 25 | my.hm.file = { 26 | ".config/yt-dlp" = { 27 | recursive = true; 28 | source = ../../../config/yt-dlp; 29 | }; 30 | }; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /nix/modules/shared/zk.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | lib, 4 | config, 5 | ... 6 | }: let 7 | cfg = config.my.modules.zk; 8 | in { 9 | options = with lib; { 10 | my.modules.zk = { 11 | enable = mkEnableOption '' 12 | Whether to enable zk module 13 | ''; 14 | }; 15 | }; 16 | 17 | config = with lib; 18 | mkIf cfg.enable { 19 | my.user = {packages = with pkgs; [zk];}; 20 | 21 | my.hm.file = { 22 | ".config/zk/config.toml" = { 23 | source = ../../../config/zk/config.toml; 24 | }; 25 | ".config/zk/templates" = { 26 | recursive = true; 27 | source = ../../../config/zk/templates; 28 | }; 29 | }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /nix/pkgs/hcron.nix: -------------------------------------------------------------------------------- 1 | { 2 | fetchurl, 3 | stdenvNoCC, 4 | }: 5 | stdenvNoCC.mkDerivation rec { 6 | name = "hcron"; 7 | version = "1.1.1"; 8 | dontBuild = true; 9 | dontConfigure = true; 10 | 11 | src = fetchurl { 12 | url = "https://github.com/lnquy/cron/releases/download/v${version}/cron_${version}_darwin_amd64.tar.gz"; 13 | sha256 = "0p42691d0wy14wjbgy3rp2pcsn3xrni9fnw35wia6jrsha2w5z07"; 14 | }; 15 | 16 | # Work around the "unpacker appears to have produced no directories" 17 | # case that happens when the archive doesn't have a subdirectory. 18 | sourceRoot = "."; 19 | 20 | installPhase = '' 21 | mkdir -p $out/bin 22 | 23 | cp cron $out/bin/hcron 24 | 25 | chmod +x $out/bin/hcron 26 | ''; 27 | } 28 | -------------------------------------------------------------------------------- /nix/pkgs/pragmatapro.nix: -------------------------------------------------------------------------------- 1 | { 2 | stdenvNoCC, 3 | requireFile, 4 | lib, 5 | pkgs, 6 | }: 7 | stdenvNoCC.mkDerivation rec { 8 | name = "PragmataPro${version}"; 9 | version = "0.9"; 10 | dontBuild = true; 11 | dontConfigure = true; 12 | 13 | src = requireFile { 14 | url = "file://path/to/${name}.zip"; 15 | sha256 = "17apwzsvbmfaiq6d00ip9lchxrc3v9r3k7dhiw1k60rjsl6fjy1i"; 16 | message = '' 17 | ${name} font not found in nix store, to add it run: 18 | $ nix-store --add-fixed sha256 /path/to/${name}.zip 19 | 20 | Did you change the file? maybe you need to update the sha256 21 | $ nix-hash --flat --base32 --type sha256 /path/to/${name}.zip | pbcopy''; 22 | }; 23 | 24 | buildInputs = [pkgs.unzip]; 25 | 26 | # Work around the "unpacker appears to have produced no directories" 27 | # case that happens when the archive doesn't have a subdirectory. 28 | sourceRoot = "."; 29 | 30 | installPhase = '' 31 | install_path=$out/share/fonts/opentype 32 | mkdir -p $install_path 33 | 34 | find -name "PragmataPro*.otf" -exec cp {} $install_path \; 35 | ''; 36 | 37 | meta = with lib; { 38 | homepage = "https://www.fsd.it/shop/fonts/pragmatapro/"; 39 | description = '' 40 | PragmataPro™ is a condensed monospaced font optimized for screen, 41 | designed by Fabrizio Schiavi to be the ideal font for coding, math and engineering 42 | ''; 43 | platforms = platforms.all; 44 | licence = licences.unfree; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmedelgabri/dotfiles/e7f65a22b13edaf42bd76522313db20239430985/screenshot.png -------------------------------------------------------------------------------- /selene.toml: -------------------------------------------------------------------------------- 1 | std = "neovim" 2 | 3 | [lints] 4 | mixed_table = "allow" 5 | -------------------------------------------------------------------------------- /templates/bun/.envrc: -------------------------------------------------------------------------------- 1 | set -e 2 | set +u 3 | 4 | use flake 5 | 6 | dotenv_if_exists 7 | 8 | watch_file .env 9 | -------------------------------------------------------------------------------- /templates/bun/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | systems.url = "github:nix-systems/default"; 5 | flake-utils = { 6 | url = "github:numtide/flake-utils"; 7 | inputs.systems.follows = "systems"; 8 | }; 9 | }; 10 | 11 | outputs = { 12 | self, 13 | nixpkgs, 14 | flake-utils, 15 | ... 16 | } @ inputs: 17 | flake-utils.lib.eachDefaultSystem ( 18 | system: let 19 | pkgs = import nixpkgs { 20 | inherit system; 21 | config.allowUnfree = true; 22 | }; 23 | in { 24 | formatter = pkgs.alejandra; 25 | devShells.default = pkgs.mkShell { 26 | buildInputs = with pkgs; [ 27 | bun 28 | ]; 29 | shellHook = '' 30 | bun -e 'console.log(`You are running Bun v${"$"}{Bun.version}`)' 31 | ''; 32 | }; 33 | } 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /templates/bun/tsconfig.json: -------------------------------------------------------------------------------- 1 | // https://bun.sh/guides/runtime/typescript 2 | { 3 | "compilerOptions": { 4 | // Enable latest features 5 | "lib": ["ESNext", "DOM"], 6 | "target": "ESNext", 7 | "module": "ESNext", 8 | "moduleDetection": "force", 9 | "jsx": "react-jsx", 10 | "allowJs": true, 11 | 12 | // Bundler mode 13 | "moduleResolution": "bundler", 14 | "allowImportingTsExtensions": true, 15 | "verbatimModuleSyntax": true, 16 | "noEmit": true, 17 | 18 | // Best practices 19 | "strict": true, 20 | "skipLibCheck": true, 21 | "noFallthroughCasesInSwitch": true, 22 | 23 | // Some stricter flags 24 | "noUnusedLocals": true, 25 | "noUnusedParameters": true, 26 | "noPropertyAccessFromIndexSignature": true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /templates/deno/.envrc: -------------------------------------------------------------------------------- 1 | set -e 2 | set +u 3 | 4 | use flake 5 | 6 | dotenv_if_exists 7 | 8 | watch_file .env deno.jsonc 9 | -------------------------------------------------------------------------------- /templates/deno/deno.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "start": "deno run src/index.ts", 4 | "test": "deno test --allow-net", 5 | "lint": "deno lint", 6 | "format": "deno fmt", 7 | }, 8 | "fmt": { 9 | "useTabs": true, 10 | "lineWidth": 80, 11 | "indentWidth": 2, 12 | "semiColons": false, 13 | "singleQuote": true, 14 | "proseWrap": "always", 15 | "include": ["src/"], 16 | "unstableComponent": true, 17 | "unstableCss": true, 18 | "unstableHtml": true, 19 | "unstableYaml": true, 20 | "unstableSql": true, 21 | // "exclude": ["src/testdata/", "src/fixtures/**/*.ts"] 22 | }, 23 | "exclude": ["dist/"], 24 | } 25 | -------------------------------------------------------------------------------- /templates/deno/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | systems.url = "github:nix-systems/default"; 5 | flake-utils = { 6 | url = "github:numtide/flake-utils"; 7 | inputs.systems.follows = "systems"; 8 | }; 9 | }; 10 | 11 | outputs = { 12 | self, 13 | nixpkgs, 14 | flake-utils, 15 | ... 16 | } @ inputs: 17 | flake-utils.lib.eachDefaultSystem ( 18 | system: let 19 | pkgs = import nixpkgs { 20 | inherit system; 21 | config.allowUnfree = true; 22 | }; 23 | in { 24 | formatter = pkgs.alejandra; 25 | devShells.default = pkgs.mkShell { 26 | buildInputs = with pkgs; [ 27 | deno 28 | ]; 29 | shellHook = '' 30 | deno eval 'console.log(Deno.version)' 31 | ''; 32 | }; 33 | } 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /templates/go/.envrc: -------------------------------------------------------------------------------- 1 | set -e 2 | set +u 3 | 4 | use flake 5 | 6 | dotenv_if_exists 7 | 8 | watch_file .env 9 | 10 | # layout go 11 | -------------------------------------------------------------------------------- /templates/go/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | systems.url = "github:nix-systems/default"; 5 | flake-utils = { 6 | url = "github:numtide/flake-utils"; 7 | inputs.systems.follows = "systems"; 8 | }; 9 | }; 10 | 11 | outputs = { 12 | self, 13 | nixpkgs, 14 | flake-utils, 15 | ... 16 | } @ inputs: 17 | flake-utils.lib.eachDefaultSystem ( 18 | system: let 19 | pkgs = import nixpkgs { 20 | inherit system; 21 | config.allowUnfree = true; 22 | }; 23 | in { 24 | formatter = pkgs.alejandra; 25 | devShells.default = pkgs.mkShell { 26 | buildInputs = with pkgs; [ 27 | go 28 | gopls 29 | go-tools # staticcheck, etc... 30 | gomodifytags 31 | gotools # goimports 32 | ]; 33 | shellHook = '' 34 | ''; 35 | }; 36 | } 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /templates/node/.envrc: -------------------------------------------------------------------------------- 1 | set -e 2 | set +u 3 | 4 | use flake 5 | 6 | dotenv_if_exists 7 | 8 | watch_file .env .nvmrc .node-version 9 | 10 | use node "$__DIRENV_NODE_VERSION__" 11 | 12 | # layout node 13 | -------------------------------------------------------------------------------- /templates/node/.nvmrc: -------------------------------------------------------------------------------- 1 | 22 2 | -------------------------------------------------------------------------------- /templates/node/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | systems.url = "github:nix-systems/default"; 5 | flake-utils = { 6 | url = "github:numtide/flake-utils"; 7 | inputs.systems.follows = "systems"; 8 | }; 9 | }; 10 | 11 | outputs = { 12 | self, 13 | nixpkgs, 14 | flake-utils, 15 | ... 16 | } @ inputs: 17 | flake-utils.lib.eachDefaultSystem ( 18 | system: let 19 | pkgs = import nixpkgs { 20 | inherit system; 21 | config.allowUnfree = true; 22 | }; 23 | in { 24 | formatter = pkgs.alejandra; 25 | devShells.default = pkgs.mkShell { 26 | buildInputs = with pkgs; [ 27 | volta 28 | nodePackages.pnpm 29 | ]; 30 | shellHook = 31 | /* 32 | bash 33 | */ 34 | '' 35 | if [[ ! -d "$HOME/.volta" ]]; then 36 | mkdir -p "$HOME/.volta" 37 | fi 38 | 39 | export VOLTA_HOME="$HOME/.volta"; 40 | export PATH="$VOLTA_HOME/bin:$PATH" 41 | export NODE_VERSIONS="$VOLTA_HOME/tools/image/node" 42 | export NODE_VERSION_PREFIX="" 43 | export __DIRENV_NODE_VERSION__="" 44 | 45 | if [ -f "./.nvmrc" ]; then 46 | __DIRENV_NODE_VERSION__="$(<./.nvmrc)" 47 | elif [ -f "./.node-version" ]; then 48 | __DIRENV_NODE_VERSION__="$(<./.node-version)" 49 | fi 50 | 51 | volta install node@"$__DIRENV_NODE_VERSION__" 52 | ''; 53 | }; 54 | } 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /templates/plain/.envrc: -------------------------------------------------------------------------------- 1 | set -e 2 | set +u 3 | 4 | use flake 5 | 6 | dotenv_if_exists 7 | 8 | watch_file .env 9 | -------------------------------------------------------------------------------- /templates/plain/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | systems.url = "github:nix-systems/default"; 5 | flake-utils = { 6 | url = "github:numtide/flake-utils"; 7 | inputs.systems.follows = "systems"; 8 | }; 9 | }; 10 | 11 | outputs = { 12 | self, 13 | nixpkgs, 14 | flake-utils, 15 | ... 16 | } @ inputs: 17 | flake-utils.lib.eachDefaultSystem ( 18 | system: let 19 | pkgs = import nixpkgs { 20 | inherit system; 21 | config.allowUnfree = true; 22 | }; 23 | in { 24 | formatter = pkgs.alejandra; 25 | devShells.default = pkgs.mkShell { 26 | buildInputs = with pkgs; [hello]; 27 | shellHook = 28 | /* 29 | bash 30 | */ 31 | '' 32 | ${pkgs.hello}/bin/hello 33 | ''; 34 | }; 35 | } 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /templates/python-script/.envrc: -------------------------------------------------------------------------------- 1 | set -e 2 | set +u 3 | 4 | PATH_add "$HOME/.local/share/../bin" 5 | 6 | use flake 7 | 8 | dotenv_if_exists 9 | 10 | watch_file .env .python-version pyproject.toml 11 | 12 | # layout python 13 | -------------------------------------------------------------------------------- /templates/python-script/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | systems.url = "github:nix-systems/default"; 5 | flake-utils = { 6 | url = "github:numtide/flake-utils"; 7 | inputs.systems.follows = "systems"; 8 | }; 9 | }; 10 | 11 | outputs = { 12 | self, 13 | nixpkgs, 14 | flake-utils, 15 | ... 16 | } @ inputs: 17 | flake-utils.lib.eachDefaultSystem ( 18 | system: let 19 | pkgs = import nixpkgs { 20 | inherit system; 21 | config.allowUnfree = true; 22 | }; 23 | in { 24 | formatter = pkgs.alejandra; 25 | devShells.default = pkgs.mkShell { 26 | buildInputs = with pkgs; [ 27 | uv 28 | ]; 29 | shellHook = 30 | /* 31 | bash 32 | */ 33 | ''uv init --script main.py''; 34 | }; 35 | } 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /templates/python/.envrc: -------------------------------------------------------------------------------- 1 | set -e 2 | set +u 3 | 4 | # $UV_TOOL_DIR 5 | 6 | PATH_add "$HOME/.local/share/../bin" 7 | 8 | use flake 9 | 10 | dotenv_if_exists 11 | 12 | watch_file .env .python-version pyproject.toml 13 | 14 | # layout python 15 | -------------------------------------------------------------------------------- /templates/python/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 4 | systems.url = "github:nix-systems/default"; 5 | flake-utils = { 6 | url = "github:numtide/flake-utils"; 7 | inputs.systems.follows = "systems"; 8 | }; 9 | }; 10 | 11 | outputs = { 12 | self, 13 | nixpkgs, 14 | flake-utils, 15 | ... 16 | } @ inputs: 17 | flake-utils.lib.eachDefaultSystem ( 18 | system: let 19 | pkgs = import nixpkgs { 20 | inherit system; 21 | config.allowUnfree = true; 22 | }; 23 | in { 24 | formatter = pkgs.alejandra; 25 | devShells.default = pkgs.mkShell { 26 | buildInputs = with pkgs; [ 27 | uv 28 | ]; 29 | shellHook = 30 | /* 31 | bash 32 | */ 33 | '' 34 | if [ ! -f ./pyproject.toml ]; then 35 | uv init --author-from git 36 | 37 | # in order to make sure pyright LSP plays well 38 | cat <> pyproject.toml 39 | 40 | [tool.pyright] 41 | venvPath = "." 42 | venv = ".venv" 43 | EOF 44 | 45 | uv tool install ruff 46 | uv tool install pyright 47 | fi 48 | ''; 49 | }; 50 | } 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /templates/readme.md: -------------------------------------------------------------------------------- 1 | # My flakes templates 2 | 3 | To quickly use inside projects or use to start new ones. 4 | 5 | ```bash 6 | nix flake init --template 'github:ahmedelgabri/dotfiles#