├── .gitignore ├── fish ├── functions │ ├── fish_mode_prompt.fish │ ├── nvm.fish │ ├── fish_right_prompt.fish │ ├── fish_user_key_bindings.fish │ ├── klg.fish │ ├── ksh.fish │ ├── ke.fish │ ├── nvm_find_nvmrc.fish │ ├── fish_greeting.fish │ ├── dplg.fish │ ├── hplib │ │ ├── err.fish │ │ ├── print_header.fish │ │ ├── fzf_search.fish │ │ ├── ifzf_search.fish │ │ ├── get_pod_list.fish │ │ ├── get_k8s_containers.fish │ │ ├── port_forward_k8s_pod.fish │ │ ├── get_k8s_namespace.fish │ │ ├── k8s_errors.fish │ │ ├── get_k8s_pod.fish │ │ ├── get_k8s_container_logs.fish │ │ ├── get_short_name.fish │ │ └── get_k8s_container.fish │ ├── gfs.fish │ ├── cpd.fish │ ├── fish_prompt.fish │ ├── gup.fish │ ├── gap.fish │ ├── pr.fish │ ├── load_nvm.fish │ ├── getenv.fish │ ├── kdp.fish │ ├── grs.fish │ ├── kd.fish │ ├── grb.fish │ ├── gdb.fish │ ├── dbss.fish │ ├── vim_rg.fish │ ├── kpf.fish │ ├── gco.fish │ ├── sdk.fish │ ├── dbcbs.fish │ ├── fp.fish │ ├── pcl.fish │ ├── dbsms.fish │ ├── dbaq.fish │ ├── prfzf.fish │ ├── dbar.fish │ ├── fzf_key_bindings.fish │ └── fisher.fish ├── print_256_colors.fish ├── tmux_wind_project.fish └── config.fish ├── nvim ├── stylua.toml ├── init.lua ├── lua │ ├── plugins │ │ ├── render-markdown.lua │ │ ├── todo-comments.lua │ │ ├── nvim-lspconfig.lua │ │ ├── nvim-neotree.lua │ │ ├── nvim-focus.lua │ │ ├── nvim-treesitter.lua │ │ ├── tiny-inline-diagnostic.nvim.lua │ │ ├── noice-nvim.lua │ │ ├── autosave.nvim.lua │ │ ├── formatter.lua │ │ ├── others.lua │ │ ├── obsidian-nvim.lua │ │ ├── colorscheme.lua │ │ └── example.lua │ └── config │ │ ├── autocmds.lua │ │ ├── options.lua │ │ ├── lazy.lua │ │ └── keymaps.lua ├── README.md ├── .neoconf.json ├── lazyvim.json ├── lazy-lock.json └── LICENSE ├── Raycast.rayconfig ├── tmux ├── mac-battery-percentage.sh ├── switch-tmux-session.fish ├── switch-tmux-window.fish └── tmux.conf ├── crontab.fish ├── README.md ├── mycli └── my.cnf ├── wezterm ├── .luarc.json ├── plugins.lua ├── colors.lua ├── get-git-dir.lua ├── utils.lua ├── tab-format.lua ├── wezterm.lua ├── status-bar.lua └── keymappings.lua ├── jetbrains └── ideavimrc ├── alfred ├── README.md └── prefs.plist ├── install ├── brew_install.sh └── setup_configs.fish ├── mac-keybindings └── DefaultKeyBinding.dict ├── git ├── repeat │ └── hooks │ │ ├── commit-msg │ │ ├── pre-commit │ │ └── prepare-commit-msg ├── gitmux.yml ├── gitconfig └── gitui │ └── key_bindings.ron ├── alacritty.toml ├── ghostty └── config ├── install.sh ├── learn-english.py ├── run.lua ├── myclirc └── posts └── raycast.md /.gitignore: -------------------------------------------------------------------------------- 1 | fish/print_256_colors.bash 2 | -------------------------------------------------------------------------------- /fish/functions/fish_mode_prompt.fish: -------------------------------------------------------------------------------- 1 | function fish_mode_prompt 2 | 3 | end 4 | -------------------------------------------------------------------------------- /nvim/stylua.toml: -------------------------------------------------------------------------------- 1 | indent_type = "Spaces" 2 | indent_width = 2 3 | column_width = 120 -------------------------------------------------------------------------------- /Raycast.rayconfig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haphamdev/dot-files/HEAD/Raycast.rayconfig -------------------------------------------------------------------------------- /nvim/init.lua: -------------------------------------------------------------------------------- 1 | -- bootstrap lazy.nvim, LazyVim and your plugins 2 | require("config.lazy") 3 | -------------------------------------------------------------------------------- /tmux/mac-battery-percentage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/bash 2 | pmset -g batt | grep -Eo "\d+%" 3 | -------------------------------------------------------------------------------- /fish/functions/nvm.fish: -------------------------------------------------------------------------------- 1 | function nvm 2 | bass source ~/.nvm/nvm.sh --no-use ';' nvm $argv 3 | end 4 | -------------------------------------------------------------------------------- /fish/functions/fish_right_prompt.fish: -------------------------------------------------------------------------------- 1 | function fish_right_prompt 2 | #intentionally left blank 3 | end 4 | -------------------------------------------------------------------------------- /fish/functions/fish_user_key_bindings.fish: -------------------------------------------------------------------------------- 1 | function fish_user_key_bindings 2 | fzf_key_bindings 3 | end 4 | -------------------------------------------------------------------------------- /fish/functions/klg.fish: -------------------------------------------------------------------------------- 1 | function klg -d "Get log of a pod (container if needed)" 2 | ~/projects/klg/klg.sh $argv 3 | end 4 | -------------------------------------------------------------------------------- /fish/functions/ksh.fish: -------------------------------------------------------------------------------- 1 | function ksh -d "Start sh for a container in k8s pod" 2 | ~/projects/klg/ksh.sh $argv 3 | end 4 | -------------------------------------------------------------------------------- /crontab.fish: -------------------------------------------------------------------------------- 1 | #!/opt/homebrew/bin/fish 2 | 3 | tmux display-message -d 10000 "$(python3 ~/projects/dot-files/learn-english.py)" 4 | -------------------------------------------------------------------------------- /fish/functions/ke.fish: -------------------------------------------------------------------------------- 1 | function ke -d "Execute a command for a container in a K8s pod" 2 | ~/projects/klg/ke.sh $argv 3 | end 4 | -------------------------------------------------------------------------------- /fish/functions/nvm_find_nvmrc.fish: -------------------------------------------------------------------------------- 1 | function nvm_find_nvmrc 2 | bass source ~/.nvm/nvm.sh --no-use ';' nvm_find_nvmrc 3 | end 4 | -------------------------------------------------------------------------------- /fish/functions/fish_greeting.fish: -------------------------------------------------------------------------------- 1 | function fish_greeting 2 | # This function is intentionally left blank 3 | # to remove fish greeting message 4 | end 5 | -------------------------------------------------------------------------------- /fish/functions/dplg.fish: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/fish 2 | function dplg -d "Delete monolith log" 3 | echo -n "" > ~/projects/personio/app/storage/logs/laravel.log 4 | end 5 | -------------------------------------------------------------------------------- /fish/functions/hplib/err.fish: -------------------------------------------------------------------------------- 1 | function err -d "Print message to error output" 2 | echo 🔥 Error: $argv >&2 3 | # echo Stack trace: (status stack-trace) >&2 4 | end 5 | -------------------------------------------------------------------------------- /fish/functions/gfs.fish: -------------------------------------------------------------------------------- 1 | function gfs -d "Git actions with fuzzy search" 2 | 3 | end 4 | 5 | function get_current_brach 6 | end 7 | 8 | function get_all_branches 9 | end 10 | -------------------------------------------------------------------------------- /nvim/lua/plugins/render-markdown.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "MeanderingProgrammer/render-markdown.nvim", 3 | opts = { 4 | checkbox = { 5 | enabled = true, 6 | }, 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /nvim/README.md: -------------------------------------------------------------------------------- 1 | # 💤 LazyVim 2 | 3 | A starter template for [LazyVim](https://github.com/LazyVim/LazyVim). 4 | Refer to the [documentation](https://lazyvim.github.io/installation) to get started. 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dot-files 2 | My dot-files dedicated for Mac OS. Fish is used as primary shell. 3 | 4 | # Installation 5 | ``` 6 | curl https://raw.githubusercontent.com/fanliver/dot-files/master/install.sh | sh 7 | ``` 8 | 9 | -------------------------------------------------------------------------------- /mycli/my.cnf: -------------------------------------------------------------------------------- 1 | [client] 2 | pager="nvim -u ~/.config/nvim/plugged/vim-tmux-navigator/plugin/tmux_navigator.vim +2 -c 'set nomod|set scrollopt=hor|set nowrap|set nomodifiable|nnoremap qq :qa|1split|windo set scrollbind|wincmd j' -" 3 | -------------------------------------------------------------------------------- /tmux/switch-tmux-session.fish: -------------------------------------------------------------------------------- 1 | #!/opt/homebrew/bin/fish 2 | 3 | tmux switch-client -t (tmux list-session | awk -F: '{print $1}' | grep -v (tmux display-message -p '#S') | fzf --reverse --header="Select Tmux Session:"; or exit 0) 4 | 5 | -------------------------------------------------------------------------------- /wezterm/.luarc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json", 3 | "workspace.library": ["./wezterm"], 4 | "runtime.version": "Lua 5.3", 5 | "hint.enable": true 6 | } 7 | 8 | -------------------------------------------------------------------------------- /fish/functions/hplib/print_header.fish: -------------------------------------------------------------------------------- 1 | function print_header 2 | if test (count $argv) -eq 0 3 | return 4 | end 5 | 6 | echo 7 | set_color yellow 8 | echo $argv[1] 9 | set_color normal 10 | end 11 | -------------------------------------------------------------------------------- /nvim/lua/plugins/todo-comments.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "folke/todo-comments.nvim", 3 | opts = { 4 | keywords = { 5 | QUESTION = { 6 | icon = "?", 7 | color = "hint", 8 | }, 9 | }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /nvim/lua/config/autocmds.lua: -------------------------------------------------------------------------------- 1 | -- Autocmds are automatically loaded on the VeryLazy event 2 | -- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua 3 | -- Add any additional autocmds here 4 | -------------------------------------------------------------------------------- /nvim/lua/plugins/nvim-lspconfig.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "neovim/nvim-lspconfig", 3 | opts = { 4 | servers = { 5 | prismals = {}, 6 | dockerls = {}, 7 | docker_compose_language_service = {}, 8 | }, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /nvim/.neoconf.json: -------------------------------------------------------------------------------- 1 | { 2 | "neodev": { 3 | "library": { 4 | "enabled": true, 5 | "plugins": true 6 | } 7 | }, 8 | "neoconf": { 9 | "plugins": { 10 | "lua_ls": { 11 | "enabled": true 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /jetbrains/ideavimrc: -------------------------------------------------------------------------------- 1 | " Use jj to exit insert mode, disable 2 | inoremap jj 3 | inoremap 4 | 5 | " Jump to start and end of line using the home row keys 6 | map H ^ 7 | map L $ 8 | 9 | set number relativenumber 10 | set ignorecase 11 | set so=5 12 | -------------------------------------------------------------------------------- /nvim/lua/plugins/nvim-neotree.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-neo-tree/neo-tree.nvim", 3 | keys = { 4 | { 5 | "e", 6 | "Neotree toggle float reveal", 7 | desc = "Reveal current file in Neotree float window", 8 | }, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /wezterm/plugins.lua: -------------------------------------------------------------------------------- 1 | local wezterm = require 'wezterm' 2 | local module = {} 3 | 4 | function module.apply_to_config(config) 5 | wezterm.plugin.require("https://github.com/mrjones2014/smart-splits.nvim.git").apply_to_config(config) 6 | end 7 | 8 | return module 9 | 10 | 11 | -------------------------------------------------------------------------------- /fish/functions/hplib/fzf_search.fish: -------------------------------------------------------------------------------- 1 | function fzf_search -d "Non-interactive fuzzy search" 2 | # Args: keyword, values 3 | 4 | set keyword $argv[1] 5 | set -e argv[1] 6 | set values $argv 7 | 8 | printf %s\n $values | fzf --filter $keyword | head -n1 9 | end 10 | -------------------------------------------------------------------------------- /nvim/lua/config/options.lua: -------------------------------------------------------------------------------- 1 | -- Options are automatically loaded before lazy.nvim startup 2 | -- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua 3 | -- Add any additional options here 4 | vim.opt.mouse = "" 5 | vim.opt.clipboard = "" 6 | -------------------------------------------------------------------------------- /alfred/README.md: -------------------------------------------------------------------------------- 1 | Copy pref.plist to `/Users/hapham/Library/Application Support/Alfred/Alfred.alfredpreferences/preferences/features/websearch` 2 | 3 | ``` 4 | cp ~/projects/dot-files/alfred/prefs.plist ~/Library/Application Support/Alfred/Alfred.alfredpreferences/preferences/features/websearch/ 5 | ``` 6 | -------------------------------------------------------------------------------- /fish/functions/hplib/ifzf_search.fish: -------------------------------------------------------------------------------- 1 | function ifzf_search -d "Interactive fuzzy search" 2 | # Args: header, values 3 | 4 | set header $argv[1] 5 | set -e argv[1] 6 | set values $argv 7 | printf %s\n $values | awk NF | fzf -1 --border --header="$header" --height=15 --reverse 8 | end 9 | -------------------------------------------------------------------------------- /fish/functions/cpd.fish: -------------------------------------------------------------------------------- 1 | function cpd -d "Copy k8s pod name to clipboard" 2 | echo Please select a pod: 3 | kubectl get pods --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' --all-namespaces |\ 4 | fzf --height=15 --border | read pod; 5 | echo $pod | pbcopy 6 | echo "✅ Pod '$pod' is copied" 7 | end 8 | -------------------------------------------------------------------------------- /nvim/lua/plugins/nvim-focus.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-focus/focus.nvim", 3 | version = false, 4 | opts = { 5 | autoresize = { enable = false }, 6 | ui = { 7 | signcolumn = false, 8 | relativenumber = true, 9 | absolutenumber_unfocussed = true, 10 | }, 11 | }, 12 | event = "BufEnter", 13 | } 14 | -------------------------------------------------------------------------------- /wezterm/colors.lua: -------------------------------------------------------------------------------- 1 | local module = {} 2 | 3 | 4 | module.primary = "#FFFFFF" 5 | module.secondary = "#FFFFFF" 6 | module.alternative = "#EBFFE3" 7 | module.disabled = "#9C9C9C" 8 | module.primaryBackground = "#278F78" 9 | module.secondaryBackground = "#2D574A" 10 | module.alternativeBackground = "#2C3832" 11 | module.statusBarBackground = module.alternativeBackground 12 | 13 | return module 14 | -------------------------------------------------------------------------------- /fish/functions/fish_prompt.fish: -------------------------------------------------------------------------------- 1 | # name: Zish 2 | 3 | function fish_prompt 4 | set_color -b 414540 5 | set_color -o blue 6 | printf '%s' (whoami) 7 | set_color $fish_color_autosuggestion[1] 8 | printf ' in ' 9 | set_color -o green 10 | printf '%s' (prompt_pwd -d 3 -D 3) 11 | 12 | set_color normal 13 | set_color yellow 14 | printf '\n> ' 15 | set_color normal 16 | end 17 | -------------------------------------------------------------------------------- /fish/print_256_colors.fish: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/fish 2 | set current_dir (dirname (status --current-filename)) 3 | set print_color_script $current_dir/print_256_colors.bash 4 | 5 | if not test -e $print_color_script 6 | echo "Downloading script..." 7 | curl -s https://gist.githubusercontent.com/HaleTom/89ffe32783f89f403bba96bd7bcd1263/raw/ -o $print_color_script 8 | end 9 | 10 | bash $print_color_script 11 | -------------------------------------------------------------------------------- /tmux/switch-tmux-window.fish: -------------------------------------------------------------------------------- 1 | #!/opt/homebrew/bin/fish 2 | set SELECTED_WINDOW (tmux list-window -F "#{window_index} - #{window_name}" | grep -v (tmux display-message -p '#W')\ 3 | | fzf --reverse --header="Select Tmux Window:" | awk -F- '{print $1}'| awk '{$1=$1};1') 4 | 5 | if test -z "$SELECTED_WINDOW" 6 | exit 0 #No window was selected, do nothing and exit 7 | end 8 | 9 | tmux select-window -t $SELECTED_WINDOW 10 | 11 | -------------------------------------------------------------------------------- /nvim/lua/plugins/nvim-treesitter.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-treesitter/nvim-treesitter", 3 | opts = { 4 | ensure_installed = { "prisma" }, 5 | incremental_selection = { 6 | enable = true, 7 | keymaps = { 8 | init_selection = "", 9 | node_incremental = "", 10 | scope_incremental = false, 11 | node_decremental = "", 12 | }, 13 | }, 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /fish/functions/hplib/get_pod_list.fish: -------------------------------------------------------------------------------- 1 | function get_pod_list -d "Get the list of K8s pods" 2 | # Args: namespace 3 | argparse 'n/namespace=' -- $argv 4 | 5 | if set -q _flag_namespace 6 | kubectl get pods --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' --namespace $_flag_namespace 7 | else 8 | kubectl get pods --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /fish/functions/gup.fish: -------------------------------------------------------------------------------- 1 | function gup -d "Set upstream for a git branch" 2 | git rev-parse --is-inside-work-tree 2> /dev/null 1>&2 3 | set -l git_error $status 4 | if test $git_error -ne 0 5 | echo 'Not in git repository' 6 | return 7 | end 8 | 9 | git branch --show-current | read current_branch 10 | echo "Your current branch is '$current_branch'" 11 | 12 | git branch -u origin/$current_branch 13 | end 14 | -------------------------------------------------------------------------------- /nvim/lua/plugins/tiny-inline-diagnostic.nvim.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "rachartier/tiny-inline-diagnostic.nvim", 4 | event = "VeryLazy", -- Or `LspAttach` 5 | priority = 1000, -- needs to be loaded in first 6 | opts = { 7 | options = { 8 | throttle = 200, 9 | }, 10 | }, 11 | }, 12 | { 13 | "neovim/nvim-lspconfig", 14 | opts = function(_, opts) 15 | opts.diagnostics.virtual_text = false 16 | end, 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /install/brew_install.sh: -------------------------------------------------------------------------------- 1 | brew install \ 2 | bash \ 3 | fish \ 4 | aws-cdk \ 5 | awscli \ 6 | bat \ 7 | curl \ 8 | eza \ 9 | fd \ 10 | fzf \ 11 | git \ 12 | git-delta \ 13 | gitui \ 14 | glow \ 15 | go \ 16 | htop \ 17 | httpie \ 18 | jj \ 19 | jq \ 20 | lazygit \ 21 | less \ 22 | lnav \ 23 | lua \ 24 | lua-language-server \ 25 | mycli \ 26 | neovim \ 27 | pgcli \ 28 | python3 \ 29 | ripgrep \ 30 | sd \ 31 | tree-sitter \ 32 | watch \ 33 | yq \ 34 | orbstack 35 | -------------------------------------------------------------------------------- /fish/functions/hplib/get_k8s_containers.fish: -------------------------------------------------------------------------------- 1 | function get_k8s_containers -d "Get all containers of a pod" 2 | argparse 'n/namespace=' 'p/pod=' -- $argv 3 | 4 | if set -q _flag_namespace 5 | set arg_namespace '-n' $_flag_namespace 6 | end 7 | 8 | if set -q _flag_pod 9 | set arg_pod '-p' $_flag_pod 10 | else 11 | return (k8s_errors POD_MISSING) 12 | end 13 | 14 | kubectl get pods $_flag_pod $arg_namespace -o jsonpath='{range .spec.containers[*]}{.name}{"\n"}' 15 | end 16 | 17 | -------------------------------------------------------------------------------- /nvim/lua/plugins/noice-nvim.lua: -------------------------------------------------------------------------------- 1 | -- There is no big config in noice.nvim 2 | -- Just want to get rid of this issue https://github.com/yioneko/vtsls/issues/159 3 | -- This should be removed when the issue is fixed 4 | return { 5 | "folke/noice.nvim", 6 | event = "VeryLazy", 7 | opts = { 8 | routes = { 9 | { 10 | filter = { 11 | event = "notify", 12 | find = "Request textDocument/inlayHint failed", 13 | }, 14 | opts = { skip = true }, 15 | }, 16 | }, 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /mac-keybindings/DefaultKeyBinding.dict: -------------------------------------------------------------------------------- 1 | { 2 | "\UF729" = moveToBeginningOfLine:; // home 3 | "\UF72B" = moveToEndOfLine:; // end 4 | "$\UF729" = moveToBeginningOfLineAndModifySelection:; // shift-home 5 | "$\UF72B" = moveToEndOfLineAndModifySelection:; // shift-end 6 | "^\UF729" = moveToBeginningOfDocument:; // ctrl-home 7 | "^\UF72B" = moveToEndOfDocument:; // ctrl-end 8 | "^$\UF729" = moveToBeginningOfDocumentAndModifySelection:; // ctrl-shift-home 9 | "^$\UF72B" = moveToEndOfDocumentAndModifySelection:; // ctrl-shift-end 10 | } 11 | -------------------------------------------------------------------------------- /nvim/lua/plugins/autosave.nvim.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "okuuva/auto-save.nvim", 3 | version = "^1.0.0", -- see https://devhints.io/semver, alternatively use '*' to use the latest tagged release 4 | cmd = "ASToggle", -- optional for lazy loading on command 5 | event = { "InsertLeave", "TextChanged" }, -- optional for lazy loading on trigger events 6 | config = function() -- Somehow, LazyNvim does not invoke setup for this plugin. I need this 'config' to run setup 7 | require("auto-save").setup({ 8 | debounce_delay = 1000, 9 | }) 10 | end, 11 | } 12 | -------------------------------------------------------------------------------- /fish/functions/gap.fish: -------------------------------------------------------------------------------- 1 | function gap -d "apply patch to current git repository" 2 | if test (count $argv) -gt 0 3 | ls $HOME/git-patches/ | tr " " "\n" | fzf --filter $argv[1] | read result 4 | else 5 | ls $HOME/git-patches/ | tr " " "\n" | fzf --border --height=50% | read result 6 | end 7 | 8 | if test $status -ne 0 9 | echo "Cancelled or no git patch was selected" 10 | return 1 11 | end 12 | 13 | set -l path "$HOME/git-patches/$result" 14 | echo "Applying patch '$path'" 15 | git apply $path 16 | end 17 | -------------------------------------------------------------------------------- /fish/functions/pr.fish: -------------------------------------------------------------------------------- 1 | # A funtion to jump to or open a directory in $HOME/projects using vs code or nvim with auto completion. 2 | function pr -d "Go to project in ,HOME/projects" 3 | switch $argv[1] 4 | case o e v vim nvim 5 | nvim $HOME/projects/$argv[2] 6 | case c code vscode 7 | code $HOME/projects/$argv[2] 8 | case '*' 9 | cd $HOME/projects/$argv[2] 10 | end 11 | end 12 | 13 | set -l project_paths (ls -d $HOME/projects/*/ | sed -E 's|\/$||' | sed -E 's|.*\/||') 14 | complete -f -c pr -a "$project_paths" 15 | 16 | -------------------------------------------------------------------------------- /fish/functions/hplib/port_forward_k8s_pod.fish: -------------------------------------------------------------------------------- 1 | function port_forward_k8s_pod -d "Port-forward a k8s pod" 2 | argparse 'n/namespace=' 'p/pod=' 'P/port=' -- $argv 3 | 4 | if set -q _flag_namespace 5 | set arg_namespace '--namespace' $_flag_namespace 6 | end 7 | 8 | if not set -q _flag_pod 9 | return (k8s_errors POD_MISSING) 10 | end 11 | 12 | if not set -q _flag_port 13 | return (k8s_errors PORT_MISSING) 14 | end 15 | 16 | echo "🚀 Forwarding port $_flag_port for pod '$_flag_pod'" 17 | kubectl port-forward $arg_namespace $_flag_pod $_flag_port 18 | end 19 | -------------------------------------------------------------------------------- /git/repeat/hooks/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the commit message from the file passed as the first argument 4 | commit_msg_file="$1" 5 | commit_msg=$(cat "$commit_msg_file") 6 | 7 | if [[ "$commit_msg" == Merge\ branch* ]]; then 8 | echo "Skipping commit-msg hook for merge commit." 9 | exit 0 10 | fi 11 | 12 | if ! [[ "$commit_msg" =~ ^RPT-[0-9]+:\ .+ ]]; then 13 | echo "Error: Commit message '$commit_msg' does not match the required format." 14 | echo "Commit messages must be prefixed with 'RPT-xxxx: '" 15 | echo "Example: 'RPT-1234: Filter user by status'" 16 | exit 1 17 | fi 18 | 19 | exit 0 20 | -------------------------------------------------------------------------------- /fish/functions/load_nvm.fish: -------------------------------------------------------------------------------- 1 | function load_nvm --on-variable="PWD" 2 | set -l default_node_version (nvm version default) 3 | set -l node_version (nvm version) 4 | set -l nvmrc_path (nvm_find_nvmrc) 5 | if test -n "$nvmrc_path" 6 | set -l nvmrc_node_version (nvm version (cat $nvmrc_path)) 7 | if test "$nvmrc_node_version" = "N/A" 8 | nvm install (cat $nvmrc_path) 9 | else if test "$nvmrc_node_version" != "$node_version" 10 | nvm use $nvmrc_node_version 11 | end 12 | else if test "$node_version" != "$default_node_version" 13 | echo "Reverting to default Node version" 14 | nvm use default 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /git/gitmux.yml: -------------------------------------------------------------------------------- 1 | tmux: 2 | symbols: 3 | branch: '⎇ ' 4 | hashprefix: ':' 5 | ahead: ↑· 6 | behind: ↓· 7 | staged: ● 8 | conflict: '✖ ' 9 | modified: '✚ ' 10 | untracked: … 11 | stashed: '⚑ ' 12 | clean: ✔ 13 | styles: 14 | state: '#[fg=yellow,bold]' 15 | branch: '#[fg=cyan,bold]' 16 | remote: '#[fg=cyan]' 17 | staged: '#[fg=green,bold]' 18 | conflict: '#[fg=red,bold]' 19 | modified: '#[fg=red,bold]' 20 | untracked: '#[fg=magenta,bold]' 21 | stashed: '#[fg=cyan,bold]' 22 | clean: '#[fg=green,bold]' 23 | layout: [branch,' ', flags] 24 | options: 25 | branch_max_len: 50 26 | -------------------------------------------------------------------------------- /fish/functions/hplib/get_k8s_namespace.fish: -------------------------------------------------------------------------------- 1 | function get_k8s_namespace -d "Pick a K8s namespace using fuzzy search" 2 | set namespaces (kubectl get namespaces --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}') 3 | 4 | if test $status -ne 0 5 | k8s_errors NAMESPACE_NOT_FOUND 6 | end 7 | 8 | if test (count $argv) -eq 0 9 | set namespace (ifzf_search 'Please select a namespace:' $namespaces) 10 | else 11 | set namespace (fzf_search $argv[1] $namespaces) 12 | end 13 | 14 | if test -z $namespace 15 | return (k8s_errors NAMESPACE_NOT_FOUND) 16 | else 17 | echo $namespace 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /fish/functions/hplib/k8s_errors.fish: -------------------------------------------------------------------------------- 1 | function k8s_errors -d "Return the error code for the error name" 2 | # Args: error name 3 | set -l error_name $argv[1] 4 | 5 | switch $error_name 6 | case POD_MISSING 7 | echo 1 8 | case POD_NOT_FOUND 9 | echo 2 10 | case NAMESPACE_NOT_FOUND 11 | echo 3 12 | case CONTAINER_NOT_FOUND 13 | echo 4 14 | case CONTAINER_MISSING 15 | echo 5 16 | case PORT_MISSING 17 | echo 6 18 | 19 | case NOT_ENOUGH_ARGUMENT 20 | echo 200 21 | 22 | case '*' 23 | echo 255 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /git/gitconfig: -------------------------------------------------------------------------------- 1 | [user] 2 | email = ha@repeat.gg 3 | name = Ha Pham 4 | signingkey = F8B3EAE076FD4841 5 | [gpg] 6 | program = /opt/homebrew/bin/gpg 7 | [commit] 8 | gpgsign = true 9 | [push] 10 | default = current 11 | autoSetupRemote = true 12 | 13 | [core] 14 | pager = delta 15 | autocrlf = input 16 | editor = /opt/homebrew/bin/nvim 17 | 18 | [interactive] 19 | diffFilter = delta --color-only 20 | 21 | [delta] 22 | features = side-by-side line-numbers decorations 23 | whitespace-error-style = 22 reverse 24 | 25 | [delta "decorations"] 26 | commit-decoration-style = bold yellow box ul 27 | file-style = bold yellow ul 28 | file-decoration-style = none 29 | -------------------------------------------------------------------------------- /fish/functions/getenv.fish: -------------------------------------------------------------------------------- 1 | function getenv -d "Copy envariable from ./gradlew.local. It can be pasted to Intellij configuration" 2 | # get all export lines from docker environments 3 | set -l envs ( 4 | set -l SHELL bash; 5 | minikube -p minikube docker-env | 6 | grep export | 7 | awk '{print($2)}' | 8 | tr '\n' ';' 9 | ) 10 | 11 | # append with all export lines from gradlew.local 12 | set -l envs $envs(cat ./gradlew.local | 13 | grep export | 14 | awk '{print($2)}' | 15 | tr '\n' ';' 16 | ) 17 | 18 | echo $envs | tr -d '"' | pbcopy 19 | echo "Environment variables are copied." 20 | end 21 | -------------------------------------------------------------------------------- /alacritty.toml: -------------------------------------------------------------------------------- 1 | [colors] 2 | draw_bold_text_with_bright_colors = true 3 | 4 | [font] 5 | size = 11.0 6 | 7 | [font.bold] 8 | family = "DejaVuSansM Nerd Font" 9 | style = "Bold" 10 | 11 | [font.bold_italic] 12 | family = "DejaVuSansM Nerd Font" 13 | style = "Bold Oblique" 14 | 15 | [font.italic] 16 | family = "DejaVuSansM Nerd Font" 17 | style = "Oblique" 18 | 19 | [font.normal] 20 | family = "DejaVuSansM Nerd Font" 21 | style = "Regular" 22 | 23 | [terminal] 24 | shell = "/opt/homebrew/bin/fish" 25 | 26 | [window] 27 | decorations = "none" 28 | opacity = 0.85 29 | startup_mode = "Maximized" 30 | option_as_alt = "Both" 31 | 32 | [cursor] 33 | style = { shape = "Block", blinking = "Always" } 34 | -------------------------------------------------------------------------------- /nvim/lua/plugins/formatter.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { 3 | "stevearc/conform.nvim", 4 | optional = true, 5 | ---@param opts ConformOpts 6 | opts = { 7 | formatters_by_ft = { 8 | javascript = { "prettier" }, 9 | typescript = { "prettier" }, 10 | javascriptreact = { "prettier" }, 11 | typescriptreact = { "prettier" }, 12 | css = { "prettier" }, 13 | html = { "prettier" }, 14 | json = { "prettier" }, 15 | yaml = { "prettier" }, 16 | markdown = { "prettier" }, 17 | graphql = { "prettier" }, 18 | lua = { "stylua" }, 19 | python = { "isort", "black" }, 20 | }, 21 | }, 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /fish/functions/kdp.fish: -------------------------------------------------------------------------------- 1 | function kdp -d "Describe a pod" 2 | set -l arg_count (count $argv) 3 | 4 | if test $arg_count -eq 0 5 | kubectl get pods --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' |\ 6 | fzf --height=15 --border --header="== Select pod:" --reverse | read pod; 7 | 8 | if test -z $pod 9 | echo \ufc38 Aborted or not found 10 | return 1 11 | end 12 | else 13 | kubectl get pods --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' |\ 14 | fzf --filter $argv[1] | read pod; 15 | end 16 | 17 | echo \uf046 Pod: $pod 18 | 19 | kubectl describe pods/$pod | less +G 20 | end 21 | -------------------------------------------------------------------------------- /fish/functions/grs.fish: -------------------------------------------------------------------------------- 1 | function grs -d "Reset --hard current local branch to the remote branch" 2 | git rev-parse --is-inside-work-tree 2>/dev/null 1>&2 3 | set -l git_error $status 4 | if test $git_error -ne 0 5 | echo 'Not in git repository' 6 | return 7 | end 8 | 9 | git branch --show-current | read current_branch 10 | echo "Your current branch is '$current_branch'" 11 | read -P "Are you sure to reset it to 'origin/$current_branch' (Y/n)? " confirm 12 | 13 | if test $status -ne 0 14 | echo Cancelled 15 | return 1 16 | end 17 | 18 | if test $confirm != y 19 | echo Aborted 20 | return 21 | end 22 | 23 | git reset --hard origin/$current_branch 24 | end 25 | -------------------------------------------------------------------------------- /fish/functions/kd.fish: -------------------------------------------------------------------------------- 1 | function kd -d "Describe k8s pod" 2 | argparse 'n/namespace=' -- $argv 3 | 4 | if test $status -ne 0 5 | return 255 6 | end 7 | 8 | if set -q _flag_namespace 9 | set -l namespace (get_k8s_namespace $_flag_namespace) 10 | set arg_namespace '-n' $namespace 11 | end 12 | 13 | if test $status -ne 0 14 | err "Namespace not found." 15 | return (k8s_errors NAMESPACE_NOT_FOUND) 16 | end 17 | 18 | set pod (get_k8s_pod $arg_namespace $argv[1]) 19 | set arg_pod '-p' $pod 20 | 21 | if test $status -ne 0 22 | err "Pod not found" 23 | return (k8s_errors POD_NOT_FOUND) 24 | end 25 | 26 | kubectl describe pods/$pod $arg_namespace | less +G 27 | end 28 | -------------------------------------------------------------------------------- /nvim/lua/plugins/others.lua: -------------------------------------------------------------------------------- 1 | return { 2 | { "mrjones2014/smart-splits.nvim" }, 3 | { 4 | "nvim-zh/colorful-winsep.nvim", 5 | config = true, 6 | event = { "WinLeave" }, 7 | }, 8 | { "rest-nvim/rest.nvim" }, 9 | { "zdcthomas/yop.nvim" }, 10 | { 11 | "haphamdev/copier.nvim", 12 | dependencies = { 13 | "zdcthomas/yop.nvim", 14 | }, 15 | config = function() 16 | require("copier").setup() 17 | end, 18 | }, 19 | { 20 | "linrongbin16/gitlinker.nvim", 21 | cmd = "GitLink", 22 | opts = {}, 23 | keys = { 24 | { "gy", "GitLink", mode = { "n", "v" }, desc = "Yank git link" }, 25 | { "gY", "GitLink!", mode = { "n", "v" }, desc = "Open git link" }, 26 | }, 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /fish/functions/grb.fish: -------------------------------------------------------------------------------- 1 | function grb -d "Rebase current git branch" 2 | git rev-parse --is-inside-work-tree 2>/dev/null 1>&2 3 | set -l git_error $status 4 | if test $git_error -ne 0 5 | echo 'Not in git repository' 6 | return 7 | end 8 | 9 | if test (count $argv) -gt 0 10 | git for-each-ref --format='%(refname:short)' | grep -v origin | fzf --filter $argv[1] | sed -E 's|origin/||' | read branch_name 11 | else 12 | git for-each-ref --format='%(refname:short)' | grep -v origin | fzf --height=40% --border | sed -E 's|origin/||' | read branch_name 13 | end 14 | 15 | if test $status -ne 0 16 | echo "Cancelled or no branch was selected." 17 | return 1 18 | end 19 | 20 | echo "Rebasing to branch '$branch_name'" 21 | git rebase -i $branch_name 22 | end 23 | -------------------------------------------------------------------------------- /fish/functions/hplib/get_k8s_pod.fish: -------------------------------------------------------------------------------- 1 | function get_k8s_pod -d "Pick a K8s pod using fuzzy search" 2 | # Args: n/namespace, p/pod 3 | argparse 'n/namespace=' -- $argv 4 | 5 | if set -q _flag_namespace 6 | set arg_namespace '--namespace' $_flag_namespace 7 | end 8 | 9 | if test $status -ne 0 10 | return (k8s_errors NAMESPACE_NOT_FOUND) 11 | end 12 | 13 | set pods (get_pod_list $arg_namespace) 14 | 15 | if test $status -ne 0 -o (count $pods) -eq 0 16 | return (k8s_errors POD_NOT_FOUND) 17 | end 18 | 19 | if test (count $argv) -gt 0 20 | set pod (fzf_search $argv[1] $pods) 21 | else 22 | set pod (ifzf_search 'Please select a pod:' $pods) 23 | end 24 | 25 | if test -z $pod 26 | return (k8s_errors POD_NOT_FOUND) 27 | else 28 | echo $pod 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /git/repeat/hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Get the current branch name 4 | branch_name=$(git symbolic-ref --short -q HEAD) 5 | 6 | # Check if we could retrieve the branch name 7 | if [ -z "$branch_name" ]; then 8 | echo "Error: Could not determine the current branch name." 9 | exit 1 10 | fi 11 | 12 | if ! [[ "$branch_name" =~ ^(feature|bugfix|hotfix)/RPT-[0-9]+- ]]; then 13 | echo "Error: Branch name '$branch_name' does not match the required format." 14 | echo "Branch name must use one of the following patterns:" 15 | echo "- feature/RPT-xxxx-more-description (example: feature/RPT-1234-find-user-by-name)" 16 | echo "- bugfix/RPT-xxxx-more-description (example: bugfix/RPT-56789-fix-user-loading-bug)" 17 | echo "- hotfix/RPT-xxxx-more-description (example: hotfix/RPT-2345-fix-login-page-crash" 18 | 19 | exit 1 20 | fi 21 | 22 | exit 0 23 | 24 | -------------------------------------------------------------------------------- /ghostty/config: -------------------------------------------------------------------------------- 1 | theme = FishTank 2 | command = /opt/homebrew/bin/fish --login --interactive 3 | background-opacity = 0.95 4 | unfocused-split-opacity = 0.5 5 | background-blur-radius = 20 6 | macos-titlebar-style = hidden 7 | 8 | # Keybindings 9 | keybind = clear 10 | keybind = ctrl+h=goto_split:left 11 | keybind = ctrl+j=goto_split:bottom 12 | keybind = ctrl+k=goto_split:top 13 | keybind = ctrl+l=goto_split:right 14 | keybind = ctrl+f>h=new_split:right 15 | keybind = ctrl+f>v=new_split:down 16 | keybind = opt+j=resize_split:down,20 17 | keybind = opt+k=resize_split:up,20 18 | keybind = opt+h=resize_split:left,20 19 | keybind = opt+l=resize_split:right,20 20 | keybind = ctrl+f>t=new_tab 21 | keybind = ctrl+f>r=reload_config 22 | keybind = ctrl+f>enter=toggle_split_zoom 23 | keybind = super+q=quit 24 | keybind = super+v=paste_from_clipboard 25 | keybind = super+c=copy_to_clipboard 26 | 27 | -------------------------------------------------------------------------------- /fish/functions/gdb.fish: -------------------------------------------------------------------------------- 1 | function gdb --description "Delete a git branch with fzf" 2 | git rev-parse --is-inside-work-tree 2>/dev/null 1>&2 3 | set -l git_error $status 4 | if test $git_error -ne 0 5 | echo 'Not in git repository' 6 | return 7 | end 8 | 9 | if test (count $argv) -gt 0 10 | git for-each-ref --format='%(refname:short)' | grep -v origin | fzf --filter $argv[1] | sed -E 's|origin/||' | read branch_name 11 | else 12 | git for-each-ref --format='%(refname:short)' | grep -v origin | fzf --height=40% --border --reverse --header="== Select branch to delete:" | sed -E 's|origin/||' | read branch_name 13 | end 14 | 15 | if test $status -ne 0 16 | echo "Cancelled or no branch was selected." 17 | return 1 18 | end 19 | 20 | echo "Deleting branch '$branch_name'" 21 | git branch -D $branch_name 22 | end 23 | -------------------------------------------------------------------------------- /wezterm/get-git-dir.lua: -------------------------------------------------------------------------------- 1 | local function exists(file) 2 | local ok, err, code = os.rename(file, file) 3 | if not ok then 4 | if code == 13 then 5 | -- Permission denied, but it exists 6 | return true 7 | end 8 | end 9 | return ok, err 10 | end 11 | 12 | local module = {} 13 | 14 | function module.getGitDir(path) 15 | if not path or #path < 1 then 16 | return path 17 | end 18 | 19 | local count = 0 20 | local error = false 21 | while path and path ~= "/" and not exists(path .. "/.git") do 22 | path = path:match("(.*)/") 23 | count = count + 1 24 | 25 | -- Maximum 30 attempt to avoid infinite loop 26 | -- a directory with more then 30 depth levels is not supported 27 | if count > 30 then 28 | error = true 29 | break 30 | end 31 | end 32 | 33 | if error or path == "/" then 34 | return nil 35 | end 36 | 37 | return path 38 | end 39 | 40 | return module 41 | -------------------------------------------------------------------------------- /fish/functions/hplib/get_k8s_container_logs.fish: -------------------------------------------------------------------------------- 1 | function get_k8s_container_logs -d "Get log of a container inside a K8s pod" 2 | # Args: n/namespace, p/pod, c/container 3 | # Read container log and redirect it to a temp file in the background job 4 | # Output: temp log file and the background job id 5 | 6 | argparse 'n/namespace=' 'p/pod=' 'c/container=' -- $argv 7 | 8 | if set -q _flag_namespace 9 | set arg_namespace '--namespace' $_flag_namespace 10 | end 11 | 12 | if not set -q _flag_pod 13 | return (k8s_errors POD_MISSING) 14 | end 15 | 16 | if set -q _flag_container 17 | set arg_container '--container' $_flag_container 18 | end 19 | 20 | set log_file_path ~/lnav-logs/$_flag_pod--$_flag_container.log 21 | kubectl logs -f pods/$_flag_pod $arg_container $arg_namespace > $log_file_path & 22 | set -l job_id (jobs -lp) 23 | echo $log_file_path $job_id 24 | end 25 | -------------------------------------------------------------------------------- /fish/functions/dbss.fish: -------------------------------------------------------------------------------- 1 | function dbss 2 | if test (count $argv) -gt 0 3 | set COMPANY_ID $argv[1] 4 | echo "🔑 Company: $COMPANY_ID" 5 | else 6 | read -P "🔑 Company: " COMPANY_ID 7 | if test -z "$COMPANY_ID" 8 | echo "Skipped" 9 | return 10 | end 11 | end 12 | 13 | print_header "Subscriptions" 14 | data-access sql execute-read-query "set personio.company_id to -1; select subscriptions.*, plans.type plan_type from subscriptions inner join plans on subscriptions.plan_id = plans.id where company_id = $COMPANY_ID" --db-identifier=subscription-service --jira-ticket=SM-981 15 | 16 | print_header "Addons" 17 | data-access sql execute-read-query "set personio.company_id to -1; select * from subscription_addons inner join addons on subscription_addons.addon_id = addons.id where company_id = $COMPANY_ID" --db-identifier=subscription-service --jira-ticket=SM-981 18 | end 19 | -------------------------------------------------------------------------------- /git/repeat/hooks/prepare-commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # git prepare-commit-msg hook for automatically prepending an issue key 4 | # from the start of the current branch name to commit messages. 5 | 6 | # check if commit is merge commit or a commit ammend 7 | if [ $2 = "merge" ] || [ $2 = "commit" ]; then 8 | exit 9 | fi 10 | 11 | ISSUE_NUMBER=$(git symbolic-ref --short -q HEAD | grep -Eo 'RPT-[0-9]+') 12 | if [ $? -ne 0 ]; then 13 | echo "No issue key found" 14 | # no issue key in branch, use the default message 15 | exit 16 | fi 17 | 18 | # check if the commit message already starts with the issue number 19 | FIRST_LINE=$(head -n1 "$1") 20 | echo "$FIRST_LINE" | grep -q "^$ISSUE_NUMBER[: ]" 21 | if [ $? -eq 0 ]; then 22 | # already prefixed 23 | exit 24 | fi 25 | 26 | # issue key matched from branch prefix, prepend to commit message 27 | TEMP=$(mktemp /tmp/commitmsg-XXXXX) 28 | (echo "$ISSUE_NUMBER: $(cat $1)") >$TEMP 29 | cat $TEMP >$1 30 | -------------------------------------------------------------------------------- /fish/functions/hplib/get_short_name.fish: -------------------------------------------------------------------------------- 1 | function get_short_name 2 | set -l long_name $argv[1] 3 | 4 | # Map of repo-name:short-name 5 | set -l mappings \ 6 | 'repeat-shopping-cart:shopping-cart' \ 7 | 'repeat-payment:payment' \ 8 | 'repeat-tournament-entry-scores:tes-scores' \ 9 | 'repeat-rewards:rewards' \ 10 | 'xygaming_symfony:symfony' \ 11 | 'repeat-mobile-app:mobile-app' \ 12 | 'repeat-twitch-api:twitch-api' \ 13 | 'repeat-orders:orders' \ 14 | 'repeat-game-statistics-api:stats-api' \ 15 | 'repeat-system-tests:system-tests' 16 | 17 | for pair in $mappings 18 | set -l key (string split ':' $pair)[1] 19 | set -l val (string split ':' $pair)[2] 20 | 21 | if test "$long_name" = "$key" 22 | echo $val 23 | return 24 | end 25 | end 26 | 27 | # No match: return original 28 | echo $long_name 29 | end 30 | -------------------------------------------------------------------------------- /fish/functions/vim_rg.fish: -------------------------------------------------------------------------------- 1 | function vim_rg -d 'A helper function to use RipGrep in vim with glob supported' 2 | set -l queries (string split -m 1 '>' "$argv") # split the glob and keyword, separator is > 3 | 4 | if test (count $queries) -eq 1 # no glob 5 | rg --column --line-number --no-heading --color=always --smart-case -- $queries[1] || true 6 | else if test -z "$queries[1]" # glob is empty 7 | rg --column --line-number --no-heading --color=always --smart-case -- $queries[2] || true 8 | else 9 | set globs (string replace -a -r '\s+' ' ' $queries[1]\ 10 | | string trim \ 11 | | string split ' ') 12 | 13 | for g in $globs 14 | set -a glob_arguments "--iglob '$g'" 15 | end 16 | 17 | set command (printf 'rg --column --line-number --no-heading --color=always --smart-case %s -- %s || true' "$glob_arguments" $queries[2]) 18 | eval $command 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if command -v brew >/dev/null 2>&1; then 3 | echo "Homebrew is installed" 4 | else 5 | echo "Homebrew is not installed. Installing..." 6 | fi 7 | 8 | if [ -d $HOME/projects/personal/dot-files ]; then 9 | echo "A dot file directory alreay exists at $HOME/projects/dot-files. Skipped cloning." 10 | else 11 | mkdir -p $HOME/projects/personal 12 | echo "Installing git" 13 | brew install git 14 | 15 | echo "Generating SSH key" 16 | if [ ! -a $HOME/.ssh/id_ed25519.pub ]; then 17 | ssh-keygen -t rsa 18 | ssh-keygen -t ed25519 -C 'hapham.dev@gmail.com' 19 | fi 20 | 21 | pbcopy <$HOME/.ssh/id_ed25519.pub 22 | echo "SSH public key has been copied. Please add it to GitHub, then press ENTER to continue." 23 | read 24 | 25 | # clone the dot-files project 26 | echo "Cloning hapham's dot-file project" 27 | mkdir $HOME/projects 28 | cd $HOME/projects 29 | git clone git@github.com:fanliver/dot-files.git 30 | fi 31 | 32 | cd $HOME/projects/dot-files 33 | ./install/setup_configs.fish 34 | -------------------------------------------------------------------------------- /nvim/lua/plugins/obsidian-nvim.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "epwalsh/obsidian.nvim", 3 | version = "*", -- recommended, use latest release instead of latest commit 4 | lazy = true, 5 | ft = "markdown", 6 | -- Replace the above line with this if you only want to load obsidian.nvim for markdown files in your vault: 7 | -- event = { 8 | -- -- If you want to use the home shortcut '~' here you need to call 'vim.fn.expand'. 9 | -- -- E.g. "BufReadPre " .. vim.fn.expand "~" .. "/my-vault/*.md" 10 | -- -- refer to `:h file-pattern` for more examples 11 | -- "BufReadPre path/to/my-vault/*.md", 12 | -- "BufNewFile path/to/my-vault/*.md", 13 | -- }, 14 | dependencies = { 15 | -- Required. 16 | "nvim-lua/plenary.nvim", 17 | }, 18 | opts = { 19 | workspaces = { 20 | { 21 | name = "personal", 22 | path = "~/notes/haphamdev", 23 | }, 24 | { 25 | name = "work", 26 | path = "~/notes/fram", 27 | }, 28 | }, 29 | 30 | -- see below for full list of options 👇 31 | }, 32 | } 33 | -------------------------------------------------------------------------------- /nvim/lua/plugins/colorscheme.lua: -------------------------------------------------------------------------------- 1 | return { 2 | -- add gruvbox 3 | { "ellisonleao/gruvbox.nvim" }, 4 | { "bluz71/vim-nightfly-colors" }, 5 | 6 | { 7 | "folke/tokyonight.nvim", 8 | disabled = true, 9 | opts = { 10 | transparent = true, 11 | styles = { 12 | sidebars = "transparent", 13 | floats = "transparent", 14 | }, 15 | on_highlights = function(hl, _) 16 | hl.LineNr = { fg = "#3b4261" } 17 | hl.LineNrAbove = { fg = "#5D6899" } 18 | hl.LineNrBelow = { fg = "#5D6899" } 19 | hl.WinSeparator = { fg = "#5D6899" } 20 | hl.LspInlayHint = { 21 | -- bg = "#24283c", 22 | fg = "#7882B3", 23 | italic = true, 24 | } 25 | hl.DiagnosticUnnecessary = { 26 | -- fg = "#626BA6", 27 | undercurl = true, 28 | } 29 | end, 30 | }, 31 | }, 32 | 33 | -- Configure LazyVim to load gruvbox 34 | { 35 | "LazyVim/LazyVim", 36 | opts = { 37 | colorscheme = "tokyonight", 38 | }, 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /fish/functions/kpf.fish: -------------------------------------------------------------------------------- 1 | function kpf -d "Port-forward for a k8s pod with fzf search" 2 | argparse 'n/namespace=' -- $argv 3 | 4 | if test $status -ne 0 5 | return 255 6 | end 7 | 8 | if set -q _flag_namespace 9 | set -l namespace (get_k8s_namespace $_flag_namespace) 10 | set arg_namespace '-n' $namespace 11 | end 12 | 13 | if test $status -ne 0 14 | err "Namespace not found." 15 | return (k8s_errors NAMESPACE_NOT_FOUND) 16 | end 17 | 18 | if test (count $argv) -eq 0 19 | err "Port is missing" 20 | return (k8s_errors PORT_MISSING) 21 | else if test (count $argv) -eq 1 22 | set pod (get_k8s_pod $arg_namespace) 23 | set arg_pod '-p' $pod 24 | set arg_port '-P' $argv[1] 25 | else 26 | set pod (get_k8s_pod $arg_namespace $argv[1]) 27 | set arg_pod '-p' $pod 28 | set arg_port '-P' $argv[2] 29 | end 30 | 31 | if test $status -ne 0 32 | err "Pod not found" 33 | return (k8s_errors POD_NOT_FOUND) 34 | end 35 | 36 | port_forward_k8s_pod $arg_namespace $arg_pod $arg_port 37 | 38 | end 39 | -------------------------------------------------------------------------------- /fish/functions/gco.fish: -------------------------------------------------------------------------------- 1 | function gco 2 | git rev-parse --is-inside-work-tree 2>/dev/null 1>&2 3 | set -l git_error $status 4 | if test $git_error -ne 0 5 | echo 'Not in git repository' 6 | return 7 | end 8 | 9 | set -l has_change (git status --porcelain) 10 | if test -n "$has_change" 11 | read -P "Stash current change ('y' for Yes, otherwise, No)? " stash_change 12 | 13 | if test $status -ne 0 14 | echo Cancelled 15 | return 1 16 | end 17 | 18 | if test $stash_change = y 19 | git stash 20 | end 21 | end 22 | 23 | if test (count $argv) -gt 0 24 | git for-each-ref --format='%(refname:short)' | fzf --filter $argv[1] | sed -E 's|origin/||' | read branch_name 25 | else 26 | git for-each-ref --format='%(refname:short)' | fzf --height=40% --border | sed -E 's|origin/||' | read branch_name 27 | end 28 | 29 | if test $status -ne 0 30 | echo "Cancelled or no branch was selected" 31 | return 1 32 | end 33 | 34 | echo "Checking out branch '$branch_name'" 35 | git checkout $branch_name 36 | end 37 | -------------------------------------------------------------------------------- /nvim/lazyvim.json: -------------------------------------------------------------------------------- 1 | { 2 | "extras": [ 3 | "lazyvim.plugins.extras.coding.luasnip", 4 | "lazyvim.plugins.extras.coding.mini-comment", 5 | "lazyvim.plugins.extras.coding.mini-surround", 6 | "lazyvim.plugins.extras.editor.mini-files", 7 | "lazyvim.plugins.extras.formatting.prettier", 8 | "lazyvim.plugins.extras.lang.docker", 9 | "lazyvim.plugins.extras.lang.go", 10 | "lazyvim.plugins.extras.lang.json", 11 | "lazyvim.plugins.extras.lang.markdown", 12 | "lazyvim.plugins.extras.lang.php", 13 | "lazyvim.plugins.extras.lang.python", 14 | "lazyvim.plugins.extras.lang.rust", 15 | "lazyvim.plugins.extras.lang.sql", 16 | "lazyvim.plugins.extras.lang.tailwind", 17 | "lazyvim.plugins.extras.lang.typescript", 18 | "lazyvim.plugins.extras.lang.yaml", 19 | "lazyvim.plugins.extras.linting.eslint", 20 | "lazyvim.plugins.extras.test.core", 21 | "lazyvim.plugins.extras.ui.mini-indentscope", 22 | "lazyvim.plugins.extras.ui.treesitter-context", 23 | "lazyvim.plugins.extras.util.mini-hipatterns" 24 | ], 25 | "install_version": 7, 26 | "news": { 27 | "NEWS.md": "11866" 28 | }, 29 | "version": 8 30 | } -------------------------------------------------------------------------------- /fish/functions/hplib/get_k8s_container.fish: -------------------------------------------------------------------------------- 1 | function get_k8s_container -d "Get container of a K8s pod using fuzzy search" 2 | # Args: n/namespace, p/pod, container 3 | argparse 'n/namespace=' 'p/pod=' -- $argv 4 | 5 | if not set -q _flag_pod 6 | return (k8s_errors POD_MISSING) 7 | end 8 | 9 | if set -q _flag_namespace 10 | set arg_namespace '--namespace' $_flag_namespace 11 | end 12 | 13 | set containers (kubectl get pods $_flag_pod $arg_namespace -o jsonpath='{range .spec.containers[*]}{.name}{"\n"}') 14 | 15 | if test $status -ne 0 16 | return (k8s_errors CONTAINER_NOT_FOUND) 17 | end 18 | 19 | if test (count $containers) -eq 1 20 | echo $containers 21 | return 22 | elif 23 | return (k8s_errors CONTAINER_NOT_FOUND) 24 | end 25 | 26 | if test (count $argv) -gt 0 27 | set container (fzf_search $argv[1] $containers) 28 | else 29 | set container (ifzf_search 'Please select a container:' $containers) 30 | end 31 | 32 | if test -z $container 33 | return (k8s_errors CONTAINER_NOT_FOUND) 34 | else 35 | echo $container 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /fish/functions/sdk.fish: -------------------------------------------------------------------------------- 1 | function sdk -d "Manage SDKs" 2 | # Guard: SDKMAN! needs to be installed 3 | if not test -f "$__fish_sdkman_init" 4 | # Propose to install SDKMAN! 5 | 6 | function read_confirm 7 | while true 8 | read -l -P "$argv[1] [y/N] " confirm 9 | 10 | switch $confirm 11 | case Y y 12 | return 0 13 | case '' N n 14 | return 1 15 | end 16 | end 17 | end 18 | 19 | if read_confirm "You don't seem to have SDKMAN! installed. Install now?" 20 | if not which curl > /dev/null 21 | echo "curl required" 22 | return 1 23 | end 24 | if not which bash > /dev/null 25 | echo "bash required" 26 | return 1 27 | end 28 | 29 | curl -s "https://get.sdkman.io" | bash | sed '/All done!/q' 30 | echo "Please open a new terminal/shell to load SDKMAN!" 31 | end 32 | else 33 | # Declare the _actual_ sdk command for fish 34 | __fish_sdkman_run_in_bash "source \"$__fish_sdkman_noexport_init\" && sdk $argv" 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /wezterm/utils.lua: -------------------------------------------------------------------------------- 1 | local wezterm = require("wezterm") 2 | local colors = require("colors") 3 | local module = {} 4 | 5 | function module.map(t, func) 6 | local result = {} 7 | for key, value in pairs(t) do 8 | local v = func(key, value) 9 | table.insert(result, v) 10 | end 11 | return result 12 | end 13 | 14 | function module.inspect(value) 15 | wezterm.log_info("Inspect: " .. wezterm.to_string(value)) 16 | end 17 | 18 | function module.mergeTable(result, toBeMerged) 19 | for _, v in pairs(toBeMerged) do 20 | table.insert(result, v) 21 | end 22 | end 23 | 24 | function module.formatSegment(input) 25 | return { 26 | "ResetAttributes", 27 | { Background = { Color = input.left or colors.statusBarBackground } }, 28 | { Foreground = { Color = input.bg or colors.secondaryBackground } }, 29 | { Text = wezterm.nerdfonts.ple_lower_right_triangle }, 30 | { Foreground = { Color = input.fg or colors.secondary } }, 31 | { Background = { Color = input.bg or colors.secondaryBackground } }, 32 | { Text = input.text }, 33 | { Background = { Color = input.right or colors.statusBarBackground } }, 34 | { Foreground = { Color = input.bg or colors.secondaryBackground } }, 35 | { Text = wezterm.nerdfonts.ple_upper_left_triangle }, 36 | } 37 | end 38 | return module 39 | -------------------------------------------------------------------------------- /fish/functions/dbcbs.fish: -------------------------------------------------------------------------------- 1 | function dbcbs 2 | if test (count $argv) -gt 0 3 | set COMPANY_ID $argv[1] 4 | echo "🔑 Company: $COMPANY_ID" 5 | else 6 | read -P "🔑 Company: " COMPANY_ID 7 | if test -z "$COMPANY_ID" 8 | echo "Skipped" 9 | return 10 | end 11 | end 12 | 13 | print_header "Customer" 14 | data-access sql execute-read-query "set personio.company_id to -1; select * from cb_customers where company_id=$COMPANY_ID" --db-identifier=chargebee-service --db-name=chargebee-service --jira-ticket=SM-981 15 | 16 | print_header "Subscription" 17 | data-access sql execute-read-query "set personio.company_id to -1; select cb_subscriptions.*, cb_plans.chargebee_plan_id from cb_subscriptions inner join cb_plans on cb_subscriptions.plan_id = cb_plans.id where company_id=$COMPANY_ID" --db-identifier=chargebee-service --db-name=chargebee-service --jira-ticket=SM-981 18 | 19 | print_header "Addons" 20 | data-access sql execute-read-query "set personio.company_id to -1; select * from cb_subscription_addons inner join cb_addons on cb_subscription_addons.addon_id = cb_addons.id where company_id=$COMPANY_ID" --db-identifier=chargebee-service --db-name=chargebee-service --jira-ticket=SM-981 21 | end 22 | 23 | 24 | -------------------------------------------------------------------------------- /fish/functions/fp.fish: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env fish 2 | 3 | function fp 4 | # Use fd to list all dirs one level under each group 5 | set -l candidates (fd -td -d1 . ~/projects/*) 6 | 7 | # Filter only those that are Git repos (contain a .git dir) 8 | set -l repos 9 | for dir in $candidates 10 | if test -d "$dir/.git" 11 | set repos $repos $dir 12 | end 13 | end 14 | 15 | # Build menu: show group/repo relative to ~/projects 16 | set -l menu 17 | set -l paths 18 | 19 | for repo in $repos 20 | set relative_path (string replace --regex '^.*/projects/' '' $repo) 21 | set menu $menu $relative_path 22 | set paths $paths $repo 23 | end 24 | 25 | if test (count $argv) -gt 0 26 | printf "%s\n" $menu | fzf --filter="$argv[1]" | read selected 27 | else 28 | printf "%s\n" $menu | fzf --prompt="Select a repository: " --height=10 --layout=reverse | read selected 29 | end 30 | 31 | if test -n "$selected" 32 | for i in (seq (count $menu)) 33 | if test "$menu[$i]" = "$selected" 34 | cd "$paths[$i]" 35 | wezterm cli set-tab-title (get_short_name (basename $selected)) 36 | return 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /fish/functions/pcl.fish: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env fish 2 | 3 | function pcl 4 | function choose_target_directory 5 | set base_dir ~/projects 6 | 7 | # Get subdirectory names only 8 | set -l options (ls -d $base_dir/*/ 2>/dev/null | xargs -n 1 basename) 9 | 10 | if test (count $options) -eq 0 11 | echo "No subdirectories found in $base_dir. Please create one first." 12 | return 1 13 | end 14 | 15 | # Use fzf to pick a directory name 16 | set -l selected (printf "%s\n" $options | fzf --height=10 --layout=reverse --prompt="Select target directory: ") 17 | 18 | if test -z "$selected" 19 | echo "No selection made. Aborting." 20 | return 1 21 | end 22 | 23 | echo "$base_dir/$selected" 24 | end 25 | 26 | if test (count $argv) -ne 1 27 | echo "Usage: pcl " 28 | return 1 29 | end 30 | 31 | set repo_url $argv[1] 32 | set repo_name (basename -s .git $repo_url) 33 | set target_parent_dir (choose_target_directory) 34 | 35 | if test $status -ne 0 36 | return 1 37 | end 38 | 39 | set target_dir "$target_parent_dir/$repo_name" 40 | 41 | if test -d "$target_dir" 42 | echo "Directory '$target_dir' already exists. Aborting." 43 | return 1 44 | end 45 | 46 | echo "Cloning $repo_url to $target_dir" 47 | 48 | git clone "$repo_url" "$target_dir" 49 | if test $status -ne 0 50 | echo "Git clone failed." 51 | return 1 52 | end 53 | 54 | cd "$target_dir" 55 | echo "Changed directory to $target_dir" 56 | end 57 | -------------------------------------------------------------------------------- /fish/functions/dbsms.fish: -------------------------------------------------------------------------------- 1 | function dbsms 2 | if test (count $argv) -gt 0 3 | set COMPANY_ID $argv[1] 4 | echo "🔑 Company: $COMPANY_ID" 5 | else 6 | read -P "🔑 Company: " COMPANY_ID 7 | if test -z "$COMPANY_ID" 8 | echo "Skipped" 9 | return 10 | end 11 | end 12 | 13 | print_header "Customer" 14 | data-access sql execute-read-query "set personio.company_id to -1; select * from customers where company_id=$COMPANY_ID" --db-identifier=subscription-management-service --db-name=subscription-management-service --jira-ticket=SM-981 15 | 16 | print_header "Subscription and plan" 17 | data-access sql execute-read-query "set personio.company_id to -1; select * from subscriptions inner join plans on plans.id = subscriptions.plan_id where company_id=$COMPANY_ID" --db-identifier=subscription-management-service --db-name=subscription-management-service --jira-ticket=SM-981 18 | 19 | print_header "Addons" 20 | data-access sql execute-read-query "set personio.company_id to -1; select * from subscription_addons inner join addons on subscription_addons.addon_id = addons.id where company_id=$COMPANY_ID" --db-identifier=subscription-management-service --db-name=subscription-management-service --jira-ticket=SM-981 21 | 22 | print_header "Recruiting option" 23 | data-access sql execute-read-query "set personio.company_id to -1; select recruiting_options.* from recruiting_options inner join subscriptions on subscriptions.recruiting_option_id = recruiting_options.id where company_id=$COMPANY_ID" --db-identifier=subscription-management-service --db-name=subscription-management-service --jira-ticket=SM-981 24 | end 25 | -------------------------------------------------------------------------------- /fish/functions/dbaq.fish: -------------------------------------------------------------------------------- 1 | function dbaq -d "Query database from stage or prod environment" 2 | argparse 'h/help' 'c/company=' 'm/message=' 'a/approver=' 'r/reviewer=' 't/ticket=' 's/stage' -- $argv 3 | 4 | if set -q _flag_help 5 | echo " 6 | Run database query to fetch data from Stage or Production environment 7 | Please provide the input param as below. Missing params will need to be entered later. 8 | 9 | -h/--help: Display help 10 | -c/--company: Company ID which you need to query data. 11 | -i/--instance: Message or reason for the request. 12 | -d/--database: Email of the approver. Approver must be in Personio EM list. 13 | -s/--stage: Query data from STAGE. Otherwise, query data from PRODUCTION 14 | " 15 | return 16 | end 17 | 18 | if set -q _flag_company 19 | echo "🔑 Company: " $_flag_company 20 | else 21 | read -P "🔑 Company: " _flag_company 22 | end 23 | 24 | if set -q _flag_instance 25 | echo "❓ Instance: " $_flag_instance 26 | else 27 | read -P "❓ Instance: " _flag_instance 28 | end 29 | 30 | if set -q _flag_database 31 | echo "💬 Database: $_flag_database" 32 | else 33 | read -P "💬 Database: " _flag_database 34 | end 35 | 36 | if set -q _flag_stage 37 | set env stage 38 | else 39 | set env prod 40 | end 41 | echo "🖥 Environment: $env" 42 | 43 | 44 | dbaccess execute-query "select * from scheduled_deletions where company_id=1935" --company-id=1935 --instance=microservices-prod --db=company-data-operations-service --env=prod 45 | 46 | end 47 | 48 | -------------------------------------------------------------------------------- /fish/tmux_wind_project.fish: -------------------------------------------------------------------------------- 1 | # Select a project in $HOME/projects using fuzzy search and open a new Tmux window 2 | 3 | set target_dirs $HOME/projects $HOME/projects/practice 4 | 5 | # The list of project names and their short-form aliases 6 | set projects \ 7 | 'admin-panel-service' \ 8 | 'chargebee-cli' \ 9 | 'chargebee-service' \ 10 | 'dot-files' \ 11 | 'company-data-operations-service' \ 12 | 'invoice-service' \ 13 | 'personio' \ 14 | 'subscription-data-monitoring-service' \ 15 | 'subscription-management-service' \ 16 | 'subscription-service' \ 17 | 'subscription-service-client-library' \ 18 | 'subscription-service-webhook' 19 | 20 | set project_aliases \ 21 | 'APS' \ 22 | 'CB-CLI' \ 23 | 'CBS' \ 24 | 'dot' \ 25 | 'CDOS' \ 26 | 'INV' \ 27 | 'Monolith' \ 28 | 'Subs Monitor' \ 29 | 'SMS' \ 30 | 'FAS' \ 31 | 'FAS client lib' \ 32 | 'SS webhook' 33 | 34 | set proj (ls $HOME/projects) 35 | set practice_proj (ls $HOME/projects/practice) 36 | 37 | # appending "practice/" to the names of projects in 'practice' directory 38 | for p in $practice_proj; 39 | set -a proj "practice/$p" 40 | end 41 | 42 | echo $proj | tr " " "\n" | grep -v ":" | fzf --border --height=95% --reverse --header='Please choose a project:' | read result 43 | 44 | if test -z $result 45 | tmux display-message "Aborted or project not found!" 46 | return 1 47 | end 48 | 49 | tmux neww -c "$HOME/projects/$result" 50 | 51 | # rename the new tmux window 52 | if set -l index (contains -i -- $result $projects) 53 | tmux rename-window $project_aliases[$index] 54 | else 55 | # using 'path basename' to get the last dir name 56 | tmux rename-window (path basename $result) 57 | end 58 | -------------------------------------------------------------------------------- /fish/functions/prfzf.fish: -------------------------------------------------------------------------------- 1 | # A function to jump to or open directory in $HOME/projects with vs code or nvim with fuzzy search 2 | function prfzf -d "Go to project in $HOME/projects using fzf search" 3 | 4 | # The list of project names and their short-form aliases 5 | set projects \ 6 | admin-panel-service \ 7 | chargebee-cli \ 8 | chargebee-service \ 9 | dot-files \ 10 | company-data-operations-service \ 11 | invoice-service \ 12 | personio \ 13 | subscription-data-monitoring-service \ 14 | subscription-management-service \ 15 | subscription-service \ 16 | subscription-service-client-library 17 | 18 | set project_aliases \ 19 | APS \ 20 | CB-CLI \ 21 | CBS \ 22 | dot \ 23 | CDOS \ 24 | INV \ 25 | Monolith \ 26 | 'Subs Monitor' \ 27 | SMS \ 28 | FAS \ 29 | 'FAS client lib' 30 | 31 | if test (count $argv) -gt 1 32 | ls $HOME/projects $HOME/projects/practice | tr " " "\n" | fzf --filter $argv[2] | read result 33 | else 34 | ls $HOME/projects $HOME/projects/practice | tr " " "\n" | fzf --border --height=50% | read result 35 | end 36 | 37 | if test -z $result 38 | echo "Aborted or project not found!" 39 | return 1 40 | end 41 | 42 | set path "$HOME/projects/$result" 43 | 44 | switch "$argv[1]" 45 | case code c 46 | code $path 47 | case e o v vim nvim 48 | nvim $path 49 | case '*' 50 | cd $path 51 | 52 | # rename the current tmux window 53 | if set -l index (contains -i -- $result $projects) 54 | wezterm cli set-tab-title $project_aliases[$index] 55 | else 56 | wezterm cli set-tab-title $result 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /learn-english.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import random 4 | 5 | dict = {} 6 | dict["Moving the needle"] = [100, "Make change in something so that the effect is measurable"] 7 | dict["Terminal velocity"] = [30, "Max velocity when you drop something from the air"] 8 | dict["With a bullet to the temple"] = [100, "Shot someone dead on the side of their head"] 9 | dict["Beneficial"] = [70, "Improving a situation; having a helpful or useful effect"] 10 | dict["Backstory"] = [40, "The story about how something was created or happened"] 11 | dict["Go down the rabbit hole"] = [70, "Jump into a difficult situation"] 12 | dict["Drop off"] = [20, "Leave something in the middle"] 13 | dict["It does exactly what it says on the tin"] = [100, "Something does exactly what it is supposed to do"] 14 | dict["From my gut feeling"] = [100, "Not based on fact, but from the feeling"] 15 | dict["Invaluable"] = [70, "Means a lot, very valuable"] 16 | dict["For the time being"] = [100, "For the present, until some other arrangement is made"] 17 | dict["Bump into someone"] = [60, "Meeting someone unexpectedly and surprisingly"] 18 | dict["Keep the ball rolling"] = [100, "Make something continue to work as expected"] 19 | dict["In the first place"] = [20, "As the first consideration or point"] 20 | dict["Culprit"] = [50, "The person who is responsible for a crime or misdeed"] 21 | dict["At some point"] = [70, "Sometime; at an indefinite time"] 22 | dict["Post-it note"] = [30, "A small paper used for writing note"] 23 | dict["Shooting in the dark"] = [60, "Attempt to guess something with a little chance of success"] 24 | dict["Low-hanging fruit"] = [100, "Something that can be easily done, achieve or taken advantage of"] 25 | 26 | probs = list(map(lambda item: item[0], list(dict.values()))) 27 | phrase = random.choices(list(dict.keys()), weights = probs)[0] 28 | meaning = dict[phrase][1] 29 | print(f"#[fg=colour16,bold]{phrase}: #[nobold]{meaning}") 30 | -------------------------------------------------------------------------------- /fish/functions/dbar.fish: -------------------------------------------------------------------------------- 1 | function dbar -d "Send dbaccess request to EM" 2 | argparse 'h/help' 'c/company=' 'm/message=' 'a/approver=' 't/ticket=' -- $argv 3 | 4 | if set -q _flag_help 5 | echo " 6 | Send request to your EM to access database in prod environment. 7 | Please provide the input param as below. Missing params will need to be entered later. 8 | 9 | -h/--help: Display help 10 | -c/--company: Company ID which you need to query data. 11 | -m/--message: Message or reason for the request. 12 | -a/--approver: Email of the approver. Approver must be in Personio EM list. 13 | -t/--ticket: The ticket that you are working go for auditing purpose 14 | " 15 | return 16 | end 17 | 18 | if set -q _flag_company 19 | echo "🔑 Company: " $_flag_company 20 | else 21 | read -P "🔑 Company: " _flag_company 22 | end 23 | 24 | if set -q _flag_ticket 25 | echo "❓ Ticket: " $_flag_ticket 26 | else 27 | read -P "❓ Ticket: " _flag_ticket 28 | end 29 | 30 | if test -z "$_flag_message" 31 | set _flag_message "I need to check the amount of document for company $_flag_company" 32 | end 33 | echo "💬 Message: $_flag_message" 34 | 35 | if test -z "$_flag_approver" 36 | set _flag_approver 'trung.truong.ext@personio.de' 37 | end 38 | echo "✅ Approver: $_flag_approver" 39 | 40 | set cmd "data-access auth request-company-access --company-id=\"$_flag_company\" --reason=\"$_flag_message\" --jira-ticket=\"$_flag_ticket\" --manager \"$_flag_approver\"" 41 | echo "Command: $cmd" 42 | read -P "Send request? (y/n/cp): " confirm 43 | 44 | if test $confirm = "y" 45 | echo $cmd | pbcopy 46 | eval $cmd 47 | echo "The command was also copied to the clipboard" 48 | else if test $confirm = "cp" 49 | echo $cmd | pbcopy 50 | echo "The command was also copied to the clipboard" 51 | else 52 | echo "Aborted!" 53 | end 54 | 55 | end 56 | -------------------------------------------------------------------------------- /nvim/lua/config/lazy.lua: -------------------------------------------------------------------------------- 1 | local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" 2 | if not (vim.uv or vim.loop).fs_stat(lazypath) then 3 | local lazyrepo = "https://github.com/folke/lazy.nvim.git" 4 | local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }) 5 | if vim.v.shell_error ~= 0 then 6 | vim.api.nvim_echo({ 7 | { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, 8 | { out, "WarningMsg" }, 9 | { "\nPress any key to exit..." }, 10 | }, true, {}) 11 | vim.fn.getchar() 12 | os.exit(1) 13 | end 14 | end 15 | vim.opt.rtp:prepend(lazypath) 16 | 17 | require("lazy").setup({ 18 | spec = { 19 | -- add LazyVim and import its plugins 20 | { "LazyVim/LazyVim", import = "lazyvim.plugins" }, 21 | -- import/override with your plugins 22 | { import = "plugins" }, 23 | }, 24 | defaults = { 25 | -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup. 26 | -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default. 27 | lazy = false, 28 | -- It's recommended to leave version=false for now, since a lot the plugin that support versioning, 29 | -- have outdated releases, which may break your Neovim install. 30 | version = false, -- always use the latest git commit 31 | -- version = "*", -- try installing the latest stable version for plugins that support semver 32 | }, 33 | install = { colorscheme = { "tokyonight", "habamax" } }, 34 | checker = { 35 | enabled = true, -- check for plugin updates periodically 36 | notify = false, -- notify on update 37 | }, -- automatically check for plugin updates 38 | performance = { 39 | rtp = { 40 | -- disable some rtp plugins 41 | disabled_plugins = { 42 | "gzip", 43 | -- "matchit", 44 | -- "matchparen", 45 | -- "netrwPlugin", 46 | "tarPlugin", 47 | "tohtml", 48 | "tutor", 49 | "zipPlugin", 50 | }, 51 | }, 52 | }, 53 | }) 54 | -------------------------------------------------------------------------------- /wezterm/tab-format.lua: -------------------------------------------------------------------------------- 1 | local wezterm = require("wezterm") 2 | local utils = require("utils") 3 | local colors = require("colors") 4 | local module = {} 5 | 6 | local function getTabTitle(tab_info) 7 | local title = tab_info.tab_title 8 | -- if the tab title is explicitly set, take that 9 | if title and #title > 0 then 10 | return title 11 | end 12 | -- Otherwise, use the title from the active pane 13 | -- in that tab 14 | return tab_info.active_pane.title 15 | end 16 | 17 | function module.apply_to_config(config) 18 | wezterm.on("format-tab-title", function(tab, tabs, panes, config, hover, max_width) 19 | local activeTabBackground = colors.primaryBackground 20 | local inactiveTabBackground = colors.secondaryBackground 21 | 22 | local edgeForeground = "#CCCCCC" 23 | local activeTabForeground = colors.primary 24 | local inactiveTabForeground = colors.disabled 25 | 26 | local tabBackground = inactiveTabBackground 27 | local tabForeground = inactiveTabForeground 28 | local intensity = "Normal" 29 | local italic = true 30 | 31 | if tab.is_active then 32 | tabBackground = activeTabBackground 33 | tabForeground = activeTabForeground 34 | intensity = "Bold" 35 | italic = true 36 | end 37 | 38 | local title = getTabTitle(tab) 39 | 40 | local edgeLeft = wezterm.nerdfonts.ple_lower_right_triangle 41 | local edgeRight = wezterm.nerdfonts.ple_upper_left_triangle 42 | 43 | return { 44 | { Background = { Color = colors.statusBarBackground } }, 45 | { Foreground = { Color = edgeForeground } }, 46 | { Text = edgeLeft }, 47 | { Background = { Color = tabBackground } }, 48 | { Foreground = { Color = edgeForeground } }, 49 | { Text = edgeRight }, 50 | { Background = { Color = tabBackground } }, 51 | { Foreground = { Color = tabForeground } }, 52 | { Attribute = { Intensity = intensity } }, 53 | { Attribute = { Italic = italic } }, 54 | { Text = title }, 55 | { Background = { Color = colors.statusBarBackground } }, 56 | { Foreground = { Color = tabBackground } }, 57 | { Text = edgeRight }, 58 | } 59 | end) 60 | end 61 | 62 | return module 63 | -------------------------------------------------------------------------------- /run.lua: -------------------------------------------------------------------------------- 1 | local q = require('vim.treesitter.query') 2 | local function i(value) 3 | print(vim.inspect(value)) 4 | end 5 | 6 | local query_string = [[ 7 | (class_declaration 8 | (class_body 9 | (function_declaration 10 | (modifiers 11 | (annotation 12 | (single_annotation 13 | (user_type 14 | identifier: (type_identifier) @anno (#eq? @anno "Test") 15 | ) 16 | ) 17 | ) 18 | ) 19 | identifier: (simple_identifier) @method 20 | ) @method_body (#offset! @method_body) 21 | ) 22 | ) 23 | ]] 24 | 25 | -- Check if a position is in a range 26 | -- For example: check if the cursor is currently inside a function 27 | -- range: {l0, c0, l1, c0} 28 | -- position: line, col 29 | local function in_position(range, line, col) 30 | local start_line, start_col, end_line, end_col = unpack(range) 31 | 32 | if line == start_line then 33 | return start_col <= col 34 | elseif line == end_line then 35 | return end_col >= col 36 | else 37 | return start_line < line and line < end_line 38 | end 39 | end 40 | 41 | local bufnr = 38 42 | local cursor_line = 44 43 | local cursor_col = 8 44 | local lang_tree = vim.treesitter.get_parser(bufnr, 'kotlin') 45 | local syntax_tree = lang_tree:parse() 46 | local root = syntax_tree[1]:root() 47 | 48 | local query = vim.treesitter.parse_query('kotlin', query_string) 49 | 50 | local lines = {} 51 | local file_name = vim.api.nvim_buf_get_name(bufnr) 52 | 53 | for _, captures, metadata in query:iter_matches(root, bufnr) do 54 | local method_name = q.get_node_text(captures[2], bufnr) 55 | local offset = metadata.content[1] 56 | 57 | -- if in_position(offset, cursor_line, cursor_col) then 58 | -- vim.api.nvim_command("make test --tests " .. "'" .. method_name .. "'") 59 | -- break 60 | -- end 61 | 62 | table.insert( 63 | lines, 64 | file_name .. ':' .. (offset[1] + 1) .. ':' .. (offset[2] + 1) .. ':' .. method_name 65 | ) 66 | end 67 | 68 | local bf = vim.api.nvim_create_buf(false, true) 69 | vim.api.nvim_buf_set_lines(bf, 0, -1, false, lines) 70 | vim.api.nvim_command("cbuffer" .. bf) 71 | 72 | -------------------------------------------------------------------------------- /git/gitui/key_bindings.ron: -------------------------------------------------------------------------------- 1 | // bit for modifiers 2 | // bits: 0 None 3 | // bits: 1 SHIFT 4 | // bits: 2 CONTROL 5 | // 6 | // Note: 7 | // If the default key layout is lower case, 8 | // and you want to use `Shift + q` to trigger the exit event, 9 | // the setting should like this `exit: Some(( code: Char('Q'), modifiers: ( bits: 1,),)),` 10 | // The Char should be upper case, and the shift modified bit should be set to 1. 11 | // 12 | // Note: 13 | // find `KeysList` type in src/keys/key_list.rs for all possible keys. 14 | // every key not overwritten via the config file will use the default specified there 15 | ( 16 | focus_right: Some(( code: Char('l'), modifiers: ( bits: 0,),)), 17 | focus_left: Some(( code: Char('h'), modifiers: ( bits: 0,),)), 18 | focus_above: Some(( code: Char('k'), modifiers: ( bits: 0,),)), 19 | focus_below: Some(( code: Char('j'), modifiers: ( bits: 0,),)), 20 | 21 | open_help: Some(( code: F(1), modifiers: ( bits: 0,),)), 22 | 23 | move_left: Some(( code: Char('h'), modifiers: ( bits: 0,),)), 24 | move_right: Some(( code: Char('l'), modifiers: ( bits: 0,),)), 25 | move_up: Some(( code: Char('k'), modifiers: ( bits: 0,),)), 26 | move_down: Some(( code: Char('j'), modifiers: ( bits: 0,),)), 27 | popup_up: Some(( code: Char('p'), modifiers: ( bits: 2,),)), 28 | popup_down: Some(( code: Char('n'), modifiers: ( bits: 2,),)), 29 | page_up: Some(( code: Char('b'), modifiers: ( bits: 2,),)), 30 | page_down: Some(( code: Char('f'), modifiers: ( bits: 2,),)), 31 | home: Some(( code: Char('g'), modifiers: ( bits: 0,),)), 32 | end: Some(( code: Char('G'), modifiers: ( bits: 1,),)), 33 | shift_up: Some(( code: Char('K'), modifiers: ( bits: 1,),)), 34 | shift_down: Some(( code: Char('J'), modifiers: ( bits: 1,),)), 35 | 36 | edit_file: Some(( code: Char('I'), modifiers: ( bits: 1,),)), 37 | 38 | status_reset_item: Some(( code: Char('U'), modifiers: ( bits: 1,),)), 39 | 40 | diff_reset_lines: Some(( code: Char('u'), modifiers: ( bits: 0,),)), 41 | diff_stage_lines: Some(( code: Char('s'), modifiers: ( bits: 0,),)), 42 | 43 | stashing_save: Some(( code: Char('w'), modifiers: ( bits: 0,),)), 44 | stashing_toggle_index: Some(( code: Char('m'), modifiers: ( bits: 0,),)), 45 | 46 | stash_open: Some(( code: Char('l'), modifiers: ( bits: 0,),)), 47 | 48 | abort_merge: Some(( code: Char('M'), modifiers: ( bits: 1,),)), 49 | ) 50 | -------------------------------------------------------------------------------- /nvim/lua/config/keymaps.lua: -------------------------------------------------------------------------------- 1 | -- Keymaps are automatically loaded on the VeryLazy event 2 | -- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua 3 | -- Add any additional keymaps here 4 | local function map(mode, lhs, rhs, opts) 5 | local options = { remap = false } 6 | if opts then 7 | options = vim.tbl_extend("force", options, opts) 8 | end 9 | vim.keymap.set(mode, lhs, rhs, options) 10 | end 11 | 12 | map("i", "jj", "", { silent = true, desc = "Exit Insert mode" }) 13 | 14 | map({ "v", "n", "o" }, "H", "^", { silent = true, desc = "Move to beginning of line" }) 15 | map({ "v", "n", "o" }, "L", "$", { silent = true, desc = "Move to end of line" }) 16 | 17 | -- v/h for vertical/horizontal split 18 | map("n", "v", ":split") 19 | map("n", "h", ":vsplit") 20 | 21 | -- Ctrl U in insert mode to switch text case of the current word 22 | map("i", "", "mqg~iw`qa") 23 | 24 | -- fp to copy the path of current file to clipboard 25 | map("n", "fp", [[:let @* = expand('%')]]) 26 | 27 | -- x to delete a character without saving it in the " register 28 | map("n", "x", '"_x', { silent = true }) 29 | 30 | map("n", "rl", [[:luafile $MYVIMRC]]) 31 | 32 | -- Disable arrow keys 33 | map("n", "", "") 34 | map("n", "", "") 35 | map("n", "", "") 36 | map("n", "", "") 37 | map("i", "", "") 38 | map("i", "", "") 39 | map("i", "", "") 40 | map("i", "", "") 41 | 42 | -- smart-splits.nvim 43 | -- recommended mappings 44 | -- resizing splits 45 | -- these keymaps will also accept a range, 46 | -- for example `10` will `resize_left` by `(10 * config.default_amount)` 47 | map("n", "", require("smart-splits").resize_left) 48 | map("n", "", require("smart-splits").resize_down) 49 | map("n", "", require("smart-splits").resize_up) 50 | map("n", "", require("smart-splits").resize_right) 51 | -- moving between splits 52 | map("n", "", require("smart-splits").move_cursor_left) 53 | map("n", "", require("smart-splits").move_cursor_down) 54 | map("n", "", require("smart-splits").move_cursor_up) 55 | map("n", "", require("smart-splits").move_cursor_right) 56 | map("n", "", require("smart-splits").move_cursor_previous) 57 | -- swapping buffers between windows 58 | map("n", "h", require("smart-splits").swap_buf_left) 59 | map("n", "j", require("smart-splits").swap_buf_down) 60 | map("n", "k", require("smart-splits").swap_buf_up) 61 | map("n", "l", require("smart-splits").swap_buf_right) 62 | map("n", "r", [[:luafile %]]) 63 | -------------------------------------------------------------------------------- /wezterm/wezterm.lua: -------------------------------------------------------------------------------- 1 | local wezterm = require("wezterm") 2 | local mux = wezterm.mux 3 | local act = wezterm.action 4 | 5 | local config = {} 6 | -- User config builder if possible 7 | 8 | if wezterm.config_builder then 9 | config = wezterm.config_builder() 10 | end 11 | 12 | -- Settings 13 | config.automatically_reload_config = false 14 | config.color_scheme = "Decaf (base16)" 15 | 16 | config.font = wezterm.font_with_fallback({ 17 | { family = "DejaVuSansM Nerd Font", scale = 1.1 }, 18 | { family = "JetBrains Mono", scale = 1.1 }, 19 | }) 20 | 21 | config.window_background_opacity = 0.95 22 | config.macos_window_background_blur = 5 23 | config.window_decorations = "RESIZE" 24 | config.window_padding = { left = 0, right = 0, top = 0, bottom = 0 } 25 | config.scrollback_lines = 5000 26 | config.default_workspace = "home" 27 | config.default_prog = { "/opt/homebrew/bin/fish", "-l" } 28 | config.status_update_interval = 2000 29 | 30 | config.inactive_pane_hsb = { 31 | saturation = 0.7, 32 | brightness = 0.3, 33 | } 34 | 35 | --- @class WeztermWorkspace 36 | --- @field cwd string 37 | --- @field tabs WeztermTab[] 38 | --- 39 | --- @class WeztermTab 40 | --- @field name string 41 | --- @field cwd string 42 | 43 | ---@type table 44 | local workspaces = { 45 | home = { 46 | cwd = "/Users/hapham", 47 | tabs = { 48 | { name = "dot", cwd = "/Users/hapham/projects/personal/dot-files/" }, 49 | { name = "notes", cwd = "/Users/hapham/notes" }, 50 | }, 51 | }, 52 | ["repeat"] = { 53 | cwd = "/Users/hapham/projects/repeat", 54 | tabs = { 55 | { name = "db", cwd = "/Users/hapham/projects/repeat" }, 56 | { name = "payment", cwd = "/Users/hapham/projects/repeat/repeat-payment" }, 57 | { name = "challenge", cwd = "/Users/hapham/projects/repeat/challenge" }, 58 | { name = "symfony", cwd = "/Users/hapham/projects/repeat/xygaming_symfony" }, 59 | { name = "rewards", cwd = "/Users/hapham/projects/repeat/repeat-rewards" }, 60 | { name = "kafka-msg", cwd = "/Users/hapham/projects/repeat/kafka-message-types" }, 61 | { name = "mobile-app", cwd = "/Users/hapham/projects/repeat/repeat-mobile-app" }, 62 | { name = "setup", cwd = "/Users/hapham/projects/repeat/services-docker" }, 63 | { name = "system-test", cwd = "/Users/hapham/projects/repeat/repeat-system-tests" }, 64 | }, 65 | }, 66 | acconto = { 67 | cwd = "/Users/hapham/projects/personal/acconto.ai", 68 | tabs = { 69 | { name = "root", cwd = "/Users/hapham/projects/personal/acconto.ai" }, 70 | { name = "server", cwd = "/Users/hapham/projects/personal/acconto.ai/server" }, 71 | { name = "react", cwd = "/Users/hapham/projects/personal/acconto.ai/React" }, 72 | }, 73 | }, 74 | } 75 | 76 | wezterm.on("gui-startup", function(w, p) 77 | for workspace_name, workspace in pairs(workspaces) do 78 | local _, initialPane, window = mux.spawn_window({ cwd = workspace.cwd, workspace = workspace_name }) 79 | 80 | for _, t in pairs(workspace.tabs) do 81 | window:spawn_tab({ cwd = t.cwd }):set_title(t.name) 82 | end 83 | 84 | -- Remove the initial tab created when creating the window 85 | -- because this initial tab is not in the defined tabs of the workspace 86 | -- As there is no direct way to close the initialTab, we can close the pane in that tab 87 | if #workspace.tabs > 1 then 88 | initialPane:send_text("exit\n") 89 | end 90 | end 91 | 92 | mux.set_active_workspace("home") 93 | end) 94 | 95 | require("status-bar").apply_to_config(config) 96 | require("tab-format").apply_to_config(config) 97 | require("keymappings").apply_to_config(config) 98 | require("plugins").apply_to_config(config) 99 | 100 | return config 101 | -------------------------------------------------------------------------------- /fish/config.fish: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/fish 2 | set -a fish_function_path /Users/hapham/projects/personal/dot-files/fish/functions/hplib 3 | 4 | eval (/opt/homebrew/bin/brew shellenv) 5 | set -x JAVA_HOME (/usr/libexec/java_home -v 17.0.2) 6 | set -x PATH $JAVA_HOME '/Users/hapham/.config/kotlin-language-server/server/build/install/server/bin' $PATH 7 | set -x PATH $PATH $HOME/.cargo/bin 8 | set -x PATH $PATH /usr/local/go/bin 9 | set -x PATH $PATH (go env GOPATH)/bin 10 | set -x PATH $PATH '/Users/hapham/Library/Application Support/edgedb/bin' 11 | set -x PATH $PATH '/usr/hapham/.skdman/bin' 12 | set -x PATH '/Users/hapham/.asdf/installs/python/3.11.6/bin' $PATH 13 | set -x PATH $PATH '/Users/hapham/.bun/bin' 14 | set -x PATH $PATH /opt/homebrew/opt/mysql-client@8.4/bin 15 | set -x PATH $PATH /Users/hapham/mongosh/bin 16 | set -x LC_AL en_US.UTF-8 17 | set -x LANG en_US.UTF-8 18 | set -x GPG_TTY `tty` 19 | set -x MANPAGER "sh -c 'col -bx | bat -l man -p'" 20 | 21 | set -x NVM_DIR "$HOME/.nvm" 22 | 23 | # Configure less to clear screen after exit and case-insensitive search 24 | set -x DELTA_PAGER "/opt/homebrew/bin/less -R -i" 25 | set -x LESS Ri 26 | 27 | set -x DELTA_NAVIGATE 1 # use n/N to navigate file by file in delta 28 | 29 | # Personio 30 | set -x AWS_VAULT_KEYCHAIN_NAME login 31 | set -x AWS_VAULT_KEYCHAIN_NAME 12h 32 | 33 | # pnpm 34 | set -gx PNPM_HOME /Users/hapham/Library/pnpm 35 | set -gx PATH "$PNPM_HOME" $PATH 36 | 37 | # fish_vi_key_bindings 38 | 39 | abbr -a rl 'source ~/.config/fish/config.fish' 40 | abbr -a x exit 41 | abbr -a ef 'nvim ~/projects/dot-files/fish/config.fish' 42 | abbr -a effn 'nvim ~/.config/fish/functions/' 43 | abbr -a ea 'nvim ~/.aws' 44 | abbr -a ls eza 45 | abbr -a ll eza -l 46 | abbr -a lt eza --tree -l --level=3 47 | abbr -a ltg eza --tree -l --git-ignore --level=3 48 | 49 | # Git abbreviations 50 | abbr -a gf 'git fetch -p' 51 | abbr -a gc 'git commit' 52 | abbr -a gst 'git status' 53 | abbr -a gm 'git merge' 54 | abbr -a gma 'git stash; git checkout master || git checkout main;' 55 | abbr -a gbr 'git checkout -b' 56 | abbr -a gp 'git stash pop' 57 | abbr -a gdc 'git checkout -- .' 58 | abbr -a grm 'git rebase master -i; or git rebase main -i' 59 | abbr -a gs 'git status' 60 | abbr -a gbk 'git checkout -' 61 | abbr -a gbp 'git checkout -; git pop' 62 | abbr -a gl 'git log --oneline --no-merges' 63 | abbr -a glm 'git log --oneline' 64 | abbr -a gdf 'git diff' 65 | abbr -a gdfs 'git diff --staged' 66 | abbr -a gu gitui 67 | abbr -a gfu 'git rebase -i HEAD~10' 68 | abbr -a cbr 'git branch --show-current | pbcopy' 69 | abbr -a k kubectl 70 | abbr -a gback 'git checkout -' 71 | abbr -a gcm 'git commit -m' 72 | abbr -a gcma 'git commit -am' 73 | abbr -a gd 'git diff' 74 | abbr -a batdiff 'git diff --name-only --diff-filter=d | xargs bat --diff' 75 | abbr -a r ranger 76 | 77 | abbr -a e nvim 78 | abbr -a lg lazygit 79 | abbr -a pc /opt/homebrew/bin/perctl 80 | abbr -a mc '~/projects/personio/monolith-cli' 81 | abbr -a plg 'lnav ~/projects/personio/app/storage-local/logs/laravel.log' 82 | abbr -a psn 'cd ~/projects/personio' 83 | abbr -a kgp 'kubectl get pods' 84 | abbr -a kct 'kubectl config set current-context' 85 | abbr -a wkgp 'watch kubectl get pods' 86 | abbr -a kdc 'kubectl describe' 87 | abbr -a proj 'cd ~/projects' 88 | abbr -a ev 'nvim ~/projects/dot-files/nvim/init.vim' 89 | abbr -a etm 'nvim ~/projects/dot-files/tmux/tmux.conf' 90 | abbr -a eal 'nvim ~/projects/dot-files/alacritty.yml' 91 | abbr -a tm 'tmux attach || tmux' 92 | abbr -a psql /opt/homebrew/opt/libpq/bin/psql 93 | 94 | abbr -a pre 'pr e' 95 | abbr -a prc 'pr c' 96 | abbr -a pr 'pr cd' 97 | 98 | abbr -a glc './gradlew.local' 99 | abbr -a grd './gradlew' 100 | abbr -a edb edgedb 101 | 102 | # In vi mode, press Ctrl+f to accept autocompletion 103 | bind -M insert \cf forward-char 104 | 105 | # In vi mode, press Ctrl-p/Ctrl-n to search history backward and forward 106 | bind -M insert \cp history-search-backward 107 | bind -M insert \cn history-search-forward 108 | 109 | # In vi mode, jj to escape insert mode 110 | # bind -M insert -m default jj backward-char force-repaint 111 | 112 | fish_add_path /usr/local/opt/ruby/bin 113 | fish_add_path /usr/local/go/bin 114 | set -x GOPATH $HOME/go 115 | fish_add_path $GOPATH/bin 116 | 117 | zoxide init fish --cmd j | source 118 | 119 | # Set color for fish command to make it highlighted 120 | set fish_color_command yellow --bold 121 | set fish_color_param yellow 122 | 123 | function add_newlines --on-event fish_postexec 124 | set -l last_command_status $status 125 | if test "$argv[1]" = clear 126 | # Do nothing 127 | return 128 | end 129 | 130 | echo 131 | echo 132 | 133 | # Check if the last command failed 134 | if test $last_command_status -ne 0 135 | set_color red 136 | echo "🔥 Execution time: $__execution_time. Exit code: $last_command_status" 137 | else 138 | set_color green 139 | echo "✅ Execution time: $__execution_time" 140 | end 141 | set_color brblack 142 | set -l width (tput cols) 143 | printf '%*s\n' $width '' | tr ' ' _ 144 | 145 | echo 146 | echo 147 | set_color normal 148 | end 149 | 150 | function pre_execution --on-event fish_preexec 151 | set -g __execution_time (date "+%Y-%m-%d %H:%M:%S") 152 | end 153 | -------------------------------------------------------------------------------- /wezterm/status-bar.lua: -------------------------------------------------------------------------------- 1 | local wezterm = require("wezterm") 2 | local colors = require("colors") 3 | local utils = require("utils") 4 | local module = {} 5 | 6 | function module.apply_to_config(config) 7 | config.window_frame = { 8 | font = require("wezterm").font({ family = "DejaVuSansM Nerd Font" }), 9 | font_size = 14, 10 | active_titlebar_bg = colors.statusBarBackground, 11 | } 12 | 13 | local function getKeyLayerStatus(window) 14 | local status = "" 15 | if window:leader_is_active() then 16 | status = "Leader " .. wezterm.nerdfonts.md_alpha_l_circle .. " " 17 | elseif window:active_key_table() then 18 | status = window:active_key_table() .. " " .. wezterm.nerdfonts.md_alpha_l_circle .. " " 19 | end 20 | 21 | if #status > 0 then 22 | return utils.formatSegment({ 23 | text = wezterm.pad_left(status, 10), 24 | bg = colors.primaryBackground, 25 | fg = colors.primary, 26 | right = colors.primaryBackground, 27 | }) 28 | end 29 | 30 | status = "______ " .. wezterm.nerdfonts.md_alpha_l_circle_outline .. " " 31 | return utils.formatSegment({ 32 | text = wezterm.pad_left(status, 10), 33 | bg = colors.alternative, 34 | fg = colors.primaryBackground, 35 | right = colors.alternative, 36 | }) 37 | end 38 | 39 | local function getCwd(pane) 40 | local cwd = pane:get_current_working_dir() 41 | local is_project = false 42 | if cwd and cwd.file_path then 43 | cwd = cwd.file_path 44 | local homeDir = wezterm.home_dir 45 | local project_prefix = homeDir .. "/projects/" 46 | is_project = cwd:sub(1, #project_prefix) == project_prefix 47 | if is_project then 48 | cwd = cwd:gsub(project_prefix, "") .. " " .. wezterm.nerdfonts.cod_code .. " " 49 | else 50 | cwd = string.gsub(cwd, homeDir, "~") .. " " .. wezterm.nerdfonts.oct_file_directory_open_fill .. " " 51 | end 52 | else 53 | cwd = "???" .. " " .. wezterm.nerdfonts.oct_file_directory_open_fill .. " " 54 | end 55 | 56 | return utils.formatSegment({ 57 | text = cwd, 58 | }) 59 | end 60 | 61 | local function getGitDiffStats(cwd) 62 | local success, gitStat, _ = wezterm.run_child_process({ "git", "-C", cwd, "diff", "--shortstat" }) 63 | 64 | if success then 65 | local _, _, changeCountString = string.find(gitStat, "(%d+) files? changed") 66 | local _, _, insertionCountString = string.find(gitStat, "(%d+) insertions?") 67 | local _, _, deletionCountString = string.find(gitStat, "(%d+) deletions?") 68 | 69 | return true, changeCountString, insertionCountString, deletionCountString 70 | else 71 | return false, 0, 0, 0 72 | end 73 | end 74 | 75 | local function getGitInfo(pane) 76 | local max_length = 30 77 | local cwd = pane:get_current_working_dir() 78 | if cwd and cwd.file_path then 79 | local gitRepoRoot = require("get-git-dir").getGitDir(cwd.file_path) 80 | if gitRepoRoot then 81 | local gitDir = gitRepoRoot .. "/.git" 82 | local cmd = { "git", "--git-dir", gitDir, "branch", "--show-current" } 83 | local success, branch, error = wezterm.run_child_process(cmd) 84 | 85 | if success then 86 | branch = string.gsub(branch, "\n", "") 87 | if #branch > max_length then 88 | branch = wezterm.truncate_right(branch, max_length - 3) .. "..." 89 | end 90 | 91 | local getStatSuccess, changes, insertions, deletions = getGitDiffStats(cwd.file_path) 92 | local statLine = "" 93 | if getStatSuccess then 94 | if changes then 95 | statLine = statLine .. wezterm.nerdfonts.fa_exclamation_circle .. " " .. changes .. " " 96 | end 97 | if insertions then 98 | statLine = statLine .. wezterm.nerdfonts.fa_plus_circle .. " " .. insertions .. " " 99 | end 100 | if deletions then 101 | statLine = statLine .. wezterm.nerdfonts.fa_minus_circle .. " " .. deletions .. " " 102 | end 103 | end 104 | 105 | return utils.formatSegment({ 106 | text = statLine .. branch .. " " .. wezterm.nerdfonts.oct_git_branch, 107 | bg = colors.secondaryBackground, 108 | fg = colors.secondary, 109 | }) 110 | end 111 | end 112 | end 113 | return utils.formatSegment({ 114 | text = " " .. wezterm.nerdfonts.md_cancel .. " " .. wezterm.nerdfonts.cod_git_commit .. " ", 115 | bg = colors.secondaryBackground, 116 | fg = colors.secondary, 117 | }) 118 | end 119 | 120 | local function getActiveWorkspace() 121 | local workspaceName = " " 122 | -- .. wezterm.nerdfonts.cod_workspace_trusted 123 | .. wezterm.nerdfonts.cod_verified_filled 124 | .. " " 125 | .. wezterm.mux.get_active_workspace():upper() 126 | .. " " 127 | 128 | return utils.formatSegment({ 129 | left = colors.secondaryBackground, 130 | text = workspaceName, 131 | }) 132 | end 133 | 134 | wezterm.on("update-status", function(window, pane) 135 | local rightStatusFormatItem = {} 136 | utils.mergeTable(rightStatusFormatItem, getGitInfo(pane)) 137 | utils.mergeTable(rightStatusFormatItem, getCwd(pane)) 138 | utils.mergeTable(rightStatusFormatItem, getKeyLayerStatus(window)) 139 | 140 | local leftStatusFormatItem = {} 141 | -- utils.mergeTable(leftStatusFormatItem, getHostname(pane)) 142 | utils.mergeTable(leftStatusFormatItem, getActiveWorkspace()) 143 | 144 | window:set_right_status(wezterm.format(rightStatusFormatItem)) 145 | window:set_left_status(wezterm.format(leftStatusFormatItem)) 146 | end) 147 | end 148 | 149 | return module 150 | -------------------------------------------------------------------------------- /fish/functions/fzf_key_bindings.fish: -------------------------------------------------------------------------------- 1 | # Key bindings 2 | # ------------ 3 | function fzf_key_bindings 4 | 5 | # Store current token in $dir as root for the 'find' command 6 | function fzf-file-widget -d "List files and folders" 7 | set -l commandline (__fzf_parse_commandline) 8 | set -l dir $commandline[1] 9 | set -l fzf_query $commandline[2] 10 | 11 | # "-path \$dir'*/\\.*'" matches hidden files/folders inside $dir but not 12 | # $dir itself, even if hidden. 13 | set -q FZF_CTRL_T_COMMAND; or set -l FZF_CTRL_T_COMMAND " 14 | command find -L \$dir -mindepth 1 \\( -path \$dir'*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' \\) -prune \ 15 | -o -type f -print \ 16 | -o -type d -print \ 17 | -o -type l -print 2> /dev/null | sed 's@^\./@@'" 18 | 19 | set -q FZF_TMUX_HEIGHT; or set FZF_TMUX_HEIGHT 40% 20 | begin 21 | set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS" 22 | eval "$FZF_CTRL_T_COMMAND | "(__fzfcmd)' -m --query "'$fzf_query'"' | while read -l r; set result $result $r; end 23 | end 24 | if [ -z "$result" ] 25 | commandline -f repaint 26 | return 27 | else 28 | # Remove last token from commandline. 29 | commandline -t "" 30 | end 31 | for i in $result 32 | commandline -it -- (string escape $i) 33 | commandline -it -- ' ' 34 | end 35 | commandline -f repaint 36 | end 37 | 38 | function fzf-history-widget -d "Show command history" 39 | set -q FZF_TMUX_HEIGHT; or set FZF_TMUX_HEIGHT 40% 40 | begin 41 | set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT $FZF_DEFAULT_OPTS --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m" 42 | 43 | set -l FISH_MAJOR (echo $version | cut -f1 -d.) 44 | set -l FISH_MINOR (echo $version | cut -f2 -d.) 45 | 46 | # history's -z flag is needed for multi-line support. 47 | # history's -z flag was added in fish 2.4.0, so don't use it for versions 48 | # before 2.4.0. 49 | if [ "$FISH_MAJOR" -gt 2 -o \( "$FISH_MAJOR" -eq 2 -a "$FISH_MINOR" -ge 4 \) ]; 50 | history -z | eval (__fzfcmd) --read0 --print0 -q '(commandline)' | read -lz result 51 | and commandline -- $result 52 | else 53 | history | eval (__fzfcmd) -q '(commandline)' | read -l result 54 | and commandline -- $result 55 | end 56 | end 57 | commandline -f repaint 58 | end 59 | 60 | function fzf-cd-widget -d "Change directory" 61 | set -l commandline (__fzf_parse_commandline) 62 | set -l dir $commandline[1] 63 | set -l fzf_query $commandline[2] 64 | 65 | set -q FZF_ALT_C_COMMAND; or set -l FZF_ALT_C_COMMAND " 66 | command find -L \$dir -mindepth 1 \\( -path \$dir'*/\\.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' \\) -prune \ 67 | -o -type d -print 2> /dev/null | sed 's@^\./@@'" 68 | set -q FZF_TMUX_HEIGHT; or set FZF_TMUX_HEIGHT 40% 69 | begin 70 | set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS" 71 | eval "$FZF_ALT_C_COMMAND | "(__fzfcmd)' +m --query "'$fzf_query'"' | read -l result 72 | 73 | if [ -n "$result" ] 74 | cd $result 75 | 76 | # Remove last token from commandline. 77 | commandline -t "" 78 | end 79 | end 80 | 81 | commandline -f repaint 82 | end 83 | 84 | function __fzfcmd 85 | set -q FZF_TMUX; or set FZF_TMUX 0 86 | set -q FZF_TMUX_HEIGHT; or set FZF_TMUX_HEIGHT 40% 87 | if [ $FZF_TMUX -eq 1 ] 88 | echo "fzf-tmux -d$FZF_TMUX_HEIGHT" 89 | else 90 | echo "fzf" 91 | end 92 | end 93 | 94 | bind \ct fzf-file-widget 95 | bind \cr fzf-history-widget 96 | bind \ec fzf-cd-widget 97 | 98 | if bind -M insert > /dev/null 2>&1 99 | bind -M insert \ct fzf-file-widget 100 | bind -M insert \cr fzf-history-widget 101 | bind -M insert \ec fzf-cd-widget 102 | end 103 | 104 | function __fzf_parse_commandline -d 'Parse the current command line token and return split of existing filepath and rest of token' 105 | # eval is used to do shell expansion on paths 106 | set -l commandline (eval "printf '%s' "(commandline -t)) 107 | 108 | if [ -z $commandline ] 109 | # Default to current directory with no --query 110 | set dir '.' 111 | set fzf_query '' 112 | else 113 | set dir (__fzf_get_dir $commandline) 114 | 115 | if [ "$dir" = "." -a (string sub -l 1 $commandline) != '.' ] 116 | # if $dir is "." but commandline is not a relative path, this means no file path found 117 | set fzf_query $commandline 118 | else 119 | # Also remove trailing slash after dir, to "split" input properly 120 | set fzf_query (string replace -r "^$dir/?" '' "$commandline") 121 | end 122 | end 123 | 124 | echo $dir 125 | echo $fzf_query 126 | end 127 | 128 | function __fzf_get_dir -d 'Find the longest existing filepath from input string' 129 | set dir $argv 130 | 131 | # Strip all trailing slashes. Ignore if $dir is root dir (/) 132 | if [ (string length $dir) -gt 1 ] 133 | set dir (string replace -r '/*$' '' $dir) 134 | end 135 | 136 | # Iteratively check if dir exists and strip tail end of path 137 | while [ ! -d "$dir" ] 138 | # If path is absolute, this can keep going until ends up at / 139 | # If path is relative, this can keep going until entire input is consumed, dirname returns "." 140 | set dir (dirname "$dir") 141 | end 142 | 143 | echo $dir 144 | end 145 | 146 | end 147 | -------------------------------------------------------------------------------- /myclirc: -------------------------------------------------------------------------------- 1 | # vi: ft=dosini 2 | [main] 3 | 4 | # Enables context sensitive auto-completion. If this is disabled the all 5 | # possible completions will be listed. 6 | smart_completion = True 7 | 8 | # Multi-line mode allows breaking up the sql statements into multiple lines. If 9 | # this is set to True, then the end of the statements must have a semi-colon. 10 | # If this is set to False then sql statements can't be split into multiple 11 | # lines. End of line (return) is considered as the end of the statement. 12 | multi_line = False 13 | 14 | # Destructive warning mode will alert you before executing a sql statement 15 | # that may cause harm to the database such as "drop table", "drop database" 16 | # or "shutdown". 17 | destructive_warning = True 18 | 19 | # log_file location. 20 | log_file = ~/.mycli.log 21 | 22 | # Default log level. Possible values: "CRITICAL", "ERROR", "WARNING", "INFO" 23 | # and "DEBUG". "NONE" disables logging. 24 | log_level = INFO 25 | 26 | # Log every query and its results to a file. Enable this by uncommenting the 27 | # line below. 28 | # audit_log = ~/.mycli-audit.log 29 | 30 | # Timing of sql statments and table rendering. 31 | timing = True 32 | 33 | # Table format. Possible values: ascii, double, github, 34 | # psql, plain, simple, grid, fancy_grid, pipe, orgtbl, rst, mediawiki, html, 35 | # latex, latex_booktabs, textile, moinmoin, jira, vertical, tsv, csv. 36 | # Recommended: ascii 37 | table_format = ascii 38 | 39 | # Syntax coloring style. Possible values (many support the "-dark" suffix): 40 | # manni, igor, xcode, vim, autumn, vs, rrt, native, perldoc, borland, tango, emacs, 41 | # friendly, monokai, paraiso, colorful, murphy, bw, pastie, paraiso, trac, default, 42 | # fruity. 43 | # Screenshots at http://mycli.net/syntax 44 | # Can be further modified in [colors] 45 | syntax_style = fruity 46 | 47 | # Keybindings: Possible values: emacs, vi. 48 | # Emacs mode: Ctrl-A is home, Ctrl-E is end. All emacs keybindings are available in the REPL. 49 | # When Vi mode is enabled you can use modal editing features offered by Vi in the REPL. 50 | key_bindings = emacs 51 | 52 | # Enabling this option will show the suggestions in a wider menu. Thus more items are suggested. 53 | wider_completion_menu = False 54 | 55 | # MySQL prompt 56 | # \D - The full current date 57 | # \d - Database name 58 | # \h - Hostname of the server 59 | # \m - Minutes of the current time 60 | # \n - Newline 61 | # \P - AM/PM 62 | # \p - Port 63 | # \R - The current time, in 24-hour military time (0-23) 64 | # \r - The current time, standard 12-hour time (1-12) 65 | # \s - Seconds of the current time 66 | # \t - Product type (Percona, MySQL, MariaDB) 67 | # \A - DSN alias name (from the [alias_dsn] section) 68 | # \u - Username 69 | # \x1b[...m - insert ANSI escape sequence 70 | prompt = '\t \u@\h:\d> ' 71 | prompt_continuation = '->' 72 | 73 | # Skip intro info on startup and outro info on exit 74 | less_chatty = False 75 | 76 | # Use alias from --login-path instead of host name in prompt 77 | login_path_as_host = False 78 | 79 | # Cause result sets to be displayed vertically if they are too wide for the current window, 80 | # and using normal tabular format otherwise. (This applies to statements terminated by ; or \G.) 81 | auto_vertical_output = False 82 | 83 | # keyword casing preference. Possible values "lower", "upper", "auto" 84 | keyword_casing = auto 85 | 86 | # disabled pager on startup 87 | enable_pager = False 88 | 89 | # Custom colors for the completion menu, toolbar, etc. 90 | [colors] 91 | completion-menu.completion.current = 'bg:#ffffff #000000' 92 | completion-menu.completion = 'bg:#008888 #ffffff' 93 | completion-menu.meta.completion.current = 'bg:#44aaaa #000000' 94 | completion-menu.meta.completion = 'bg:#448888 #ffffff' 95 | completion-menu.multi-column-meta = 'bg:#aaffff #000000' 96 | scrollbar.arrow = 'bg:#003333' 97 | scrollbar = 'bg:#00aaaa' 98 | selected = '#ffffff bg:#6666aa' 99 | search = '#ffffff bg:#4444aa' 100 | search.current = '#ffffff bg:#44aa44' 101 | bottom-toolbar = 'bg:#222222 #aaaaaa' 102 | bottom-toolbar.off = 'bg:#222222 #888888' 103 | bottom-toolbar.on = 'bg:#222222 #ffffff' 104 | search-toolbar = 'noinherit bold' 105 | search-toolbar.text = 'nobold' 106 | system-toolbar = 'noinherit bold' 107 | arg-toolbar = 'noinherit bold' 108 | arg-toolbar.text = 'nobold' 109 | bottom-toolbar.transaction.valid = 'bg:#222222 #00ff5f bold' 110 | bottom-toolbar.transaction.failed = 'bg:#222222 #ff005f bold' 111 | 112 | # style classes for colored table output 113 | output.header = "#00ff5f bold" 114 | output.odd-row = "" 115 | output.even-row = "" 116 | output.null = "#808080" 117 | 118 | # SQL syntax highlighting overrides 119 | # sql.comment = 'italic #408080' 120 | # sql.comment.multi-line = '' 121 | # sql.comment.single-line = '' 122 | # sql.comment.optimizer-hint = '' 123 | # sql.escape = 'border:#FF0000' 124 | # sql.keyword = 'bold #008000' 125 | # sql.datatype = 'nobold #B00040' 126 | # sql.literal = '' 127 | # sql.literal.date = '' 128 | # sql.symbol = '' 129 | # sql.quoted-schema-object = '' 130 | # sql.quoted-schema-object.escape = '' 131 | # sql.constant = '#880000' 132 | # sql.function = '#0000FF' 133 | # sql.variable = '#19177C' 134 | # sql.number = '#666666' 135 | # sql.number.binary = '' 136 | # sql.number.float = '' 137 | # sql.number.hex = '' 138 | # sql.number.integer = '' 139 | # sql.operator = '#666666' 140 | # sql.punctuation = '' 141 | # sql.string = '#BA2121' 142 | # sql.string.double-quouted = '' 143 | # sql.string.escape = 'bold #BB6622' 144 | # sql.string.single-quoted = '' 145 | # sql.whitespace = '' 146 | 147 | # Favorite queries. 148 | [favorite_queries] 149 | 150 | # Use the -d option to reference a DSN. 151 | # Special characters in passwords and other strings can be escaped with URL encoding. 152 | [alias_dsn] 153 | # example_dsn = mysql://[user[:password]@][host][:port][/dbname] 154 | -------------------------------------------------------------------------------- /nvim/lua/plugins/example.lua: -------------------------------------------------------------------------------- 1 | -- since this is just an example spec, don't actually load anything here and return an empty spec 2 | -- stylua: ignore 3 | if true then return {} end 4 | 5 | -- every spec file under the "plugins" directory will be loaded automatically by lazy.nvim 6 | -- 7 | -- In your plugin files, you can: 8 | -- * add extra plugins 9 | -- * disable/enabled LazyVim plugins 10 | -- * override the configuration of LazyVim plugins 11 | return { 12 | -- add gruvbox 13 | { "ellisonleao/gruvbox.nvim" }, 14 | 15 | -- Configure LazyVim to load gruvbox 16 | { 17 | "LazyVim/LazyVim", 18 | opts = { 19 | colorscheme = "gruvbox", 20 | }, 21 | }, 22 | 23 | -- change trouble config 24 | { 25 | "folke/trouble.nvim", 26 | -- opts will be merged with the parent spec 27 | opts = { use_diagnostic_signs = true }, 28 | }, 29 | 30 | -- disable trouble 31 | { "folke/trouble.nvim", enabled = false }, 32 | 33 | -- override nvim-cmp and add cmp-emoji 34 | { 35 | "hrsh7th/nvim-cmp", 36 | dependencies = { "hrsh7th/cmp-emoji" }, 37 | ---@param opts cmp.ConfigSchema 38 | opts = function(_, opts) 39 | table.insert(opts.sources, { name = "emoji" }) 40 | end, 41 | }, 42 | 43 | -- change some telescope options and a keymap to browse plugin files 44 | { 45 | "nvim-telescope/telescope.nvim", 46 | keys = { 47 | -- add a keymap to browse plugin files 48 | -- stylua: ignore 49 | { 50 | "fp", 51 | function() require("telescope.builtin").find_files({ cwd = require("lazy.core.config").options.root }) end, 52 | desc = "Find Plugin File", 53 | }, 54 | }, 55 | -- change some options 56 | opts = { 57 | defaults = { 58 | layout_strategy = "horizontal", 59 | layout_config = { prompt_position = "top" }, 60 | sorting_strategy = "ascending", 61 | winblend = 0, 62 | }, 63 | }, 64 | }, 65 | 66 | -- add pyright to lspconfig 67 | { 68 | "neovim/nvim-lspconfig", 69 | ---@class PluginLspOpts 70 | opts = { 71 | ---@type lspconfig.options 72 | servers = { 73 | -- pyright will be automatically installed with mason and loaded with lspconfig 74 | pyright = {}, 75 | }, 76 | }, 77 | }, 78 | 79 | -- add tsserver and setup with typescript.nvim instead of lspconfig 80 | { 81 | "neovim/nvim-lspconfig", 82 | dependencies = { 83 | "jose-elias-alvarez/typescript.nvim", 84 | init = function() 85 | require("lazyvim.util").lsp.on_attach(function(_, buffer) 86 | -- stylua: ignore 87 | vim.keymap.set( "n", "co", "TypescriptOrganizeImports", { buffer = buffer, desc = "Organize Imports" }) 88 | vim.keymap.set("n", "cR", "TypescriptRenameFile", { desc = "Rename File", buffer = buffer }) 89 | end) 90 | end, 91 | }, 92 | ---@class PluginLspOpts 93 | opts = { 94 | ---@type lspconfig.options 95 | servers = { 96 | -- tsserver will be automatically installed with mason and loaded with lspconfig 97 | tsserver = {}, 98 | }, 99 | -- you can do any additional lsp server setup here 100 | -- return true if you don't want this server to be setup with lspconfig 101 | ---@type table 102 | setup = { 103 | -- example to setup with typescript.nvim 104 | tsserver = function(_, opts) 105 | require("typescript").setup({ server = opts }) 106 | return true 107 | end, 108 | -- Specify * to use this function as a fallback for any server 109 | -- ["*"] = function(server, opts) end, 110 | }, 111 | }, 112 | }, 113 | 114 | -- for typescript, LazyVim also includes extra specs to properly setup lspconfig, 115 | -- treesitter, mason and typescript.nvim. So instead of the above, you can use: 116 | { import = "lazyvim.plugins.extras.lang.typescript" }, 117 | 118 | -- add more treesitter parsers 119 | { 120 | "nvim-treesitter/nvim-treesitter", 121 | opts = { 122 | ensure_installed = { 123 | "bash", 124 | "html", 125 | "javascript", 126 | "json", 127 | "lua", 128 | "markdown", 129 | "markdown_inline", 130 | "python", 131 | "query", 132 | "regex", 133 | "tsx", 134 | "typescript", 135 | "vim", 136 | "yaml", 137 | }, 138 | }, 139 | }, 140 | 141 | -- since `vim.tbl_deep_extend`, can only merge tables and not lists, the code above 142 | -- would overwrite `ensure_installed` with the new value. 143 | -- If you'd rather extend the default config, use the code below instead: 144 | { 145 | "nvim-treesitter/nvim-treesitter", 146 | opts = function(_, opts) 147 | -- add tsx and treesitter 148 | vim.list_extend(opts.ensure_installed, { 149 | "tsx", 150 | "typescript", 151 | }) 152 | end, 153 | }, 154 | 155 | -- the opts function can also be used to change the default opts: 156 | { 157 | "nvim-lualine/lualine.nvim", 158 | event = "VeryLazy", 159 | opts = function(_, opts) 160 | table.insert(opts.sections.lualine_x, { 161 | function() 162 | return "😄" 163 | end, 164 | }) 165 | end, 166 | }, 167 | 168 | -- or you can return new options to override all the defaults 169 | { 170 | "nvim-lualine/lualine.nvim", 171 | event = "VeryLazy", 172 | opts = function() 173 | return { 174 | --[[add your custom lualine config here]] 175 | } 176 | end, 177 | }, 178 | 179 | -- use mini.starter instead of alpha 180 | { import = "lazyvim.plugins.extras.ui.mini-starter" }, 181 | 182 | -- add jsonls and schemastore packages, and setup treesitter for json, json5 and jsonc 183 | { import = "lazyvim.plugins.extras.lang.json" }, 184 | 185 | -- add any tools you want to have installed below 186 | { 187 | "williamboman/mason.nvim", 188 | opts = { 189 | ensure_installed = { 190 | "stylua", 191 | "shellcheck", 192 | "shfmt", 193 | "flake8", 194 | }, 195 | }, 196 | }, 197 | } 198 | -------------------------------------------------------------------------------- /nvim/lazy-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "LazyVim": { "branch": "main", "commit": "4ebcd611b2c81de9badba26146ee86ed4020cee5" }, 3 | "LuaSnip": { "branch": "master", "commit": "73813308abc2eaeff2bc0d3f2f79270c491be9d7" }, 4 | "SchemaStore.nvim": { "branch": "main", "commit": "c8af3f44c68757344b4dcb82e2ac48892b1be765" }, 5 | "auto-save.nvim": { "branch": "main", "commit": "5fbcaac0a2698c87a9a1bd2083cb6949505cca12" }, 6 | "blink.cmp": { "branch": "main", "commit": "327fff91fe6af358e990be7be1ec8b78037d2138" }, 7 | "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, 8 | "catppuccin": { "branch": "main", "commit": "c89184526212e04feffbddda9d06b041a8fca416" }, 9 | "colorful-winsep.nvim": { "branch": "alpha", "commit": "642afcd59d900b2ab2493fa7f03e64a1f7eeb8b5" }, 10 | "conform.nvim": { "branch": "master", "commit": "c64cc754ace603e185ab30113aaef174187eacf8" }, 11 | "copier.nvim": { "branch": "master", "commit": "57a364a9deb2944e50f6e6eb775868e487da1a02" }, 12 | "crates.nvim": { "branch": "main", "commit": "ac9fa498a9edb96dc3056724ff69d5f40b898453" }, 13 | "flash.nvim": { "branch": "main", "commit": "b68bda044d68e4026c4e1ec6df3c5afd7eb8e341" }, 14 | "focus.nvim": { "branch": "master", "commit": "5500e1a9e926eec5a361d910679282fd723c0a96" }, 15 | "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, 16 | "fzf-lua": { "branch": "main", "commit": "4be5156ea8fae0a4914e8c3a4f005dc133019599" }, 17 | "gitlinker.nvim": { "branch": "master", "commit": "7c1fae10e39fba627a433a0d7126683c79af289f" }, 18 | "gitsigns.nvim": { "branch": "main", "commit": "0c6826374f47fcbb2b53053986ccc59c115044ff" }, 19 | "grug-far.nvim": { "branch": "main", "commit": "48f9afb684de1c191af7bed96bc1db85ba33f6a4" }, 20 | "gruvbox.nvim": { "branch": "main", "commit": "5e0a460d8e0f7f669c158dedd5f9ae2bcac31437" }, 21 | "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, 22 | "lazydev.nvim": { "branch": "main", "commit": "258d2a5ef4a3e3d6d9ba9da72c9725c53e9afcbd" }, 23 | "lualine.nvim": { "branch": "master", "commit": "b8c23159c0161f4b89196f74ee3a6d02cdc3a955" }, 24 | "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, 25 | "mason-lspconfig.nvim": { "branch": "main", "commit": "f760507df8c49a4bf46a4d12e1fc616797508979" }, 26 | "mason.nvim": { "branch": "main", "commit": "a83eabdc8c49c0c93bf5bb162fa3b57404a9d095" }, 27 | "mini.ai": { "branch": "main", "commit": "e0d00c227112e942ed2789dd4c21d651002831c0" }, 28 | "mini.comment": { "branch": "main", "commit": "796eff9194389220c8d89e0303857630adaaf786" }, 29 | "mini.files": { "branch": "main", "commit": "d22c5b74b7764d0bd33e4988e5ee00139cfe22e3" }, 30 | "mini.hipatterns": { "branch": "main", "commit": "1e0e8f51d50b18eb23b50eef8d97bfd9482e29d9" }, 31 | "mini.icons": { "branch": "main", "commit": "e8fae66cb400744daeedf6e387347df50271c252" }, 32 | "mini.indentscope": { "branch": "main", "commit": "fc1bb1e4573f7174cb6e2bbabc3453340a9eec16" }, 33 | "mini.pairs": { "branch": "main", "commit": "bada72fe4ec607f882a098d15aa4a3279bc6883d" }, 34 | "mini.surround": { "branch": "main", "commit": "aec6ed2902a2fd809e3c2fe79ee4568791285201" }, 35 | "neo-tree.nvim": { "branch": "main", "commit": "8dd9f08ff086d09d112f1873f88dc0f74b598cdb" }, 36 | "neotest": { "branch": "master", "commit": "2cf3544fb55cdd428a9a1b7154aea9c9823426e8" }, 37 | "neotest-golang": { "branch": "main", "commit": "dd5f63b6dc9fe8d8c9b5fc1c5651437e3d2cf0f3" }, 38 | "neotest-python": { "branch": "master", "commit": "7cab6e2ecc260bf61b97ca147574a470bd880cbd" }, 39 | "noice.nvim": { "branch": "main", "commit": "0427460c2d7f673ad60eb02b35f5e9926cf67c59" }, 40 | "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, 41 | "nvim-lint": { "branch": "master", "commit": "335a6044be16d7701001059cba9baa36fbeef422" }, 42 | "nvim-lspconfig": { "branch": "master", "commit": "db8fef885009fdec0daeff3e5dda92e1f539611e" }, 43 | "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, 44 | "nvim-treesitter": { "branch": "main", "commit": "77362027f7aa850c87419fd571151e76b0b342a6" }, 45 | "nvim-treesitter-context": { "branch": "master", "commit": "41847d3dafb5004464708a3db06b14f12bde548a" }, 46 | "nvim-treesitter-textobjects": { "branch": "main", "commit": "1b2d85d3de6114c4bcea89ffb2cd1ce9e3a19931" }, 47 | "nvim-ts-autotag": { "branch": "main", "commit": "c4ca798ab95b316a768d51eaaaee48f64a4a46bc" }, 48 | "nvim-ts-context-commentstring": { "branch": "main", "commit": "1b212c2eee76d787bbea6aa5e92a2b534e7b4f8f" }, 49 | "obsidian.nvim": { "branch": "main", "commit": "ae1f76a75c7ce36866e1d9342a8f6f5b9c2caf9b" }, 50 | "persistence.nvim": { "branch": "main", "commit": "166a79a55bfa7a4db3e26fc031b4d92af71d0b51" }, 51 | "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, 52 | "render-markdown.nvim": { "branch": "main", "commit": "9ab9dade85d8c7d411cc89b592028da3d1b7955a" }, 53 | "rest.nvim": { "branch": "main", "commit": "de9726ab956e30202aafbcdea83c1d6bffe54227" }, 54 | "rustaceanvim": { "branch": "master", "commit": "7c9271934d926969e920f7da932da6ba234b1e5a" }, 55 | "smart-splits.nvim": { "branch": "master", "commit": "652fbde8a997b9c9d32030dfaf2e7e1319dda7a3" }, 56 | "snacks.nvim": { "branch": "main", "commit": "bfe8c26dbd83f7c4fbc222787552e29b4eccfcc0" }, 57 | "tiny-inline-diagnostic.nvim": { "branch": "main", "commit": "29315861711f11daf75e1cf0953ab92ec1a3e69f" }, 58 | "todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" }, 59 | "tokyonight.nvim": { "branch": "main", "commit": "4d159616aee17796c2c94d2f5f87d2ee1a3f67c7" }, 60 | "trouble.nvim": { "branch": "main", "commit": "f176232e7759c4f8abd923c21e3e5a5c76cd6837" }, 61 | "ts-comments.nvim": { "branch": "main", "commit": "1bd9d0ba1d8b336c3db50692ffd0955fe1bb9f0c" }, 62 | "venv-selector.nvim": { "branch": "main", "commit": "ab5002d83817e481f7eef07b488c7e402d231bcf" }, 63 | "vim-dadbod": { "branch": "master", "commit": "e95afed23712f969f83b4857a24cf9d59114c2e6" }, 64 | "vim-dadbod-completion": { "branch": "master", "commit": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6" }, 65 | "vim-dadbod-ui": { "branch": "master", "commit": "e8b53c0f3aa6e6127ac2a2d2071d9aade6c6e373" }, 66 | "vim-nightfly-colors": { "branch": "master", "commit": "f32c881d2f55fd79917cd6770f604821058cccdc" }, 67 | "which-key.nvim": { "branch": "main", "commit": "904308e6885bbb7b60714c80ab3daf0c071c1492" }, 68 | "yop.nvim": { "branch": "main", "commit": "ec26d86cfa96783f6894babcc509e5287aef9a25" } 69 | } 70 | -------------------------------------------------------------------------------- /tmux/tmux.conf: -------------------------------------------------------------------------------- 1 | unbind-key -a # Clear all default key binding 2 | unbind C-b 3 | set -g prefix C-f 4 | bind C-f send-prefix 5 | 6 | set-option -g default-shell /opt/homebrew/bin/fish 7 | set -g default-terminal "screen-256color" 8 | set -as terminal-features ",alacritty*:RGB" 9 | 10 | # Start windows and pane number with 1 instead of 0 11 | set -g base-index 1 12 | setw -g pane-base-index 1 13 | 14 | # Re-number windows when one is closed 15 | set -g renumber-windows 1 16 | 17 | # Word separators 18 | setw -g word-separators ' @"=()[]_-:,.' 19 | setw -ag word-separators "'" 20 | 21 | # Show times longer than supposed 22 | set -g display-panes-time 2000 23 | 24 | # tmux messages are displayed for 4 seconds 25 | set -g display-time 2000 26 | 27 | # set tmux history limit 28 | set -g history-limit 30000 29 | 30 | # Faster command sequence 31 | set -s escape-time 0 32 | 33 | # Increase repeat timeout 34 | set -sg repeat-time 600 35 | 36 | # Set focus-events 37 | set-option -g focus-events on 38 | 39 | # Split window vertically and horizontally, open new pane in the same directory 40 | bind-key h split-window -h -c '#{pane_current_path}' 41 | bind-key v split-window -v -c '#{pane_current_path}' 42 | 43 | # Reload source file ~/.tmux.conf 44 | unbind r 45 | bind r source-file ~/.tmux.conf \; display "Reloaded!" 46 | 47 | # Resize all panes equally 48 | bind-key | select-layout even-horizontal 49 | bind-key = select-layout even-vertical 50 | 51 | # Disable confirm killing pane 52 | # bind-key x kill-pane 53 | 54 | # Resize panes 55 | bind-key -r J resize-pane -D 5 56 | bind-key -r K resize-pane -U 5 57 | bind-key -r H resize-pane -L 5 58 | bind-key -r L resize-pane -R 5 59 | 60 | # Select panes 61 | # NOTE(arslan): See to prevent cycling https://github.com/tmux/tmux/issues/1158 62 | bind -n C-h if -F '#{pane_at_left}' '' 'select-pane -L' 63 | bind -n C-l if -F '#{pane_at_right}' '' 'select-pane -R' 64 | bind -n C-k if -F '#{pane_at_top}' '' 'select-pane -U' 65 | bind -n C-j if -F '#{pane_at_bottom}' '' 'select-pane -D' 66 | 67 | # This tmux statusbar config was created by tmuxline.vim 68 | # on Wed, 25 Nov 2015 69 | set -g status "on" 70 | set -g status-bg "colour236" 71 | set -g status-justify "left" 72 | set -g status-position "top" 73 | set -g status-left-length "100" 74 | set -g status-right-length "100" 75 | set -g status-left "#[fg=colour151,bg=colour232,bold] #S #[fg=colour148,bg=colour236,nobold,nounderscore,noitalics]" 76 | set -g status-right "#(gitmux -cfg ~/projects/dot-files/git/gitmux.yml '#{pane_current_path}') #{?client_prefix,#[bg=colour2],} #[fg=colour240,bg=colour236,nobold,nounderscore,noitalics]#[fg=colour250,bg=colour240] %Y-%m-%d %H:%M #[fg=colour252,bg=colour240,nobold,nounderscore,noitalics]#[fg=colour241,bg=colour252] #h " 77 | 78 | setw -g window-status-separator "" 79 | # setw -g window-status-format "#[fg=colour255,bg=colour241] #I #[fg=colour255,bg=colour241]#W " 80 | setw -g window-status-format "#[fg=colour255,bg=colour241] #W " 81 | setw -g window-status-current-format "#[fg=colour0,bg=colour178]#{?window_zoomed_flag,#[fg=green][],} #W #[fg=colour0,bg=colour236,nobold,nounderscore,noitalics]" 82 | 83 | 84 | # List of plugins 85 | # see this https://github.com/tmux-plugins/tpm to installation 86 | set -g @plugin 'tmux-plugins/tpm' 87 | set -g @plugin 'tmux-plugins/tmux-open' 88 | set -g @plugin 'tmux-plugins/tmux-yank' 89 | set -g @plugin 'tmux-plugins/tmux-resurrect' 90 | set -g @plugin 'tmux-plugins/tmux-continuum' 91 | set -g @plugin 'wfxr/tmux-fzf-url' 92 | 93 | # enabling auto saving tmux sessions 94 | set -g @continuum-restore 'on' 95 | 96 | # Set inactive/ active window styles 97 | set -g pane-border-style 'fg=colour8,bg=terminal' 98 | set -g pane-active-border-style 'fg=colour51,bg=terminal' 99 | set -g window-active-style 'fg=terminal,bg=terminal' 100 | set -g window-style 'fg=terminal,bg=terminal' 101 | set -g pane-border-status top 102 | 103 | # Smart pane switching with awareness of Vim splits. 104 | # See: https://github.com/christoomey/vim-tmux-navigator 105 | is_vim="ps -o state= -o comm= -t '#{pane_tty}' \ 106 | | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'" 107 | bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L' 108 | bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D' 109 | bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U' 110 | bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R' 111 | tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")' 112 | if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \ 113 | "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\' 'select-pane -l'" 114 | if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \ 115 | "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\' 'select-pane -l'" 116 | 117 | bind-key -T copy-mode-vi 'C-h' select-pane -L 118 | bind-key -T copy-mode-vi 'C-j' select-pane -D 119 | bind-key -T copy-mode-vi 'C-k' select-pane -U 120 | bind-key -T copy-mode-vi 'C-l' select-pane -R 121 | bind-key -T copy-mode-vi 'C-\' select-pane -l 122 | 123 | # Turn vi binding copy mode 124 | set-option -g status-keys vi 125 | set-window-option -g mode-keys vi 126 | 127 | # Copy in copy mode like vim 128 | bind -T copy-mode-vi v send -X begin-selection 129 | bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "pbcopy" 130 | 131 | # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) 132 | run -b '~/.tmux/plugins/tpm/tpm' 133 | 134 | # Popup window for quick action 135 | bind-key -n 'M-Enter' display-menu -T 'Please choose:' \ 136 | "Watch default pods" D "display-popup -EE 'watch kubectl get pods'" \ 137 | "Watch kube-system pods" K "display-popup -EE 'watch kubectl get pods -n kube-system'" \ 138 | "Copy name of a K8s pod" P "display-popup -EE 'fish -c cpd'" \ 139 | "" \ 140 | "System task manager" H "display-popup -EE -h 80% -w 80% htop" \ 141 | "New terminal" n "display-popup -EE -h 80% -w 80%" \ 142 | "" \ 143 | "Run all test (Kotlin mS)" T "send-keys './gradlew.local :test --info' 'Enter'" \ 144 | "Build project (Kotlin mS)" B "send-keys './gradlew.local :testClasses --info' 'Enter'" \ 145 | 146 | bind-key w popup -EE '~/projects/dot-files/tmux/switch-tmux-window.fish' 147 | bind-key s popup -EE '~/projects/dot-files/tmux/switch-tmux-session.fish' 148 | bind-key : command-prompt 149 | bind-key p popup -E 'fish ~/projects/dot-files/fish/tmux_wind_project.fish' 150 | bind-key c new-window 151 | bind-key [ copy-mode 152 | bind-key n command-prompt -p "Enter the new window name:" "rename-window '%%'" 153 | bind-key p popup -E 'fish ~/projects/dot-files/fish/tmux_wind_project.fish' 154 | -------------------------------------------------------------------------------- /install/setup_configs.fish: -------------------------------------------------------------------------------- 1 | #!/opt/homebrew/bin/fish 2 | 3 | mkdir -p $HOME/.config 4 | 5 | set dir_dot_files $HOME/projects/personal/dot-files 6 | set dir_config $HOME/.config 7 | 8 | # ============================================================================ 9 | # Utils 10 | # ============================================================================ 11 | 12 | function file_not_exist 13 | if not test -e $argv[1] 14 | return 0 15 | else 16 | return 1 17 | end 18 | end 19 | 20 | function dir_not_exist 21 | if not test -d $argv[1] 22 | return 0 23 | else 24 | return 1 25 | end 26 | end 27 | 28 | function symlink_not_exist 29 | if not test -L $argv[1] 30 | return 0 31 | else 32 | return 1 33 | end 34 | end 35 | 36 | # ============================================================================ 37 | # Fish config 38 | # ============================================================================ 39 | set sdir_fish_config $dir_dot_files/fish 40 | set ddir_fish_config $dir_config/fish 41 | 42 | function link_fish_config 43 | set -l sfile_fish_config $sdir_fish_config/config.fish 44 | set -l dfile_fish_config $ddir_fish_config/config.fish 45 | 46 | if symlink_not_exist $dfile_fish_config 47 | echo "Linking fish config..." 48 | mkdir $ddir_fish_config 49 | ln -s $sfile_fish_config $dfile_fish_config 50 | echo "Fish config is linked successfully" 51 | else 52 | echo "Fish config is linked already. Skip." 53 | end 54 | end 55 | 56 | function link_fish_functions 57 | set -l sdir_fish_functions $sdir_fish_config/functions 58 | set -l ddir_fish_functions $ddir_fish_config/functions 59 | 60 | if symlink_not_exist $ddir_fish_functions 61 | echo "Linking fish functions..." 62 | mkdir $ddir_fish_config 63 | rm -rf $ddir_fish_functions 64 | ln -s $sdir_fish_functions $ddir_fish_functions 65 | echo "Fish functions are linked successfully" 66 | else 67 | echo "Fish functions are linked already. Skip" 68 | end 69 | end 70 | 71 | function install_oh_my_fish 72 | if type -q omf 73 | echo "Oh my fish is already installed. Skip installation." 74 | return 75 | end 76 | 77 | echo "Installing Oh my fish..." 78 | curl -L https://get.oh-my.fish | fish 79 | omf theme zish 80 | 81 | if test $status -eq 0 82 | echo "Oh my fish is installed successfully" 83 | else 84 | echo "Failed to install Oh my fish" 85 | end 86 | end 87 | 88 | # ============================================================================ 89 | # tmux 90 | # ============================================================================ 91 | function link_tmux_config_file 92 | set sfile_tmux_config $dir_dot_files/tmux/tmux.conf 93 | set dfile_tmux_config $HOME/.tmux.conf 94 | 95 | if symlink_not_exist $dfile_tmux_config 96 | echo "Linking Tmux config..." 97 | ln -s $sfile_tmux_config $dfile_tmux_config 98 | echo "Tmux config is linked successfully" 99 | echo "Cloning Tmux plugin manager..." 100 | git clone https://github.com/tmux-plugins/tpm $HOME/.tmux/plugins/tpm 101 | else 102 | echo "Tmux config is linked already. Skip" 103 | end 104 | end 105 | 106 | # ============================================================================ 107 | # Alacritty 108 | # ============================================================================ 109 | function link_alacritty 110 | set sfile_alacritty_config $dir_dot_files/alacritty.toml 111 | set ddir_alacritty_config $dir_config/alacritty 112 | set dfile_alacritty_config $ddir_alacritty_config/alacritty.toml 113 | 114 | if symlink_not_exist $dfile_alacritty_config 115 | echo "Linking Alacritty config..." 116 | mkdir -p $ddir_alacritty_config 117 | ln -s $sfile_alacritty_config $dfile_alacritty_config 118 | echo "Alacritty config is linked successfully" 119 | else 120 | echo "Alacritty config is linked already. Skip" 121 | end 122 | end 123 | 124 | # ============================================================================ 125 | # Neo vim 126 | # ============================================================================ 127 | function link_neo_vim 128 | set sfile_nvim_config $dir_dot_files/nvim/init.lua 129 | set ddir_nvim_config $dir_config/nvim 130 | set dfile_nvim_config $ddir_nvim_config/init.lua 131 | set sdir_nvim_lua $dir_dot_files/nvim/lua 132 | set ddir_nvim_lua $dir_nvim_config/lua 133 | 134 | if symlink_not_exist $dfile_nvim_config 135 | echo "Linking Neovim config..." 136 | mkdir -p $ddir_nvim_config 137 | ln -s $sfile_nvim_config $dfile_nvim_config 138 | ln -s $sdir_nvim_lua $ddir_nvim_lua 139 | echo "Neovim config is linked successfully" 140 | else 141 | echo "Neo vim config is linked already. Skip" 142 | end 143 | end 144 | 145 | # ============================================================================ 146 | # Linking config for IdeaVim plugin (Intellij IDEA) 147 | # ============================================================================ 148 | function link_idea_vimrc 149 | set sfile_ideavim_config $dir_dot_files/jetbrains/ideavimrc 150 | set dfile_ideavim_config $HOME/.ideavimrc 151 | 152 | if symlink_not_exist $dfile_ideavim_config 153 | echo "Linking IdeaVim config..." 154 | ln -s $sfile_ideavim_config $dfile_ideavim_config 155 | echo "Intellij IdeaVim config is linked successfully" 156 | else 157 | echo "Intellij IdeaVim config is linked already. Skip" 158 | end 159 | end 160 | 161 | # ============================================================================ 162 | # Linking config for gitui 163 | # More info: https://github.com/extrawurst/gitui/blob/master/KEY_CONFIG.md 164 | # ============================================================================ 165 | function link_gitui 166 | set sfile_gitui_config $dir_dot_files/git/gitui/key_bindings.ron 167 | set ddir_gitui_config $HOME/.config/gitui 168 | set dfile_gitui_config $ddir_gitui_config/key_bindings.ron 169 | 170 | if symlink_not_exist $dfile_gitui_config 171 | echo "Linking gitui key binding config..." 172 | mkdir -p $ddir_gitui_config 173 | ln -s $sfile_gitui_config $dfile_gitui_config 174 | echo "Gitui key binding config is linked successfully" 175 | else 176 | echo "Gitui key binding config is linked already. Skip" 177 | end 178 | end 179 | 180 | # ============================================================================ 181 | # Linking config for gitui 182 | # More info: https://github.com/extrawurst/gitui/blob/master/KEY_CONFIG.md 183 | # ============================================================================ 184 | function link_gitconfig 185 | set sfile_git_config $dir_dot_files/git/gitconfig 186 | set dfile_git_config $HOME/.gitconfig 187 | 188 | if symlink_not_exist $dfile_git_config 189 | echo "Linking git config..." 190 | ln -s $sfile_git_config $dfile_git_config 191 | echo "Git config is linked successfully" 192 | else 193 | echo "Git config is linked already. Skip" 194 | end 195 | end 196 | 197 | link_fish_config 198 | link_fish_functions 199 | install_oh_my_fish 200 | link_tmux_config_file 201 | link_alacritty 202 | link_neo_vim 203 | link_idea_vimrc 204 | link_gitui 205 | link_gitconfig 206 | 207 | # Use VIM key binding for fish 208 | fish_vi_key_bindings 209 | -------------------------------------------------------------------------------- /wezterm/keymappings.lua: -------------------------------------------------------------------------------- 1 | local wezterm = require("wezterm") 2 | local utils = require("utils") 3 | local act = wezterm.action 4 | local module = {} 5 | 6 | function module.apply_to_config(config) 7 | config.leader = { key = "f", mods = "CTRL", timeout_milliseconds = 3000 } 8 | 9 | config.keys = { 10 | { key = "f", mods = "LEADER", action = act.SendKey({ key = "f", mods = "CTRL" }) }, 11 | { key = "f", mods = "LEADER|CTRL", action = act.SendKey({ key = "f", mods = "CTRL" }) }, 12 | { 13 | key = "h", 14 | mods = "LEADER", 15 | action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }), 16 | }, 17 | { 18 | key = "v", 19 | mods = "LEADER", 20 | action = act.SplitVertical({ domain = "CurrentPaneDomain" }), 21 | }, 22 | -- Reload Wezterm config 23 | { key = "r", mods = "LEADER", action = act.ReloadConfiguration }, 24 | 25 | -- Showing Debug overlay 26 | { key = "D", mods = "LEADER", action = act.ShowDebugOverlay }, 27 | 28 | -- Switch panes 29 | { key = "h", mods = "CTRL", action = act.ActivatePaneDirection("Left") }, 30 | { key = "j", mods = "CTRL", action = act.ActivatePaneDirection("Down") }, 31 | { key = "k", mods = "CTRL", action = act.ActivatePaneDirection("Up") }, 32 | { key = "l", mods = "CTRL", action = act.ActivatePaneDirection("Right") }, 33 | 34 | -- Resize panes 35 | { key = "h", mods = "OPT", action = act.AdjustPaneSize({ "Left", 1 }) }, 36 | { key = "j", mods = "OPT", action = act.AdjustPaneSize({ "Down", 1 }) }, 37 | { key = "k", mods = "OPT", action = act.AdjustPaneSize({ "Up", 1 }) }, 38 | { key = "l", mods = "OPT", action = act.AdjustPaneSize({ "Right", 1 }) }, 39 | 40 | -- Activate command palette 41 | { key = ":", mods = "LEADER", action = act.ActivateCommandPalette }, 42 | 43 | -- Zoom in a pane 44 | { key = "Enter", mods = "LEADER", action = act.TogglePaneZoomState }, 45 | 46 | -- Rotate panes 47 | { key = "]", mods = "LEADER", action = act.RotatePanes("Clockwise") }, 48 | 49 | -- Manipulating tabs 50 | { key = "c", mods = "LEADER", action = act.SpawnTab("CurrentPaneDomain") }, 51 | 52 | --Activate other key tables 53 | { 54 | key = "2", 55 | mods = "LEADER", 56 | action = act.ActivateKeyTable({ 57 | name = "repeated", 58 | one_shot = false, 59 | }), 60 | }, 61 | { 62 | key = "3", 63 | mods = "LEADER", 64 | action = act.ActivateKeyTable({ 65 | name = "one_hit", 66 | one_shot = true, 67 | }), 68 | }, 69 | 70 | -- Switching tabs 71 | { 72 | key = "t", 73 | mods = "LEADER", 74 | action = wezterm.action_callback(function(win, pane) 75 | local tabInfo = utils.map(win:mux_window():tabs_with_info(), function(index, tab) 76 | local title = tab.tab:get_title() 77 | title = not title or #title == 0 and tostring(index) or title 78 | return { label = title, id = tostring(index - 1) } 79 | end) 80 | 81 | win:perform_action( 82 | act.InputSelector({ 83 | action = wezterm.action_callback(function(w, p, id, label) 84 | if label then 85 | w:perform_action(act.ActivateTab(tonumber(id)), p) 86 | end 87 | end), 88 | choices = tabInfo, 89 | fuzzy_description = "Choose a tab:", 90 | fuzzy = true, 91 | }), 92 | pane 93 | ) 94 | end), 95 | }, 96 | 97 | -- Switching workspaces 98 | { 99 | key = "w", 100 | mods = "LEADER", 101 | action = wezterm.action_callback(function(window, pane) 102 | local workspaces = wezterm.mux.get_workspace_names() 103 | 104 | -- Add an option to create new workspace 105 | table.insert(workspaces, "!!new-workspace") 106 | 107 | local choices = utils.map(workspaces, function(id, w) 108 | return { label = w } 109 | end) 110 | 111 | window:perform_action( 112 | act.InputSelector({ 113 | choices = choices, 114 | fuzzy_description = "Choose a workspace:", 115 | fuzzy = true, 116 | action = wezterm.action_callback(function(w, p, _, label) 117 | if not label then 118 | return 119 | end 120 | if label == "!!new-workspace" then 121 | -- Ask for new workspace name and spawn it 122 | w:perform_action( 123 | act.PromptInputLine({ 124 | description = "Enter workspace name:", 125 | action = wezterm.action_callback(function(w, p, line) 126 | if line then 127 | w:perform_action(act.SwitchToWorkspace({ name = line }), p) 128 | end 129 | end), 130 | }), 131 | p 132 | ) 133 | else 134 | w:perform_action(act.SwitchToWorkspace({ name = label }), p) 135 | end 136 | end), 137 | }), 138 | pane 139 | ) 140 | end), 141 | }, 142 | 143 | -- Copy mode 144 | { key = "[", mods = "LEADER", action = act.ActivateCopyMode }, 145 | { key = "o", mods = "LEADER", action = act.ActivateLastTab }, 146 | 147 | -- Open dot-file tab 148 | { 149 | key = "j", 150 | mods = "LEADER", 151 | action = act.SwitchToWorkspace({ name = "home" }), 152 | }, 153 | { 154 | key = "k", 155 | mods = "LEADER", 156 | action = act.SwitchToWorkspace({ name = "repeat" }), 157 | }, 158 | { 159 | key = "l", 160 | mods = "LEADER", 161 | action = act.SwitchToWorkspace({ name = "acconto" }), 162 | }, 163 | { 164 | key = ".", 165 | mods = "LEADER", 166 | action = act.Multiple({ 167 | act.SwitchToWorkspace({ name = "home" }), 168 | wezterm.action_callback(function(w, p) 169 | w:perform_action(act.ActivateTab(0), p) 170 | end), 171 | }), 172 | }, 173 | 174 | -- Open notes tab 175 | { 176 | key = "n", 177 | mods = "LEADER", 178 | action = act.Multiple({ 179 | act.SwitchToWorkspace({ name = "home" }), 180 | wezterm.action_callback(function(w, p) 181 | w:perform_action(act.ActivateTab(1), p) 182 | end), 183 | }), 184 | }, 185 | { 186 | key = "y", 187 | mods = "LEADER", 188 | action = act.QuickSelectArgs({ 189 | label = "Open URL", 190 | patterns = { 191 | "[%w._~:/?#@!$&*+-]+%.[%w._~:/?#@!$&*%%+-=]+", 192 | }, 193 | action = wezterm.action_callback(function(win, pane) 194 | local url = win:get_selection_text_for_pane(pane) 195 | wezterm.log_info("Opening " .. url) 196 | wezterm.open_with(url) 197 | end), 198 | }), 199 | }, 200 | 201 | -- Claude Code: Shift-Enter for new line 202 | { key = "Enter", mods = "SHIFT", action = wezterm.action({ SendString = "\x1b\r" }) }, 203 | } 204 | 205 | config.key_tables = { 206 | repeated = { 207 | { key = "h", action = act.AdjustPaneSize({ "Left", 1 }) }, 208 | { key = "j", action = act.AdjustPaneSize({ "Down", 1 }) }, 209 | { key = "k", action = act.AdjustPaneSize({ "Up", 1 }) }, 210 | { key = "l", action = act.AdjustPaneSize({ "Right", 1 }) }, 211 | { key = "Escape", action = act.PopKeyTable }, 212 | 213 | -- increase opacity 214 | { 215 | key = "+", 216 | action = wezterm.action_callback(function(w, p) 217 | local config_overrides = {} 218 | local current_config = w:effective_config() 219 | local current_opacity = current_config.window_background_opacity 220 | if current_opacity <= 0.9 then 221 | config_overrides.window_background_opacity = current_opacity + 0.1 222 | end 223 | w:set_config_overrides(config_overrides) 224 | end), 225 | }, 226 | 227 | -- decrease opacity 228 | { 229 | key = "-", 230 | action = wezterm.action_callback(function(w, p) 231 | local config_overrides = {} 232 | local current_config = w:effective_config() 233 | local current_opacity = current_config.window_background_opacity 234 | if current_opacity >= 0.1 then 235 | config_overrides.window_background_opacity = current_opacity - 0.1 236 | end 237 | w:set_config_overrides(config_overrides) 238 | end), 239 | }, 240 | }, 241 | one_hit = { 242 | -- rename tab 243 | { 244 | key = "r", 245 | action = act.PromptInputLine({ 246 | description = "Enter the tab title:", 247 | action = wezterm.action_callback(function(window, _, line) 248 | if line then 249 | window:active_tab():set_title(line) 250 | end 251 | end), 252 | }), 253 | }, 254 | 255 | -- rename workspace 256 | { 257 | key = "R", 258 | action = act.PromptInputLine({ 259 | description = "Enter new workspace name:", 260 | action = wezterm.action_callback(function(_, _, line) 261 | if line then 262 | wezterm.mux.rename_workspace(wezterm.mux.get_active_workspace(), line) 263 | end 264 | end), 265 | }), 266 | }, 267 | 268 | -- Split the pane horizontally. 269 | -- New pane will be 1/3 of the screen width 270 | { 271 | key = "h", 272 | action = wezterm.action.SplitPane({ 273 | direction = "Left", 274 | size = { Percent = 33 }, 275 | }), 276 | }, 277 | { 278 | key = "l", 279 | action = wezterm.action.SplitPane({ 280 | direction = "Right", 281 | size = { Percent = 33 }, 282 | }), 283 | }, 284 | }, 285 | } 286 | end 287 | 288 | return module 289 | -------------------------------------------------------------------------------- /alfred/prefs.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | customSites 6 | 7 | 1A7A95F5-7FD7-4E63-86E0-271FDE5DF3F0 8 | 9 | enabled 10 | 11 | keyword 12 | pslog 13 | text 14 | Personio STAGE log 15 | url 16 | https://kibana-proxy.stage.personio-internal.de/ 17 | utf8 18 | 19 | 20 | 1E4F763E-5CE5-4FCF-86C3-FFB67B592B9D 21 | 22 | enabled 23 | 24 | keyword 25 | gm1 26 | text 27 | Gmail (Personio) 28 | url 29 | https://mail.google.com/mail/u/1/#inbox 30 | utf8 31 | 32 | 33 | 24F20B3C-C58D-4DD9-B677-82B4B4A784C9 34 | 35 | enabled 36 | 37 | keyword 38 | gm2 39 | text 40 | Gmail (Fram) 41 | url 42 | https://mail.google.com/mail/u/2/#inbox 43 | utf8 44 | 45 | 46 | 2560C157-BA46-46B0-B8EC-35516293390A 47 | 48 | enabled 49 | 50 | keyword 51 | jr 52 | text 53 | Open a Jira CO- task by ID 54 | url 55 | https://personio.atlassian.net/browse/CO-{query} 56 | utf8 57 | 58 | 59 | 4CEF3CBA-7CBB-4F44-AD56-1D27ECC65CCF 60 | 61 | enabled 62 | 63 | keyword 64 | mr 65 | text 66 | Jump to a Merge Request by ID 67 | url 68 | https://gitlab.personio-internal.de/personio/personio/merge_requests/{query} 69 | utf8 70 | 71 | 72 | 51E328BD-7D74-443F-B21F-97B89DA962E3 73 | 74 | enabled 75 | 76 | keyword 77 | psrd 78 | text 79 | Personio STAGE Rundeck 80 | url 81 | https://rundeck.stage.personio-internal.de/ 82 | utf8 83 | 84 | 85 | 55DFA24D-90F9-4021-B48F-8549B2144227 86 | 87 | enabled 88 | 89 | keyword 90 | pplog 91 | text 92 | Personio PROD log 93 | url 94 | https://kibana-proxy.prod.personio-internal.de/ 95 | utf8 96 | 97 | 98 | 55EDDE13-7E07-408D-9FBB-FAA7D09849BA 99 | 100 | enabled 101 | 102 | keyword 103 | od 104 | text 105 | Oxford Dict 106 | url 107 | https://www.oxfordlearnersdictionaries.com/definition/english/{query} 108 | utf8 109 | 110 | 111 | 5BFCD4BC-C607-4127-A716-A781C9653F93 112 | 113 | enabled 114 | 115 | keyword 116 | dor 117 | text 118 | Search my DevOps requests 119 | url 120 | https://personio.atlassian.net/issues/?jql=project%20%3D%20IE%20AND%20creator%20in%20(currentUser())%20AND%20text%20~%20%22{query}%22%20order%20by%20created%20DESC 121 | utf8 122 | 123 | 124 | 6142D37D-975B-4CE1-A599-F2139DCBE3B7 125 | 126 | enabled 127 | 128 | keyword 129 | f33 130 | text 131 | Voz F33 132 | url 133 | https://next.voz.vn/f/33/ 134 | utf8 135 | 136 | 137 | 779A6E71-4C2F-4CE6-8131-3705FA6E9859 138 | 139 | enabled 140 | 141 | keyword 142 | jrla 143 | text 144 | Jira board for Laravel upgrade 145 | url 146 | https://personio.atlassian.net/secure/RapidBoard.jspa?projectKey=LU&rapidView=274 147 | utf8 148 | 149 | 150 | 8B57D838-6651-4BBA-B60E-0599219B373E 151 | 152 | enabled 153 | 154 | keyword 155 | gl 156 | text 157 | GitLab MR created by someone 158 | url 159 | https://gitlab.personio-internal.de/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&author_username={query} 160 | utf8 161 | 162 | 163 | 95839073-F531-44F9-A75A-732E3E357EF8 164 | 165 | enabled 166 | 167 | keyword 168 | dm 169 | text 170 | Demo Payroll panel 171 | url 172 | https://admin.stage.personio-internal.de/companies/payroll 173 | utf8 174 | 175 | 176 | 9DD077C4-1D17-447D-BCD0-7ACC711EBB42 177 | 178 | enabled 179 | 180 | keyword 181 | jrco 182 | text 183 | Jira CO Active sprint 184 | url 185 | https://personio.atlassian.net/secure/RapidBoard.jspa?rapidView=16 186 | utf8 187 | 188 | 189 | A060182D-9522-48A0-B7B4-B6481A22C759 190 | 191 | enabled 192 | 193 | keyword 194 | jrff 195 | text 196 | Jira CO Firefighter board 197 | url 198 | https://personio.atlassian.net/secure/RapidBoard.jspa?rapidView=100 199 | utf8 200 | 201 | 202 | AB3CF8CA-6DE7-4376-86D3-D4D87D349B7E 203 | 204 | enabled 205 | 206 | keyword 207 | pprd 208 | text 209 | Personio PROD Rundeck 210 | url 211 | https://rundeck.prod.personio-internal.de/ 212 | utf8 213 | 214 | 215 | ADB9FAAC-53A8-4608-A041-32BF39C42823 216 | 217 | enabled 218 | 219 | keyword 220 | yt 221 | text 222 | Visit Youtube 223 | url 224 | https://www.youtube.com/ 225 | utf8 226 | 227 | 228 | B8A6F215-AF2A-40F2-BE74-9C595400A6F7 229 | 230 | enabled 231 | 232 | keyword 233 | pw 234 | text 235 | Personio Confluence wiki 236 | url 237 | https://personio.atlassian.net/wiki/search?text={query} 238 | utf8 239 | 240 | 241 | C2BE642C-5C9A-4F90-BD5C-2D7CD59094E0 242 | 243 | enabled 244 | 245 | keyword 246 | glp 247 | text 248 | Personio Gitlab pipeline 249 | url 250 | https://gitlab.personio-internal.de/personio/personio/pipelines 251 | utf8 252 | 253 | 254 | CB26DABF-9B40-49B7-8C5D-759D59BE20A2 255 | 256 | enabled 257 | 258 | keyword 259 | olg 260 | text 261 | OneLogin portal 262 | url 263 | https://personio.onelogin.com/portal/ 264 | utf8 265 | 266 | 267 | D2F61F8C-A0E4-4FA9-A2F2-231E66BC9D86 268 | 269 | enabled 270 | 271 | keyword 272 | psnlc 273 | text 274 | Local Personio Admin panel 275 | url 276 | http://admin.dev.personio.de 277 | utf8 278 | 279 | 280 | E392E75A-DC47-4100-B4BF-DCEC9BBBCAEE 281 | 282 | enabled 283 | 284 | keyword 285 | jrbl 286 | text 287 | Jira CO Backlog 288 | url 289 | https://personio.atlassian.net/secure/RapidBoard.jspa?rapidView=16&view=planning.nodetail 290 | utf8 291 | 292 | 293 | FDBD2584-FD78-4A9F-ABA7-CEB1AE7610A1 294 | 295 | enabled 296 | 297 | keyword 298 | glhp 299 | text 300 | GitLab MR created by Ha Pham 301 | url 302 | https://gitlab.personio-internal.de/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&author_username=Ha.Pham.ext 303 | utf8 304 | 305 | 306 | 307 | onlyShowEnabledInPrefs 308 | 309 | 310 | 311 | -------------------------------------------------------------------------------- /posts/raycast.md: -------------------------------------------------------------------------------- 1 | # How I boost my productivity with [Raycast](https://www.raycast.com/) 2 | Disclaimer: Not only for a software developer 😎 3 | 4 | MacOS gives us Spotlight, a powerful tool to quickly open applications and switch from one app to another. 5 | No longer moving the mouse pointer to choose the app we need... 6 | 7 | It's awesome 🎉. But not enough 😢. We want more things like that. 8 | Because typing the shortcut keys in keyboard is absolutely faster than moving around the screen with mouse or trackpad, 9 | **not only for opening applications on your computer.** 10 | 11 | We have to jump to different Zoom calls every working day, we frequently open some directories storing all things we need for work or entertainment, 12 | we visit a website tens of times everyday, our web browser keeps opening a huge bunch of tabs because we want to quickly view it when we need, **why not make shortcut for it?** 13 | 14 | Let's check out [Raycast](https://www.raycast.com/) (it's free) and I promise you'll never think again. 15 | 16 | ## Goodbye, Spotlight! 17 | If you usually hover your mouse pointer over the long list of application icons pinned on the Dock just to open an application, 18 | you no longer need it. Just hit `Cmd+space` and type some letters before hitting `Return` key to open or jump to your application. 19 | 20 | Wait, is it Spotlight I'm talking about? 21 | Uhmm, perhaps yes, but no. 22 | You can do the same thing with Spotlight, or [Alfred](https://www.alfredapp.com/) (an even better tool 👍), but still no, I'm talking about Raycast 💯. 23 | Just download and install Raycast, and try it. Believe me, it'll work. 24 | 25 | ### But Spotlight keeps showing up when hitting Cmd+Space 🤷‍♂️ 26 | No worry, you can get rid of it in 1 minute. 27 | 28 | First, open Raycast (I truly believe you can open an app on MacOS 👊), you will see Raycast icon in the Menu bar on the right top area of your screen. Keep it there, we'll use it later. 29 | 30 | Open `System preferences > Keyboard` (you can do that in Spotlight by `Cmd+Space` and type `keyboard`), 31 | select `Shorcuts` tab on the top of the pop up, then select `Spotlight` on the left menu. 32 | Finally, uncheck the option `Show Spotlight search` on the right pane. That's it. 33 | 34 | Now, `Cmd+Space` will not bring Spotlight up anymore. Instead, we need it to bring Raycast up. 35 | 36 | Now you can click on the Raycast icon on the menu bar and open `Preferences`. 37 | 38 | image 39 | 40 | In Raycast Preferences window, we can configure a shortcut key for Raycast by clicking on `Raycast Hotkey`, 41 | and type the hotkey that we like, of course, it will be `Cmd+Space`. 42 | 43 | image 44 | 45 | Now you can open Raycast with `Cmd+Space`. So you can uncheck `Show Raycast on menu bar` to remove the Raycast icon on you menu bar, save some space for other stuffs. 46 | 47 | ## OK, what makes Raycast better than Spotlight then? 48 | What makes Raycast so powerful is the huge list of extensions that can satisfy all needs from the users. 49 | To see all extension, just open Raycast with `Cmd+Space` then type `Extensions` and hit `Return`. 50 | Now you can see the Raycast Extension preferences which contains all extensions installed in your Raycast. 51 | If the extension you want to use does not show here, it means you have not installed it yet. 52 | You can install by clicking on the + button on the top right corner and choose `Install From Store` 53 | 54 | image 55 | 56 | Are you ready to explore the power of Raycast? Go!!! 57 | 58 | ## Quickly open websites or files 59 | ### Let's open our website in a blink of an eye 60 | For instance, if you need to visit your JIRA board or roadmap every now and then, you can create a shortcut for it. 61 | 62 | To create a quicklink, let's open Raycast (again, `Cmd+Space`), type `extensions` (or just `ext` would be enough, Raycast is so smart) 63 | and hit `return` to open Raycast Extensions preferences. 64 | 65 | Scroll down to see the `Quicklinks` configuration. You can add or edit your quicklinks there. 66 | 67 | You can also set alias for each quicklink if you like so that you can quickly open it with the alias instead of typing the quicklink name. 68 | For example, to create a quicklink for searching video on YouTube: 69 | - Quicklink name: Search on YouTube 70 | - Link: `https://www.youtube.com/results?search_query={query}` 71 | - Open with: Safari (or your default web browser) 72 | - Alias: `yt` 73 | 74 | image 75 | 76 | Now you can type `ytbeautiful piano` to search for `beautiful piano` on YouTube. 77 | As you can see, `{query}` in the quicklink will be replaced by the keywords you typed after ``. 78 | This approach can be applied for many website with search features, e.g. Google, YouTube, JIRA, etc. 79 | You can test it by searching for something in your web browser and look at the URL of that search result. 80 | 81 | You can create quicklink to do many things: open frequently used websites, Google search, search for JIRA ticket or Confluence page, 82 | search files/directories on your Google drive, etc. 💯 83 | 84 | ### Opening frequently used files/directories 85 | 86 | With quicklinks, you can also quickly open your files with the same way as for your websites. 87 | 88 | Just replace the `link` with the full path to your file/directory and choose the application to open that file via `Open with` option. 89 | 90 | For example, the below quicklink helps me quickly open Downloads directory when typing `dwn` in Raycast 91 | - Quicklink name: Open Downloads 92 | - Link: `~/Downloads` 93 | - Open with: Finder 94 | - Alias: `dwn` 95 | 96 | image 97 | 98 | 99 | ## Pasting items from clipboard history 100 | Every computer user needs clipboard to copy or move something to somewhere. But the clipboard only stores the last thing that we copy. That's paintful. 😭 101 | 102 | Raycast can help you to manage hundreds of items in clipboard and you can quickly search for it before pasting. 103 | For example, I am sure that I copied the text `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua` yesterday, 104 | now you want to paste it to your Google slide. I can simply press `Cmd+Shift+V` then type `lorem` and hit `Return` to paste it. 105 | 106 | To enable clipboard manager in your Raycast, make sure **Clipboard History** extension is installed via Raycast store. 107 | Don't forget to set the hotkey for your Clipboard History extension to quickly access it, `Cmd+Shift+V` would be a nice choice. 108 | 109 | ## Quickly search for emoji, like this 😉 110 | If you are a fan of emoji 👍, you will like the `Search Emoji` extension. 111 | 112 | ## Quickily search for earch gif 113 | `Search for GIFs` would be a nice extension to search for the funny animated images. 114 | This extension helps you quickly copy the URL of the funny gifs and then paste it to your chat. 115 | 116 | ## Moving and resizing windows is now so simple 117 | If you usually place your application windows side by side 118 | or split your screen into multiple smaller areas where you can view multiple applications, Raycast would be a big help for you. 119 | 120 | image 121 | 122 | `Window Management` extension supports a lot of nice features: moving window to next display, 123 | resizing your window (right half, left half, bottom half, up-right quarter, maximizing, etc.). 124 | With some hotkeys configured, now you can move your windows around the screen like magic. 125 | 126 | ## Jumping to your online meeting within 1 second 127 | This is one of the most interesting feature that Raycast can bring to me. 128 | With **Calendar** extension, you can quickly view your schedules in your calendar. 129 | 130 | image 131 | 132 | Especially, if your schedule contains Zoom or Google Meet link, 5 minutes before and after the meeting starts, 133 | just open Raycast and you can see the meeting will show up right away on top, just hit enter to join the call. 134 | 135 | # Quick switching audio device 🔈 136 | If you have multiple input and/or output audio devices connected with your Mac, `Set Audio Device` will be a good choice for you. It supports quickly choosing the input/output device. For example: choosing the hi-end stereo for listening music and quickly switching to your headset for a call. Awesome!!! 137 | 138 | # Quick switching bluetooth connection 📶 139 | Connection to your bluetooth devices can be easily managed with `Toothpick` extension. 140 | 141 | # Enjoy it! 142 | So far, I have shown you a bunch of features that Raycast can boost your productivity. 143 | I enjoyed it a lot, hopefully it can do the same for your life. 144 | 145 | There are still more extensions in the store for us to discover: searching web browser bookmarks, calculator, translation, etc. 146 | If you find out any other nice extension, please share it with me. 147 | 148 | Have a nice day! 149 | 150 | -------------------------------------------------------------------------------- /nvim/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /fish/functions/fisher.fish: -------------------------------------------------------------------------------- 1 | function fisher --argument-names cmd --description "A plugin manager for Fish" 2 | set --query fisher_path || set --local fisher_path $__fish_config_dir 3 | set --local fisher_version 4.4.3 4 | set --local fish_plugins $__fish_config_dir/fish_plugins 5 | 6 | switch "$cmd" 7 | case -v --version 8 | echo "fisher, version $fisher_version" 9 | case "" -h --help 10 | echo "Usage: fisher install Install plugins" 11 | echo " fisher remove Remove installed plugins" 12 | echo " fisher update Update installed plugins" 13 | echo " fisher update Update all installed plugins" 14 | echo " fisher list [] List installed plugins matching regex" 15 | echo "Options:" 16 | echo " -v, --version Print version" 17 | echo " -h, --help Print this help message" 18 | echo "Variables:" 19 | echo " \$fisher_path Plugin installation path. Default: $__fish_config_dir" | string replace --regex -- $HOME \~ 20 | case ls list 21 | string match --entire --regex -- "$argv[2]" $_fisher_plugins 22 | case install update remove 23 | isatty || read --local --null --array stdin && set --append argv $stdin 24 | 25 | set --local install_plugins 26 | set --local update_plugins 27 | set --local remove_plugins 28 | set --local arg_plugins $argv[2..-1] 29 | set --local old_plugins $_fisher_plugins 30 | set --local new_plugins 31 | 32 | test -e $fish_plugins && set --local file_plugins (string match --regex -- '^[^\s]+$' <$fish_plugins) 33 | 34 | if ! set --query argv[2] 35 | if test "$cmd" != update 36 | echo "fisher: Not enough arguments for command: \"$cmd\"" >&2 && return 1 37 | else if ! set --query file_plugins 38 | echo "fisher: \"$fish_plugins\" file not found: \"$cmd\"" >&2 && return 1 39 | end 40 | set arg_plugins $file_plugins 41 | end 42 | 43 | for plugin in $arg_plugins 44 | set plugin (test -e "$plugin" && realpath $plugin || string lower -- $plugin) 45 | contains -- "$plugin" $new_plugins || set --append new_plugins $plugin 46 | end 47 | 48 | if set --query argv[2] 49 | for plugin in $new_plugins 50 | if contains -- "$plugin" $old_plugins 51 | test "$cmd" = remove && 52 | set --append remove_plugins $plugin || 53 | set --append update_plugins $plugin 54 | else if test "$cmd" = install 55 | set --append install_plugins $plugin 56 | else 57 | echo "fisher: Plugin not installed: \"$plugin\"" >&2 && return 1 58 | end 59 | end 60 | else 61 | for plugin in $new_plugins 62 | contains -- "$plugin" $old_plugins && 63 | set --append update_plugins $plugin || 64 | set --append install_plugins $plugin 65 | end 66 | 67 | for plugin in $old_plugins 68 | contains -- "$plugin" $new_plugins || set --append remove_plugins $plugin 69 | end 70 | end 71 | 72 | set --local pid_list 73 | set --local source_plugins 74 | set --local fetch_plugins $update_plugins $install_plugins 75 | set --local fish_path (status fish-path) 76 | 77 | echo (set_color --bold)fisher $cmd version $fisher_version(set_color normal) 78 | 79 | for plugin in $fetch_plugins 80 | set --local source (command mktemp -d) 81 | set --append source_plugins $source 82 | 83 | command mkdir -p $source/{completions,conf.d,themes,functions} 84 | 85 | $fish_path --command " 86 | if test -e $plugin 87 | command cp -Rf $plugin/* $source 88 | else 89 | set temp (command mktemp -d) 90 | set repo (string split -- \@ $plugin) || set repo[2] HEAD 91 | 92 | if set path (string replace --regex -- '^(https://)?gitlab.com/' '' \$repo[1]) 93 | set name (string split -- / \$path)[-1] 94 | set url https://gitlab.com/\$path/-/archive/\$repo[2]/\$name-\$repo[2].tar.gz 95 | else 96 | set url https://api.github.com/repos/\$repo[1]/tarball/\$repo[2] 97 | end 98 | 99 | echo Fetching (set_color --underline)\$url(set_color normal) 100 | 101 | if curl --silent -L \$url | tar -xzC \$temp -f - 2>/dev/null 102 | command cp -Rf \$temp/*/* $source 103 | else 104 | echo fisher: Invalid plugin name or host unavailable: \\\"$plugin\\\" >&2 105 | command rm -rf $source 106 | end 107 | 108 | command rm -rf \$temp 109 | end 110 | 111 | set files $source/* && string match --quiet --regex -- .+\.fish\\\$ \$files 112 | " & 113 | 114 | set --append pid_list (jobs --last --pid) 115 | end 116 | 117 | wait $pid_list 2>/dev/null 118 | 119 | for plugin in $fetch_plugins 120 | if set --local source $source_plugins[(contains --index -- "$plugin" $fetch_plugins)] && test ! -e $source 121 | if set --local index (contains --index -- "$plugin" $install_plugins) 122 | set --erase install_plugins[$index] 123 | else 124 | set --erase update_plugins[(contains --index -- "$plugin" $update_plugins)] 125 | end 126 | end 127 | end 128 | 129 | for plugin in $update_plugins $remove_plugins 130 | if set --local index (contains --index -- "$plugin" $_fisher_plugins) 131 | set --local plugin_files_var _fisher_(string escape --style=var -- $plugin)_files 132 | 133 | if contains -- "$plugin" $remove_plugins 134 | for name in (string replace --filter --regex -- '.+/conf\.d/([^/]+)\.fish$' '$1' $$plugin_files_var) 135 | emit {$name}_uninstall 136 | end 137 | printf "%s\n" Removing\ (set_color red --bold)$plugin(set_color normal) " "$$plugin_files_var | string replace -- \~ ~ 138 | set --erase _fisher_plugins[$index] 139 | end 140 | 141 | command rm -rf (string replace -- \~ ~ $$plugin_files_var) 142 | 143 | functions --erase (string replace --filter --regex -- '.+/functions/([^/]+)\.fish$' '$1' $$plugin_files_var) 144 | 145 | for name in (string replace --filter --regex -- '.+/completions/([^/]+)\.fish$' '$1' $$plugin_files_var) 146 | complete --erase --command $name 147 | end 148 | 149 | set --erase $plugin_files_var 150 | end 151 | end 152 | 153 | if set --query update_plugins[1] || set --query install_plugins[1] 154 | command mkdir -p $fisher_path/{functions,themes,conf.d,completions} 155 | end 156 | 157 | for plugin in $update_plugins $install_plugins 158 | set --local source $source_plugins[(contains --index -- "$plugin" $fetch_plugins)] 159 | set --local files $source/{functions,themes,conf.d,completions}/* 160 | 161 | if set --local index (contains --index -- $plugin $install_plugins) 162 | set --local user_files $fisher_path/{functions,themes,conf.d,completions}/* 163 | set --local conflict_files 164 | 165 | for file in (string replace -- $source/ $fisher_path/ $files) 166 | contains -- $file $user_files && set --append conflict_files $file 167 | end 168 | 169 | if set --query conflict_files[1] && set --erase install_plugins[$index] 170 | echo -s "fisher: Cannot install \"$plugin\": please remove or move conflicting files first:" \n" "$conflict_files >&2 171 | continue 172 | end 173 | end 174 | 175 | for file in (string replace -- $source/ "" $files) 176 | command cp -RLf $source/$file $fisher_path/$file 177 | end 178 | 179 | set --local plugin_files_var _fisher_(string escape --style=var -- $plugin)_files 180 | 181 | set --query files[1] && set --universal $plugin_files_var (string replace -- $source $fisher_path $files | string replace -- ~ \~) 182 | 183 | contains -- $plugin $_fisher_plugins || set --universal --append _fisher_plugins $plugin 184 | contains -- $plugin $install_plugins && set --local event install || set --local event update 185 | 186 | printf "%s\n" Installing\ (set_color --bold)$plugin(set_color normal) " "$$plugin_files_var | string replace -- \~ ~ 187 | 188 | for file in (string match --regex -- '.+/[^/]+\.fish$' $$plugin_files_var | string replace -- \~ ~) 189 | source $file 190 | if set --local name (string replace --regex -- '.+conf\.d/([^/]+)\.fish$' '$1' $file) 191 | emit {$name}_$event 192 | end 193 | end 194 | end 195 | 196 | command rm -rf $source_plugins 197 | 198 | if set --query _fisher_plugins[1] 199 | set --local commit_plugins 200 | 201 | for plugin in $file_plugins 202 | contains -- (string lower -- $plugin) (string lower -- $_fisher_plugins) && set --append commit_plugins $plugin 203 | end 204 | 205 | for plugin in $_fisher_plugins 206 | contains -- (string lower -- $plugin) (string lower -- $commit_plugins) || set --append commit_plugins $plugin 207 | end 208 | 209 | printf "%s\n" $commit_plugins >$fish_plugins 210 | else 211 | set --erase _fisher_plugins 212 | command rm -f $fish_plugins 213 | end 214 | 215 | set --local total (count $install_plugins) (count $update_plugins) (count $remove_plugins) 216 | 217 | test "$total" != "0 0 0" && echo (string join ", " ( 218 | test $total[1] = 0 || echo "Installed $total[1]") ( 219 | test $total[2] = 0 || echo "Updated $total[2]") ( 220 | test $total[3] = 0 || echo "Removed $total[3]") 221 | ) plugin/s 222 | case \* 223 | echo "fisher: Unknown command: \"$cmd\"" >&2 && return 1 224 | end 225 | end 226 | 227 | if ! set --query _fisher_upgraded_to_4_4 228 | set --universal _fisher_upgraded_to_4_4 229 | if functions --query _fisher_list 230 | set --query XDG_DATA_HOME[1] || set --local XDG_DATA_HOME ~/.local/share 231 | command rm -rf $XDG_DATA_HOME/fisher 232 | functions --erase _fisher_{list,plugin_parse} 233 | fisher update >/dev/null 2>/dev/null 234 | else 235 | for var in (set --names | string match --entire --regex '^_fisher_.+_files$') 236 | set $var (string replace -- ~ \~ $$var) 237 | end 238 | functions --erase _fisher_fish_postexec 239 | end 240 | end 241 | --------------------------------------------------------------------------------