├── .config ├── git │ ├── ignore │ └── config ├── karabiner │ ├── .gitignore │ └── karabiner.json ├── nvim │ ├── after │ │ └── ftplugin │ │ │ ├── javascript.lua │ │ │ ├── gosum.lua │ │ │ ├── hcl.lua │ │ │ ├── gomod.lua │ │ │ ├── json.lua │ │ │ ├── help.lua │ │ │ ├── scss.lua │ │ │ ├── sh.lua │ │ │ ├── dockerfile.lua │ │ │ ├── lua.lua │ │ │ ├── query.lua │ │ │ ├── terraform.lua │ │ │ ├── yaml.lua │ │ │ ├── markdown.lua │ │ │ ├── typescript.lua │ │ │ ├── go.lua │ │ │ └── python.lua │ ├── lua │ │ ├── plugins │ │ │ ├── devicons.lua │ │ │ ├── surround.lua │ │ │ ├── gitsigns.lua │ │ │ ├── floatterm.lua │ │ │ ├── neoscroll.lua │ │ │ ├── autosave.lua │ │ │ ├── colorschemes.lua │ │ │ ├── fzf.lua │ │ │ ├── zen.lua │ │ │ ├── treesitter.lua │ │ │ ├── filetree.lua │ │ │ ├── mason.lua │ │ │ ├── lualine.lua │ │ │ ├── conform.lua │ │ │ ├── blink.lua │ │ │ └── lspconfig.lua │ │ ├── autocmds.lua │ │ ├── options.lua │ │ ├── keymaps.lua │ │ ├── utils.lua │ │ └── extras.lua │ ├── lsp │ │ ├── typescript-language-server.lua │ │ ├── gopls.lua │ │ └── lua_ls.lua │ ├── lazy-lock.json │ ├── init.lua │ └── snippets │ │ └── go.json ├── alacritty │ └── alacritty.toml └── wezterm │ └── wezterm.lua ├── .sqliterc ├── .bash_profile ├── .Xmodmap ├── scripts ├── aws │ ├── s3put │ └── get-aws-token ├── shell │ ├── port │ ├── snippet-selector │ ├── pretty-grep.awk │ ├── epoch │ ├── xfi │ ├── sys │ ├── colors │ └── surf ├── media │ ├── blobget │ └── gif ├── git │ ├── git-worktree-switch │ ├── git-switch │ ├── git-add │ ├── git-search │ ├── git-commit │ ├── git-diff │ ├── git-stash-checkout │ ├── git-feed │ ├── git-prs │ └── git-worktree-all ├── bds ├── bcs ├── file │ ├── pj │ ├── hide │ ├── md │ ├── oib │ └── pdftrim └── github │ ├── myprs │ ├── contributors │ ├── gists │ └── bkp ├── .gitmessage ├── .inputrc ├── .vim_bash_env ├── .vale.ini ├── scd-completions.bash ├── snippets ├── markdown.snippets ├── python.snippets ├── sh.snippets └── go.snippets ├── .bash_aliases ├── .zshrc ├── .nanorc ├── README.md ├── .bashrc ├── .bash_functions └── .tmux.conf.local /.config/git/ignore: -------------------------------------------------------------------------------- 1 | tags 2 | *.DS_Store -------------------------------------------------------------------------------- /.sqliterc: -------------------------------------------------------------------------------- 1 | .header on 2 | .timer on 3 | .mode column -------------------------------------------------------------------------------- /.config/karabiner/.gitignore: -------------------------------------------------------------------------------- 1 | assets 2 | automatic_backups 3 | -------------------------------------------------------------------------------- /.bash_profile: -------------------------------------------------------------------------------- 1 | if [ -f ~/.bashrc ]; then 2 | source ~/.bashrc 3 | fi -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/javascript.lua: -------------------------------------------------------------------------------- 1 | vim.treesitter.start() 2 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/gosum.lua: -------------------------------------------------------------------------------- 1 | -- Start the Treesitter parser for "go.sum" files 2 | vim.treesitter.start() 3 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/hcl.lua: -------------------------------------------------------------------------------- 1 | -- Start the Treesitter parsing process for HCL files 2 | vim.treesitter.start() 3 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/gomod.lua: -------------------------------------------------------------------------------- 1 | -- Start the Treesitter parsing process for "go.mod" files 2 | vim.treesitter.start() 3 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/devicons.lua: -------------------------------------------------------------------------------- 1 | -- Module for adding devicon support to Neovim 2 | 3 | return { 4 | "nvim-tree/nvim-web-devicons", 5 | } 6 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/surround.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "tpope/vim-surround", 3 | event = "VeryLazy" -- or remove if you want it to load immediately 4 | } 5 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/json.lua: -------------------------------------------------------------------------------- 1 | -- Start the Treesitter parsing process 2 | vim.treesitter.start() 3 | 4 | -- Start the "jsonls" LSP server 5 | vim.lsp.enable("jsonls", true) 6 | -------------------------------------------------------------------------------- /.Xmodmap: -------------------------------------------------------------------------------- 1 | ! 66 is the keycode of Caps_Lock 2 | ! https://superuser.com/questions/566871/how-to-map-the-caps-lock-key-to-escape-key-in-arch-linux 3 | 4 | clear Lock 5 | keycode 66 = Escape 6 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/help.lua: -------------------------------------------------------------------------------- 1 | -- Settings to apply specifically to "vimdoc" files/buffers 2 | 3 | vim.b.miniindentscope_disable = true -- This is necessary to disable indent lines on help files 4 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/scss.lua: -------------------------------------------------------------------------------- 1 | -- Start the Treesitter parsing process for SASS files 2 | vim.treesitter.start() 3 | 4 | -- Start the LSP server for the SASS files 5 | vim.lsp.enable("cssls", true) 6 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/sh.lua: -------------------------------------------------------------------------------- 1 | -- Start the Treesitter parser for Shell files 2 | vim.treesitter.start() 3 | 4 | -- Start the "bashls" LSP server for Bash scripting 5 | vim.lsp.enable("bashls", true) 6 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/gitsigns.lua: -------------------------------------------------------------------------------- 1 | -- Module for configuring the "gitsigns" plugin for Git VCS capabilities 2 | 3 | return { 4 | "lewis6991/gitsigns.nvim", 5 | event = "BufReadPost", 6 | config = true, 7 | } -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/dockerfile.lua: -------------------------------------------------------------------------------- 1 | -- Start the Treesitter parsing process for Dockerfile 2 | vim.treesitter.start() 3 | 4 | -- Enable the "dockerls" LSP server for Dockerfile 5 | vim.lsp.enable("dockerls", true) 6 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/lua.lua: -------------------------------------------------------------------------------- 1 | -- Module for configuring Lua specific buffer 2 | 3 | -- Start the Treesitter parser process 4 | vim.treesitter.start() 5 | -- Enable and configure the LSP server 6 | vim.lsp.enable("lua_ls", true) 7 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/query.lua: -------------------------------------------------------------------------------- 1 | -- Filetype plugin configurations for the "query" filetype 2 | 3 | -- Disable the redundant number column on the right side for "query" files 4 | vim.wo.number = false 5 | vim.wo.relativenumber = false 6 | -------------------------------------------------------------------------------- /scripts/aws/s3put: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | 4 | read -e -p "Enter File Path: " -r IMAGE_PATH 5 | 6 | read -p "Enter S3 Pre-Sign URL: " -r S3_URL 7 | 8 | 9 | if curl -X PUT -T "$IMAGE_PATH" -L "$S3_URL"; then 10 | echo "Done" 11 | fi 12 | -------------------------------------------------------------------------------- /.config/alacritty/alacritty.toml: -------------------------------------------------------------------------------- 1 | [window] 2 | decorations = "Buttonless" 3 | opacity=0.8 4 | blur=true 5 | startup_mode="Maximized" 6 | dynamic_padding=false 7 | 8 | [font] 9 | normal = { family = "FiraCode Nerd Font", style = "Medium" } 10 | size=22 11 | 12 | 13 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/terraform.lua: -------------------------------------------------------------------------------- 1 | -- Set the correct comment string format for Terraform files 2 | vim.opt.commentstring = "// %s" 3 | 4 | -- Start the Treesitter parsing process 5 | vim.treesitter.start() 6 | 7 | -- Start the "terraform-ls" LSP server 8 | vim.lsp.enable("terraformls", true) 9 | -------------------------------------------------------------------------------- /.gitmessage: -------------------------------------------------------------------------------- 1 | # If applied, this commit will... 2 | # [Add/Fix/Remove/Update/Refactor/Document] [issue #id] [summary] 3 | 4 | 5 | # Why is it necessary? (Bug fix, feature, improvements?) 6 | - 7 | # How does the change address the issue? 8 | - 9 | # What side effects does this change have? 10 | - -------------------------------------------------------------------------------- /scripts/shell/port: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Check if port is already in use 4 | 5 | if [ $# -eq 0 ]; then 6 | sudo lsof -iTCP -sTCP:LISTEN -n -P 7 | elif [ $# -eq 1 ]; then 8 | sudo lsof -iTCP -sTCP:LISTEN -n -P | grep -i --color $1 9 | else 10 | echo "Usage: port [PORT]" 11 | fi 12 | -------------------------------------------------------------------------------- /scripts/media/blobget: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | 4 | read -p "Enter Video Blob URL: " -r BLOB_URL 5 | 6 | read -p "Enter New File name: " -r NEW_FILE 7 | 8 | NEW_FILE=${NEW_FILE:-'output'} 9 | 10 | ffmpeg -hide_banner -loglevel error -stats -i "$BLOB_URL" -c copy -bsf:a aac_adtstoasc "$NEW_FILE.mp4" 11 | 12 | -------------------------------------------------------------------------------- /scripts/git/git-worktree-switch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # FZF Wrapper over git to interactively switch git worktrees 4 | 5 | worktree=$( 6 | git worktree list | fzf \ 7 | --prompt="Switch Worktree: " \ 8 | --height 40% --reverse | 9 | awk '{print $1}' 10 | ) 11 | 12 | cd "$worktree" || return 13 | -------------------------------------------------------------------------------- /scripts/bds: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # Script to connect to bluetooth devices 4 | 5 | 6 | device=$(bluetoothctl paired-devices | fzf \ 7 | --prompt="Choose Device: " \ 8 | --height 40% --reverse --multi \ 9 | --header="Choose a device to connect to" 10 | ) 11 | 12 | bluetoothctl connect $(echo $device | awk '{print $2}') 13 | -------------------------------------------------------------------------------- /.inputrc: -------------------------------------------------------------------------------- 1 | set show-all-if-ambiguous on 2 | set completion-ignore-case on 3 | set completion-map-case on 4 | set show-all-if-unmodified on 5 | set menu-complete-display-prefix on 6 | set colored-stats on 7 | set colored-completion-prefix on 8 | set menu-complete-display-prefix on 9 | set print-completions-horizontally on 10 | "\t": menu-complete 11 | -------------------------------------------------------------------------------- /scripts/git/git-switch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # FZF + Git interactively switch branches 4 | 5 | choice=$( 6 | git for-each-ref --format='%(refname:short)' | fzf \ 7 | --prompt="Switch Branch: " \ 8 | --height 40% --reverse 9 | ) 10 | 11 | if [ -n "$choice" ]; then 12 | git switch $choice 13 | fi 14 | -------------------------------------------------------------------------------- /.vim_bash_env: -------------------------------------------------------------------------------- 1 | shopt -s expand_aliases 2 | source ~/.bash_aliases 3 | source ~/.bash_functions 4 | 5 | if ! shopt -oq posix; then 6 | if [ -f /usr/share/bash-completion/bash_completion ]; then 7 | . /usr/share/bash-completion/bash_completion 8 | elif [ -f /etc/bash_completion ]; then 9 | . /etc/bash_completion 10 | fi 11 | fi 12 | -------------------------------------------------------------------------------- /.vale.ini: -------------------------------------------------------------------------------- 1 | # This goes in a file named either `.vale.ini` or `_vale.ini`. 2 | StylesPath = styles 3 | MinAlertLevel = suggestion 4 | 5 | # External packages 6 | Packages = Google, Readability, alex, proselint, IBM 7 | # Only Markdown and .txt files; change to whatever you're using. 8 | [*.{md,txt}] 9 | # List of styles to load. 10 | BasedOnStyles = alex, proselint 11 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/yaml.lua: -------------------------------------------------------------------------------- 1 | -- Start the Treesitter parsing logic 2 | vim.treesitter.start() 3 | 4 | -- INFO: Only open "massive" buffers with folds enabled 5 | if vim.api.nvim_buf_line_count(0) >= 100 then 6 | vim.opt.foldmethod = "indent" 7 | vim.opt.foldlevel = 1 8 | vim.opt.foldenable = true 9 | end 10 | 11 | -- Start the "yamlls" LSP server 12 | vim.lsp.enable("yamlls", true) 13 | -------------------------------------------------------------------------------- /scripts/git/git-add: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # FZF Wrapper over git to interactively stage files 4 | 5 | readarray -t choices < <( 6 | git ls-files --other --modified --exclude-standard | fzf \ 7 | --prompt="Stage Files: " \ 8 | --height 40% --reverse --multi \ 9 | --header="Files (TAB to select multiple)" 10 | ) 11 | 12 | git add "${choices[@]}" 13 | -------------------------------------------------------------------------------- /scripts/bcs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # FZF Wrapper to connect to devices using bluetoothctl 4 | 5 | # TODO: check if bluetooh service is running if not, start it 6 | # TODO: retry mechanism if connection fails 7 | 8 | choice=$(bluetoothctl devices | fzf \ 9 | --prompt="Choose Device: " \ 10 | --height 40% --reverse --multi) 11 | 12 | device=$(echo $choice | awk '{print $2}') 13 | 14 | bluetoothctl connect "$device" 15 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/floatterm.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "voldikss/vim-floaterm", 3 | cmd = {"FloatermToggle", "FloatermNew", "FloatermShow", "FloatermHide"}, 4 | config = function() 5 | -- hi FloatermBorder cterm=bold gui=bold guibg=NONE guifg=orange 6 | vim.api.nvim_set_hl(0, "FloatermBorder", { 7 | bold = true, 8 | bg = "NONE", 9 | fg = "orange" 10 | }) 11 | end 12 | } -------------------------------------------------------------------------------- /.config/nvim/lsp/typescript-language-server.lua: -------------------------------------------------------------------------------- 1 | return { 2 | cmd = { "typescript-language-server", "--stdio" }, 3 | filetypes = { 4 | "typescript", 5 | "javascript", 6 | }, 7 | root_markers = { "package.json" }, 8 | capabilities = (function() 9 | local capabilities = vim.lsp.protocol.make_client_capabilities() 10 | capabilities.textDocument.completion.completionItem.snippetSupport = true 11 | return capabilities 12 | end)(), 13 | } 14 | -------------------------------------------------------------------------------- /scripts/shell/snippet-selector: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Use rofi to use text snippets 4 | 5 | # sudo apt install -y rofi xdotool xclip 6 | 7 | SNIPPET_FILE="$HOME/Documents/.Varshney/snippets/links.txt" 8 | selection=$(rofi -i -width 1000 -dmenu -p "Choose Snippet: " 2> /dev/null $@ < "$SNIPPET_FILE") 9 | echo -n "$selection" | xclip -selection c 10 | # xclip -o 11 | current_wid=$(xdo id) 12 | xdotool key --window "$current_wid" --clearmodifiers ctrl+v 13 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/markdown.lua: -------------------------------------------------------------------------------- 1 | -- Filetype plugin which applies settings only for Markdown files 2 | 3 | vim.opt.wrap = true -- Wrap lines instead of continuing on beyond the limits of the monitor 4 | vim.opt.linebreak = true -- Wrap the lines at the end of a word instead of the last character of a line 5 | 6 | -- Enable the "vale-ls" LSP server for Markdown files 7 | vim.lsp.enable("vale-ls", true) 8 | 9 | -- Start the Treesitter parsing process 10 | vim.treesitter.start() 11 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/neoscroll.lua: -------------------------------------------------------------------------------- 1 | -- Module for configuring the plugin for smooth scrolling 2 | -- https://github.com/karb94/neoscroll.nvim 3 | 4 | return { 5 | "karb94/neoscroll.nvim", 6 | event = { "BufRead", "BufNewFile" }, 7 | opts = { 8 | respect_scrolloff = true, 9 | cursor_scrolls_alone = false, 10 | easing = "quadratic", -- default: linear 11 | -- linear, quadratic, cubic, quartic, quintic, circular, sine 12 | }, 13 | config = function(_, opts) 14 | require("neoscroll").setup(opts) 15 | end, 16 | } 17 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/autosave.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "Pocco81/auto-save.nvim", 3 | lazy = false, 4 | opts = { 5 | execution_message = { 6 | message = function() -- message to print on save 7 | return ("AutoSaved at " .. vim.fn.strftime("%H:%M:%S")) 8 | end, 9 | dim = 0.18, -- dim the color of `message` 10 | cleaning_interval = 1250 -- (milliseconds) automatically clean MsgArea after displaying `message`. See :h MsgArea 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/typescript.lua: -------------------------------------------------------------------------------- 1 | -- Start the Treesitter parsing process for TypeScript files 2 | vim.treesitter.start() 3 | vim.lsp.enable("typescript-language-server", true) 4 | 5 | -- Folding configurations for Neovim 6 | if vim.api.nvim_buf_line_count(0) >= 100 then 7 | vim.o.foldmethod = "expr" -- Allow folding using the "nvim-treesitter" plugin 8 | vim.o.foldexpr = "nvim_treesitter#foldexpr()" -- Configure the folding algorithm to be from the plugin 9 | vim.o.foldlevel = 1 -- Configure the maximum indenting for the folding 10 | end 11 | -------------------------------------------------------------------------------- /scripts/git/git-search: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # FZF Wrapper over git to interactively search code changes inside functions 4 | 5 | readarray -t choices < <(git ls-files | fzf \ 6 | --prompt="Choose File: " \ 7 | --height 40% --reverse \ 8 | ) 9 | 10 | printf "%s\n" "$(grep -o -P '(?<=def ).*?(?=\()' $choices)" | fzf \ 11 | --ansi --preview "echo {} | xargs -I{} git log --color -L :{}:$choices" \ 12 | --prompt="Choose function/method: " \ 13 | --bind 'j:down,k:up,ctrl-j:preview-down,ctrl-k:preview-up,ctrl-space:toggle-preview' --preview-window right:60% \ 14 | -------------------------------------------------------------------------------- /scripts/git/git-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | gitmoji_path="$HOME/.config/gitmojis.csv" 4 | 5 | emoji=$(cat $gitmoji_path | fzf --prompt="Choose gitmoji: " --height 40% --reverse | awk '{print $1}') 6 | printf "Emoji: %s\n" "$emoji" 7 | 8 | read -erp "Enter Commit Title: " title 9 | echo -e "Enter Commit Message (Ctrl+d when done):" 10 | msg=$( "$json_file_path" 14 | done 15 | else 16 | pretty_json=$(python3 -m json.tool "$1") && echo "$pretty_json" > "$1" 17 | fi 18 | } 19 | 20 | __pj "$@" 21 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/go.lua: -------------------------------------------------------------------------------- 1 | -- Module for configuring Go 2 | 3 | -- Start the Treesitter parsing process 4 | vim.treesitter.start() 5 | -- Start the "gopls" LSP server 6 | vim.lsp.enable("gopls", true) 7 | 8 | -- Configure the indent-based folds for Go buffers 9 | if vim.api.nvim_buf_line_count(0) >= 100 then 10 | vim.opt.foldmethod = "expr" 11 | vim.opt.foldexpr = "nvim_treesitter#foldexpr()" 12 | vim.opt.foldlevel = 0 -- Start with folds closed 13 | vim.opt.foldcolumn = "auto" -- Show fold indicators on the left margin 14 | vim.opt.foldnestmax = 99 -- Maximum depth of folds 15 | end 16 | -------------------------------------------------------------------------------- /scripts/shell/pretty-grep.awk: -------------------------------------------------------------------------------- 1 | # Utility to print grep searches in a human friendly way 2 | 3 | # Credits: https://www.endpoint.com/blog/2017/01/18/using-awk-to-beautify-grep-searches 4 | 5 | BEGIN { 6 | FS=":" 7 | file="" 8 | filestarted=0 9 | GREEN_FG="\033[1;38;5;154m" 10 | RESET="\033[m" 11 | } 12 | 13 | # $0 : the entire line 14 | # $1 : filepath 15 | # $2 : line number 16 | # $3 : the rest of the line 17 | 18 | { 19 | if($1 != file && $1 != ""){ 20 | file=$1 21 | print "\n" $1 ":" 22 | filestarted=0; 23 | } 24 | if(filestarted != 0){ 25 | print GREEN_FG "|" RESET 26 | } 27 | out=substr($0, length($1 ":" $2 ": ")) 28 | print $2 " " out 29 | filestarted=1; 30 | } 31 | -------------------------------------------------------------------------------- /scripts/file/hide: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Script to hide sensitive data from a command 4 | # This script assume everything inside double quotes is sensitive 5 | 6 | # TODO: add help & about option 7 | 8 | from sys import stdin 9 | from os import isatty 10 | import re 11 | 12 | quotes_regex = re.compile('"(.*?)"') 13 | 14 | def hide_secrets(data: str): 15 | sensitive_data = re.findall(quotes_regex, data) 16 | 17 | for secret in sensitive_data: 18 | data = data.replace(secret, "*" * len(secret)) 19 | print(data) 20 | 21 | 22 | if __name__ == "__main__": 23 | is_pipe = not isatty(stdin.fileno()) 24 | 25 | if is_pipe: 26 | query = stdin.read() 27 | hide_secrets(query) -------------------------------------------------------------------------------- /scd-completions.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | _scd_completions(){ 4 | local cur=${COMP_WORDS[COMP_CWORD]} 5 | local IFS=$'\n' 6 | # handle space separated dir names 7 | dqc='"' 8 | while read -r file_path; do 9 | [[ -d $file_path ]] && search_results+=( "$dqc$file_path$dqc" ) 10 | done < <( locate -er "/$cur$" ) 11 | if [[ ${#search_results} == 0 ]]; then 12 | while read -r file_path; do 13 | [[ -d $file_path ]] && search_results+=( "$dqc$file_path$dqc" ) 14 | # do loose search 15 | done < <( locate -ebr "$cur" ) 16 | fi 17 | 18 | COMPREPLY=("${search_results[@]}") 19 | unset search_results 20 | } 21 | 22 | complete -F _scd_completions scd 23 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/colorschemes.lua: -------------------------------------------------------------------------------- 1 | return {{ 2 | "Shatur/neovim-ayu", 3 | priority = 1000, 4 | lazy = false, -- Load immediately 5 | config = function() 6 | require("ayu").setup({ 7 | mirage = true 8 | }) 9 | end 10 | }, { 11 | "sainnhe/sonokai", 12 | priority = 1000, 13 | lazy = false 14 | 15 | }, { 16 | "franbach/miramare", 17 | priority = 1000, 18 | lazy = false 19 | }, { 20 | "NLKNguyen/papercolor-theme", 21 | priority = 1000, 22 | lazy = false 23 | }, { 24 | "drewtempelmeyer/palenight.vim", 25 | priority = 1000, 26 | lazy = false 27 | }, { 28 | "lifepillar/vim-gruvbox8", 29 | priority = 1000, 30 | lazy = false 31 | }} 32 | -------------------------------------------------------------------------------- /snippets/markdown.snippets: -------------------------------------------------------------------------------- 1 | extends all 2 | 3 | snippet head "Jekyll Post Header" b 4 | --- 5 | layout: post 6 | comments: true 7 | title: ${1:title} 8 | description: ${2:description} 9 | tags: ${3:tags} 10 | image: ${4:image} 11 | last_modified_at: 2021-07-05 12 | banner_image: ${5:banner_image} 13 | --- 14 | 15 | $0 16 | endsnippet 17 | 18 | snippet til "TIL Heading" b 19 | # ${1:How to ...} 20 | **_Posted on `date "+%d %b, %Y"`_** 21 | $0 22 | endsnippet 23 | 24 | snippet tbc "Centerd Table" 25 | | ${1:column1} | ${2:column2} | ${3:column3} | 26 | |:-------------:|:-------------:|:----------:| 27 | | $0 | Y | N | 28 | | f2 | Y | N | 29 | endsnippet 30 | 31 | -------------------------------------------------------------------------------- /scripts/shell/epoch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # Script to ouput current unix epoch and convert to readable datetime 4 | 5 | case "$(uname)" in 6 | Linux ) converter="date" ;; 7 | Darwin ) converter="gdate" ;; 8 | esac 9 | 10 | case "$1" in 11 | now) 12 | date +'%s' 13 | [ $(uname) == "Darwin" ] && date -r $(date -u +%s) || date --date="@$(date -u +%s)" ;; 14 | later) 15 | # e.g epoch later "10 days" 16 | [ -z "$2" ] && echo "argument missing, 'epoch later '" && return 17 | $converter -d "$2" 18 | $converter -u +%s -d "$2";; 19 | *) 20 | [ -z $1 ] && echo "argument missing, 'epoch '" && return 21 | [ $(uname) == "Darwin" ] && date -r "$1" || date --date="@$1";; 22 | esac 23 | 24 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/fzf.lua: -------------------------------------------------------------------------------- 1 | --[[return { 2 | "junegunn/fzf.vim", 3 | dependencies = { "junegunn/fzf" }, 4 | lazy = false, -- Load lazily 5 | -- check https://github.com/junegunn/fzf.vim 6 | cmd = { "FZF", "FZFPreview", "FZFPreviewFile", "FZFPreviewBuffer", "FZFPreviewGrep" }, 7 | }]] 8 | 9 | return { 10 | "ibhagwan/fzf-lua", 11 | lazy = false, 12 | --[[ init = function() 13 | ---@diagnostic disable-next-line: duplicate-set-field 14 | vim.ui.select = function(...) 15 | require("fzf-lua").register_ui_select() 16 | vim.ui.select(...) 17 | end 18 | end,]] 19 | -- optional for icon support 20 | dependencies = { "nvim-tree/nvim-web-devicons" }, 21 | -- or if using mini.icons/mini.nvim 22 | -- dependencies = { "echasnovski/mini.icons" }, 23 | opts = {}, 24 | config = function(_, opts) 25 | require("fzf-lua").setup(opts) 26 | require("fzf-lua").register_ui_select() 27 | end, 28 | } 29 | -------------------------------------------------------------------------------- /scripts/git/git-diff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # FZF Wrapper over git to interactively diff files across branches 4 | 5 | readarray -t git_files < <(git ls-files | fzf \ 6 | --prompt="Choose File(s): " \ 7 | --height 40% --reverse --multi \ 8 | --header="Choose files to diff (TAB to select multiple files)" 9 | ) 10 | 11 | target_branch=$(git for-each-ref --format='%(refname:short)' refs/heads/* | fzf \ 12 | --prompt="Select target branch: " \ 13 | --header="Select branch to compare the files against" \ 14 | --height 40% --reverse 15 | ) 16 | 17 | # get current branch 18 | current_branch=$(git branch | grep \\* | cut -d ' ' -f2) 19 | 20 | printf "%s\n" "Viewing diff for following files against $(tput bold)$target_branch$(tput sgr0)" 21 | printf "$(tput bold)$(tput setaf 208)%s$(tput sgr0)\n" "${git_files[@]}" 22 | echo 23 | 24 | git diff "$current_branch".."$target_branch" -- "${git_files[@]}" 25 | 26 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/zen.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "folke/zen-mode.nvim", 3 | cmd = {"ZenMode"}, 4 | config = function() 5 | require("zen-mode").setup({ 6 | window = { 7 | backdrop = 0.95, -- Darkens the background 8 | width = 120, -- Width of the Zen window 9 | height = 1, -- Height of the Zen window 10 | options = { 11 | signcolumn = "no", -- Disable sign column 12 | number = false, -- Disable line numbers 13 | relativenumber = false, -- Disable relative line numbers 14 | cursorline = false, -- Disable cursor line 15 | foldcolumn = "0", -- Disable fold column 16 | laststatus = 0, -- Disable last status line 17 | showcmd = false 18 | } 19 | } 20 | }) 21 | end 22 | } 23 | -------------------------------------------------------------------------------- /.config/nvim/lua/autocmds.lua: -------------------------------------------------------------------------------- 1 | -- autocmds.lua 2 | 3 | local augroup = vim.api.nvim_create_augroup 4 | local autocmd = vim.api.nvim_create_autocmd 5 | 6 | local general = augroup("GeneralSettings", { clear = true }) 7 | 8 | -- Reload file if changed externally 9 | autocmd("FocusGained", { 10 | group = general, 11 | pattern = "*", 12 | command = "checktime", 13 | }) 14 | 15 | -- Highlight on yank 16 | autocmd("TextYankPost", { 17 | group = general, 18 | pattern = "*", 19 | callback = function() 20 | vim.highlight.on_yank({ timeout = 200 }) 21 | end, 22 | }) 23 | 24 | -- Filetype specific indentation 25 | autocmd("FileType", { 26 | group = general, 27 | pattern = { "python", "lua" }, 28 | callback = function() 29 | vim.opt_local.shiftwidth = 4 30 | vim.opt_local.tabstop = 4 31 | end, 32 | }) 33 | 34 | -- Automatically resize splits on window resize 35 | autocmd("VimResized", { 36 | group = general, 37 | command = "wincmd =", 38 | }) 39 | -------------------------------------------------------------------------------- /.config/nvim/lsp/gopls.lua: -------------------------------------------------------------------------------- 1 | -- Configurations for the "gopls" LSP server for Go files 2 | return { 3 | cmd = {"gopls"}, 4 | filetypes = {"go", "gomod", "gowork", "gotmpl"}, 5 | root_markers = {"go.work", "go.mod", ".git"}, 6 | settings = { 7 | gopls = { 8 | usePlaceholders = true, 9 | completeUnimported = true, 10 | staticcheck = true, 11 | analyses = { 12 | unusedparams = true, 13 | shadow = true 14 | } 15 | } 16 | }, 17 | on_init = function(client) 18 | -- Optional: adjust client config on init if needed 19 | local path = client.workspace_folders and client.workspace_folders[1].name or nil 20 | if path and not vim.uv.fs_stat(path .. "/go.mod") then 21 | vim.notify("gopls: go.mod not found in root dir", vim.log.levels.WARN) 22 | end 23 | end, 24 | capabilities = (function() 25 | local capabilities = vim.lsp.protocol.make_client_capabilities() 26 | capabilities.textDocument.completion.completionItem.snippetSupport = true 27 | return capabilities 28 | end)() 29 | } 30 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/treesitter.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-treesitter/nvim-treesitter", 3 | branch = "master", 4 | lazy = false, 5 | priority = 100, 6 | build = ":TSUpdate", 7 | config = function() 8 | local ok, treesitter = pcall(require, "nvim-treesitter.configs") 9 | if not ok then 10 | return 11 | end 12 | 13 | treesitter.setup({ 14 | ensure_installed = { 15 | "bash", 16 | "comment", 17 | "css", 18 | "diff", 19 | "dockerfile", 20 | "git_rebase", 21 | "gitattributes", 22 | "gitcommit", 23 | "gitignore", 24 | "go", 25 | "gomod", 26 | "gosum", 27 | "hcl", 28 | "html", 29 | "javascript", 30 | "jinja", 31 | "jsdoc", 32 | "json", 33 | "lua", 34 | "make", 35 | "markdown", 36 | "markdown_inline", 37 | "mermaid", 38 | "python", 39 | "regex", 40 | "rst", 41 | "scss", 42 | "terraform", 43 | "toml", 44 | "typescript", 45 | "yaml", 46 | "vim", 47 | "vimdoc", 48 | }, 49 | sync_install = false, 50 | auto_install = true, 51 | highlight = { 52 | enable = true, 53 | additional_vim_regex_highlighting = false, 54 | }, 55 | }) 56 | end, 57 | } 58 | -------------------------------------------------------------------------------- /scripts/shell/xfi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script helps ignore unnecessary dir paths while using find 4 | 5 | EXCLUDE_DIRS=( 6 | "! -path /*.git/*" 7 | "! -path /*go/*" 8 | "! -path /*.bundle/*" 9 | "! -path /*.cache/*" 10 | "! -path /*.local/*" 11 | "! -path /*.themes/*" 12 | "! -path /*.config/*" 13 | "! -path /*.codeintel/*" 14 | "! -path /*.mozilla/*" 15 | "! -path /*python2.7/*" 16 | "! -path /*python3.6/*" 17 | "! -path /*python3.8/*" 18 | "! -path /*__pycache__/*" 19 | "! -path /*.vscode/*" 20 | "! -path /*.themes/*" 21 | "! -path /*.icons/*" 22 | "! -path /*.dartServer/*" 23 | "! -path /*.gradle/*" 24 | "! -path /*.pub-cache/*" 25 | "! -path /*flutter/*" 26 | "! -path /*node_modules/*" 27 | "! -path /*Android/*" 28 | "! -path /*.android/*" 29 | "! -path /*.java/*" 30 | "! -path /*styles/*" 31 | "! -path /*.vscode-oss/*" 32 | "! -path /*.jekyll-cache/*" 33 | "! -path /*.emacs.d/*" 34 | "! -path /*android-studio/*" 35 | "! -path /*python-wheels/*" 36 | ) 37 | # additionally ignore snap/ cuz its getting expanded 38 | find $HOME ${EXCLUDE_DIRS[@]} ! -path "/*snap/*" ! -path "/*Library/*" 39 | -------------------------------------------------------------------------------- /.config/nvim/after/ftplugin/python.lua: -------------------------------------------------------------------------------- 1 | -- Filetype plugin module for configuring Python development in Neovim 2 | -- Refer to the resource shared below for further inspiration 3 | -- https://github.com/aikow/dotfiles/blob/main/config/nvim/after/ftplugin/python.lua 4 | 5 | local map = require("utils").map 6 | 7 | -- INFO: Local keymap (specific to Python files) to execute the current Python script 8 | if os.getenv("VIRTUAL_ENV") ~= nil then 9 | map("n", "", "terminal pytest %") 10 | map("n", "", "terminal python %") 11 | else 12 | map("n", "", "terminal python3 %") 13 | end 14 | 15 | -- Wrap words at the EOL "cleanly" (i.e) ensure the words are wrapped and not just characters 16 | vim.opt.wrap = true 17 | vim.opt.linebreak = true 18 | 19 | -- Start the Treesitter parse process for highligting Python files 20 | vim.treesitter.start() 21 | 22 | -- Configure the indent-based folds for Python buffers 23 | if vim.api.nvim_buf_line_count(0) >= 100 then 24 | vim.opt.foldmethod = "expr" 25 | vim.opt.foldexpr = "nvim_treesitter#foldexpr()" 26 | vim.opt.foldlevel = 0 27 | vim.opt.foldcolumn = "auto" 28 | end 29 | 30 | -- Start the "pyright" LSP server 31 | vim.lsp.enable("pyright", true) 32 | -------------------------------------------------------------------------------- /.config/nvim/lsp/lua_ls.lua: -------------------------------------------------------------------------------- 1 | -- Configurations for the "lua_ls" LSP server for Lua files 2 | return { 3 | cmd = { "lua-language-server" }, 4 | filetypes = { "lua" }, 5 | root_markers = { 6 | ".luarc.json", 7 | ".luarc.jsonc", 8 | ".luacheckrc", 9 | ".stylua.toml", 10 | "stylua.toml", 11 | "selene.toml", 12 | "selene.yml", 13 | ".git", 14 | }, 15 | on_init = function(client) 16 | if client.workspace_folders then 17 | local path = client.workspace_folders[1].name 18 | 19 | if 20 | path ~= vim.fn.stdpath("config") 21 | and (vim.uv.fs_stat(path .. "/.luarc.json") or vim.uv.fs_stat(path .. "/.luarc.jsonc")) 22 | then 23 | return 24 | end 25 | end 26 | 27 | client.config.settings.Lua = vim.tbl_deep_extend("force", client.config.settings.Lua, { 28 | runtime = { version = "LuaJIT" }, 29 | path = { "lua/?.lua", "lua/?/init.lua" }, 30 | workspace = { 31 | checkThirdParty = false, 32 | library = vim.api.nvim_get_runtime_file("", true), 33 | -- library = { vim.env.RUNTIME }, 34 | }, 35 | diagnostics = { 36 | globals = { "vim", "vim.g" }, 37 | enable = true, 38 | }, 39 | format = { enable = false }, 40 | }) 41 | end, 42 | settings = { 43 | Lua = {}, 44 | }, 45 | } 46 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/filetree.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-tree/nvim-tree.lua", 3 | lazy = false, 4 | dependencies = {"nvim-tree/nvim-web-devicons"}, 5 | cmd = { "NvimTreeToggle", "NvimTreeOpen", "NvimTreeFocus" }, 6 | config = function() 7 | -- Disable netrw 8 | -- vim.g.loaded_netrw = 1 9 | -- vim.g.loaded_netrwPlugin = 1 10 | require("nvim-tree").setup({ 11 | sort = { 12 | sorter = "case_sensitive" 13 | }, 14 | view = { 15 | width = 30 16 | }, 17 | renderer = { 18 | group_empty = true 19 | }, 20 | filters = { 21 | dotfiles = false 22 | } 23 | }) 24 | -- -- Auto-open NvimTree on startup 25 | -- local function open_nvim_tree(data) 26 | -- -- Ignore if it's a directory 27 | -- if vim.fn.isdirectory(data.file) == 1 then 28 | -- require("nvim-tree.api").tree.open() 29 | -- return 30 | -- end 31 | -- -- For normal files 32 | -- require("nvim-tree.api").tree.open() 33 | -- end 34 | 35 | -- vim.api.nvim_create_autocmd({ "VimEnter" }, { callback = open_nvim_tree }) 36 | end 37 | } 38 | -------------------------------------------------------------------------------- /scripts/media/gif: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Utility to convert video files to GIFs using ffmpeg 4 | # 5 | # Usage: convert-to-gif.sh 6 | # To skip frames: convert-to-gif.sh 7 | # Example: 8 | # convert-to-gif.sh video.mp4 28 9 | 10 | 11 | if [[ -z "$1" ]]; then 12 | echo "No video file specified" 13 | exit 1 14 | fi 15 | 16 | # get everything after last / 17 | video=${1##*/} 18 | # remove everything after . 19 | filename=${video%.*} 20 | 21 | echo -e "$(tput bold) Getting video dimensions $(tput sgr0)" 22 | # Get video dimensions 23 | dimensions=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 "$1") 24 | 25 | echo -e "$(tput bold) Generating Palette $(tput sgr0)" 26 | # Generate palette 27 | ffmpeg -i "$1" -vf "fps=22,scale=${dimensions%x*}:-1:flags=lanczos,palettegen" "$filename".png 28 | 29 | echo -e "$(tput bold) Converting Video to GIF $(tput sgr0)" 30 | 31 | if [[ "$2" ]]; then 32 | ffmpeg -t "$2" -i "$1" -i "$filename".png -filter_complex "fps=22,scale=${dimensions%x*}:-1:flags=lanczos[x];[x][1:v]paletteuse" "$filename".gif 33 | else 34 | ffmpeg -i "$1" -i "$filename".png -filter_complex "fps=22,scale=${dimensions%x*}:-1:flags=lanczos[x];[x][1:v]paletteuse" "$filename".gif 35 | fi 36 | 37 | echo -e "Removing palette" 38 | rm "$filename".png 39 | -------------------------------------------------------------------------------- /scripts/file/md: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | IFS=$'\n\t' 5 | 6 | # md.sh: watch a MD file & build its HTML preview using commonmarker 7 | 8 | IFS=$'\n' 9 | 10 | cleanup() { 11 | printf "\n%s" "Removing $1" 12 | rm "$1" 13 | exit 14 | } 15 | 16 | build_preview() { 17 | echo -e "\nBuilding HTML preview ($(date +%I:%M:%S))" 18 | if commonmarker --extension=table "$1" >"$html_preview"; then 19 | echo -e "Preview at: $(tput bold)file://$PWD/$html_preview$(tput sgr0)" 20 | else 21 | echo -e "commonmarker not found or some error occured" 22 | fi 23 | } 24 | 25 | watch_changes() { 26 | while true; do 27 | echo -en "\rWatching file $(tput bold)$1$(tput sgr0) ..." 28 | last_modify_time=$(date -d "@$(stat -c '%Y' "$1")" '+%T') 29 | sleep 0.1 30 | last_modify_time_2=$(date -d "@$(stat -c '%Y' "$1")" '+%T') 31 | 32 | [[ "$last_modify_time" != "$last_modify_time_2" ]] && build_preview "$1" 33 | 34 | [[ -f "$html_preview" ]] && trap "cleanup '$html_preview'" SIGINT 35 | done 36 | } 37 | 38 | if [[ -z "$1" ]]; then 39 | echo -e "md requires a .md file" 40 | exit 1 41 | else 42 | html_preview="${1%.*}.html" 43 | build_preview "$1" 44 | echo -e "Opening preview in browser ..." 45 | # alternative is to directly invoke browser 46 | xdg-open "file://$PWD/$html_preview" &>/dev/null 47 | watch_changes "$1" 48 | fi 49 | -------------------------------------------------------------------------------- /.config/wezterm/wezterm.lua: -------------------------------------------------------------------------------- 1 | -- Pull in the wezterm API 2 | local wezterm = require("wezterm") 3 | 4 | -- This will hold the configuration. 5 | local config = wezterm.config_builder() 6 | 7 | -- This is where you actually apply your config choices. 8 | 9 | --config.initial_cols = 120 10 | --config.initial_rows = 28 11 | config.window_decorations = "RESIZE" 12 | 13 | config.font_size = 15 14 | config.color_scheme = "Ayu Mirage" 15 | config.font = wezterm.font("FiraCode Nerd Font") 16 | 17 | -- Remove extra padding 18 | config.window_padding = { 19 | left = 0, 20 | right = 0, 21 | top = 0, 22 | bottom = 0, 23 | } 24 | config.window_frame = { 25 | active_titlebar_bg = "#090909", 26 | } 27 | 28 | config.animation_fps = 120 29 | config.cursor_blink_ease_in = "EaseOut" 30 | config.cursor_blink_ease_out = "EaseOut" 31 | config.default_cursor_style = "BlinkingBlock" 32 | config.cursor_blink_rate = 650 33 | config.window_background_opacity = 0.7 -- 0.0 = fully transparent, 1.0 = opaque 34 | config.text_background_opacity = 1.0 -- keep text solid 35 | config.macos_window_background_blur = 20 36 | --config.line_height = 1.0 -- or slightly less, e.g., 0.95 37 | config.cursor_thickness = "2pt" 38 | 39 | config.colors = { 40 | cursor_bg = "#5DFFFF", 41 | cursor_fg = "#1E1E1E", 42 | } 43 | 44 | wezterm.on("gui-startup", function(cmd) 45 | local tab, pane, window = wezterm.mux.spawn_window(cmd or {}) 46 | window:gui_window():toggle_fullscreen() 47 | end) 48 | 49 | return config 50 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/mason.lua: -------------------------------------------------------------------------------- 1 | -- Module for configuring the "mason" plugin for managing LSP servers 2 | 3 | return { 4 | { 5 | "mason-org/mason.nvim", 6 | cmd = { "LspInstall", "LspUninstall", "Mason" }, 7 | opts = { 8 | -- Configure the plugin to have rounded borders 9 | ui = { border = "rounded" }, 10 | 11 | -- Configure the log levels for the plugin 12 | log_level = vim.log.levels.WARN, 13 | }, 14 | config = function(_, opts) 15 | require("mason").setup(opts) 16 | end, 17 | dependencies = { "neovim/nvim-lspconfig" }, 18 | }, 19 | 20 | { 21 | "WhoIsSethDaniel/mason-tool-installer.nvim", 22 | cmd = { "MasonToolsInstall", "MasonToolsUpdate", "MasonToolsClean" }, 23 | opts = { 24 | ensure_installed = { 25 | "bash-language-server", 26 | "black", 27 | "css-lsp", 28 | "debugpy", 29 | "dockerfile-language-server", 30 | "eslint-lsp", 31 | "goimports-reviser", 32 | "golines", 33 | "hadolint", 34 | "hclfmt", 35 | "json-lsp", 36 | "lua-language-server", 37 | "prettier", 38 | "pyright-langserver", 39 | "shellcheck", 40 | "shfmt", 41 | "stylua", 42 | "stylelint", 43 | "sqlls", 44 | "terraform-ls", 45 | "typescript-language-server", 46 | "tinymist", 47 | "vale-ls", 48 | "vtsls", 49 | "yaml-language-server", 50 | "yamllint", 51 | }, 52 | }, 53 | config = function(_, opts) 54 | require("mason-tool-installer").setup(opts) 55 | end, 56 | }, 57 | } 58 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/lualine.lua: -------------------------------------------------------------------------------- 1 | -- Module for configuring the statusline plugin - "lualine" 2 | return { 3 | "nvim-lualine/lualine.nvim", 4 | -- This needs to be loaded after the "VeryLazy" event otherwise an ugly 5 | -- unstyled statusline is created after Neovim startup 6 | event = "VeryLazy", 7 | opts = { 8 | -- Leaving an empty table renders the square-edged components, else the default angled ones are loaded 9 | section_separators = { 10 | left = "", 11 | right = "", 12 | }, 13 | component_separators = { 14 | left = "", 15 | right = "", 16 | }, 17 | --theme = "horizon", 18 | globalstatus = true, 19 | disabled_filetypes = { 20 | statusline = { 21 | "dashboard", 22 | "filesytem", 23 | "mason", 24 | "neo-tree", 25 | "neo-tree-popup", 26 | "null-ls-info", 27 | "lazy", 28 | "lspinfo", 29 | "ministarter", 30 | "TelescopePrompt", 31 | }, 32 | }, 33 | }, 34 | config = function(_, opts) 35 | local sections = { 36 | -- Statusline components to showcase on the right-most end 37 | lualine_x = { "filetype" }, 38 | -- add "progress" to lualine_y to show file scroll percentage 39 | lualine_y = { "" }, 40 | lualine_z = { "location" }, 41 | lualine_c = { "filename" }, 42 | -- lualine_c = { -- INFO: This section shows the entire filepath relative to the project root 43 | -- { "filename", path = 1 }, 44 | -- }, 45 | } 46 | 47 | require("lualine").setup({ 48 | options = opts, 49 | sections = sections, 50 | }) 51 | end, 52 | disable = false, 53 | } 54 | -------------------------------------------------------------------------------- /.config/nvim/lua/options.lua: -------------------------------------------------------------------------------- 1 | local opt = vim.opt 2 | opt.number = true 3 | opt.relativenumber = true 4 | opt.autoindent = true 5 | opt.smartindent = true 6 | opt.expandtab = true 7 | opt.showcmd = true 8 | opt.autoread = true 9 | opt.cursorline = true 10 | opt.iskeyword:append("-") 11 | opt.wildignorecase = true 12 | opt.wildignore = { 13 | "*.jpg", 14 | "*.bmp", 15 | "*.gif", 16 | "*.png", 17 | "*.jpeg", 18 | "*.avi", 19 | "*.mp4", 20 | "*.mkv", 21 | "*.pdf", 22 | "*.odt", 23 | "*/.git/*", 24 | "*/site-packages/*", 25 | "*/lib/*", 26 | "*/bin/*", 27 | "*.pyc", 28 | } 29 | opt.path:append("**") 30 | opt.shortmess:append("c") 31 | opt.dictionary:append("/usr/share/dict/words") 32 | opt.lazyredraw = true 33 | opt.completeopt = "menuone,noselect" 34 | opt.encoding = "UTF-8" 35 | opt.termguicolors = true 36 | opt.background = "dark" 37 | -- disable NVIM start message 38 | opt.shortmess:append("I") 39 | 40 | vim.g.netrw_banner = 0 -- disable annoying banner 41 | vim.g.netrw_liststyle = 3 -- tree view 42 | vim.g.netrw_browse_split = 2 -- Open file in new vertical split 43 | vim.g.netrw_preview = 1 44 | vim.g.netrw_altv = 1 45 | vim.g.netrw_winsize = 27 -- Fix width to 27% 46 | vim.g.netrw_special_syntax = 1 -- Enable special file highlighting 47 | vim.g.netrw_browsex_viewer = "browse" 48 | 49 | vim.o.tabstop = 4 -- A TAB character looks like 4 spaces 50 | vim.o.expandtab = true -- Pressing the TAB key will insert spaces instead of a TAB character 51 | vim.o.softtabstop = 4 -- Number of spaces inserted instead of a TAB character 52 | vim.o.shiftwidth = 4 -- Number of spaces inserted when indenting 53 | -------------------------------------------------------------------------------- /scripts/shell/sys: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Realtime system info 4 | # 5 | # Use: watch -ct -n0 sys.sh 6 | # 7 | # TODO: 8 | # 1. Netspeed 9 | # 2. Open ports ? 10 | 11 | # color definitions 12 | RESET=$'\e[0m' 13 | BOLD_GREEN_FG=$'\e[1;32m' 14 | BOLD_WHITE_FG=$'\e[1m' 15 | 16 | ## RAM Usage 17 | ram=$(free -h | awk '/^Mem:/ {print $3 "/" $2}') 18 | 19 | ## Show CPU temperature 20 | temperature=$(sensors | awk '/^Core*/ {print $1$2, $3}') 21 | 22 | ## Most Memory Intensive processes 23 | mem_intensive=$(ps axch -o cmd:15,%mem --sort=-%mem | head) 24 | 25 | ## Most CPU Intensive processes 26 | cpu_intensive=$(ps axch -o cmd:15,%cpu --sort=-%cpu | head) 27 | 28 | ## Network usage stats 29 | net_device=$(route | awk '/default/ {print $8}') 30 | TRANSMITTED=$(ifconfig "$net_device" | awk '/TX packets/ {print $6$7}') 31 | RECEIVED=$(ifconfig "$net_device" | awk '/RX packets/ {print $6$7}') 32 | 33 | pc_uptime=$(uptime -p | awk '{for (i=2; i= 1) print $NF; }') 34 | 35 | printf "%70s\n\n" "${BOLD_WHITE_FG}System Monitor${RESET}" 36 | printf "%s\n\n" "${BOLD_GREEN_FG}Network Usage since${RESET} $pc_uptime" 37 | printf "%s\n" "🔼 TRANSMITTED : $TRANSMITTED" 38 | printf "%s\n" "🔽 RECEIVED : $RECEIVED" 39 | 40 | printf "\n%s\n" "${BOLD_GREEN_FG}RAM :${RESET} $ram" 41 | 42 | printf "\n%s\n\n" "${BOLD_GREEN_FG}CPU Temperature 🌡 : ${RESET}" 43 | printf "%s\n" "$temperature" 44 | 45 | printf "\n%s\n\n" "${BOLD_GREEN_FG}Most Memory Intensive Processes${RESET}" 46 | printf "%s" "$mem_intensive" 47 | 48 | printf "\n\n%s\n\n" "${BOLD_GREEN_FG}Most CPU Intensive Processes${RESET}" 49 | printf "%s\n\n" "$cpu_intensive" 50 | -------------------------------------------------------------------------------- /scripts/git/git-stash-checkout: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # FZF + Git script to interactively recover one or more files from stash 4 | 5 | # Doesnt preview/checkout untracked files stored in stash 6 | 7 | # preliminary check to see if we have stash or not 8 | have_stash=$(git stash list) 9 | [ -z "$have_stash" ] && echo "Stash is empty!" && exit 10 | 11 | # get the stash 12 | stash=$(git --no-pager stash list --pretty=format:'%C(bold blue)%gd%C(reset)%C(bold green) (%cr)%C(reset) - %s' --color | fzf \ 13 | --prompt="Choose stash: " \ 14 | --preview "echo {} | cut -d' ' -f1 | xargs -I{} git stash show --color -p {}" \ 15 | --bind 'j:down,k:up,ctrl-j:preview-down,ctrl-k:preview-up,ctrl-space:toggle-preview' --preview-window right:60% \ 16 | --ansi --height 60% --reverse | \ 17 | awk '{print $1}' 18 | ) 19 | 20 | if [[ -z "$stash" ]]; then 21 | printf "%s\n" "Please select a stash" 22 | else 23 | # get the file from stash 24 | readarray -t files < <(git stash show -p "$stash" --name-only | fzf \ 25 | --prompt="Choose file(s): " \ 26 | --height 40% --reverse --multi \ 27 | --header="Choose files to recover from stash (TAB to select multiple files)" 28 | ) 29 | if [[ -z "$files" ]]; then 30 | echo "Please select atleast 1 file " 31 | else 32 | # git checkout -- 33 | # git checkout "$stash" -- "${files[@]}" 34 | 35 | # better way 36 | # Merge the changes on top of current version 37 | # https://stackoverflow.com/questions/15264553/how-to-unstash-only-certain-files/50370632#50370632 38 | git diff "$stash"^1 "$stash" -- "${files[@]}" | git apply 39 | fi 40 | fi 41 | -------------------------------------------------------------------------------- /.config/nvim/lua/keymaps.lua: -------------------------------------------------------------------------------- 1 | -- keymaps.lua 2 | 3 | local map = vim.keymap.set 4 | local opts = { noremap = true, silent = true } 5 | 6 | -- Leader key 7 | vim.g.mapleader = " " 8 | 9 | -- Terminal mode escape 10 | map("t", "", "", opts) 11 | 12 | -- File explorer 13 | map("n", "n", ":NvimTreeToggle", opts) 14 | 15 | -- Terminal 16 | --map("n", "t", ":FloatermToggle", opts) 17 | 18 | -- Save & quit 19 | map("n", "w", ":w", opts) 20 | map("n", "q", ":q", opts) 21 | map("n", "x", ":x", opts) 22 | 23 | -- Clear search 24 | map("n", "c", ":nohlsearch", opts) 25 | 26 | -- Toggle Goyo mode 27 | -- map("n", "z", ":Goyo", opts) 28 | 29 | -- FZF Lua 30 | map("n", "f", ":FzfLua files", opts) 31 | map("n", "g", ":FzfLua live_grep", opts) 32 | map("n", "b", ":FzfLua buffers", opts) 33 | map("n", "c", ":FzfLua colorschemes", opts) 34 | 35 | -- Activate Command Mode using ";" 36 | map("n", ";", ":") 37 | 38 | -- Resize split windows 39 | map("n", "", ":vertical resize +3") 40 | map("n", "", ":vertical resize -3") 41 | 42 | -- Cycle through open buffers 43 | map("n", "", ":bn") 44 | 45 | -- Tab to cycle through open splits 46 | map("n", "", "") 47 | 48 | -- Copy using ctrl + c 49 | map("v", "", '"+y') 50 | map("v", "", '"+y') 51 | map("i", "", '"+pi') 52 | 53 | -- vertical split 54 | map("n", "v", ":vsp") 55 | 56 | -- horizontal split 57 | map("n", "s", ":sp") 58 | 59 | -- new tab 60 | map("n", "t", ":tabnew") 61 | 62 | -- Visual inner line (without whitespaces) - slightly better than shift+v 63 | map("v", "il", ":normal ^vg_") 64 | -------------------------------------------------------------------------------- /scripts/file/oib: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | A utility to open a texfile as an HTML page 5 | (to use Grammarly web extension) 6 | """ 7 | 8 | from sys import stdin 9 | from string import Template 10 | from pathlib import Path 11 | import os 12 | import sys 13 | import http.server 14 | import socketserver 15 | import webbrowser 16 | 17 | TEMPLATE = Template( 18 | """ 19 | 20 | 21 | 22 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | """ 43 | ) 44 | 45 | 46 | def serve(path): 47 | PORT = 8000 48 | Handler = http.server.SimpleHTTPRequestHandler 49 | try: 50 | socketserver.TCPServer.allow_reuse_address = True 51 | with socketserver.TCPServer(("", PORT), Handler) as httpd: 52 | print("Serving at port", PORT) 53 | httpd.serve_forever() 54 | except KeyboardInterrupt: 55 | os.remove(path) 56 | print("\nClosing server ... Bye") 57 | sys.exit() 58 | 59 | 60 | if __name__ == "__main__": 61 | is_pipe = not os.isatty(stdin.fileno()) 62 | textpad_filename = "temp.html" 63 | textpad_filepath = Path.cwd() / textpad_filename 64 | if is_pipe: 65 | content = stdin.read() 66 | 67 | with open(textpad_filepath, "w") as fw: 68 | fw.write(TEMPLATE.substitute(text=content)) 69 | webbrowser.open(f"http://127.0.0.1:8000/{textpad_filename}") 70 | serve(textpad_filepath) 71 | -------------------------------------------------------------------------------- /scripts/shell/colors: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | colors256() { 4 | local c i j 5 | 6 | printf "Colors 0 to 15 for the standard 16 colors\n" 7 | for ((c = 0; c < 16; c++)); do 8 | printf "|%s%3d%s" "$(tput setaf "$c")" "$c" "$(tput sgr0)" 9 | done 10 | printf "|\n\n" 11 | 12 | printf "Colors 16 to 231 for 256 colors\n" 13 | for ((i = j = 0; c < 232; c++, i++)); do 14 | printf "|" 15 | ((i > 5 && (i = 0, ++j))) && printf " |" 16 | ((j > 5 && (j = 0, 1))) && printf "\b \n|" 17 | printf "%s%3d%s" "$(tput setaf "$c")" "$c" "$(tput sgr0)" 18 | done 19 | printf "|\n\n" 20 | 21 | printf "Greyscale 232 to 255 for 256 colors\n" 22 | for (( ; c < 256; c++)); do 23 | printf "|%s%s%3d%s" "$(tput bold)" "$(tput setaf "$c")" "$c" "$(tput sgr0)" 24 | done 25 | printf "|\n" 26 | } 27 | 28 | style() { 29 | 30 | echo "tput character test" 31 | echo "===================" 32 | echo 33 | 34 | tput bold 35 | echo "This text has the bold attribute." 36 | tput sgr0 37 | 38 | tput smul 39 | echo "This text is underlined (smul)." 40 | tput rmul 41 | 42 | # Most terminal emulators do not support blinking text (though xterm 43 | # does) because blinking text is considered to be in bad taste ;-) 44 | tput blink 45 | echo "This text is blinking (blink)." 46 | tput sgr0 47 | 48 | tput rev 49 | echo "This text has the reverse attribute" 50 | tput sgr0 51 | 52 | # Standout mode is reverse on many terminals, bold on others. 53 | tput smso 54 | echo "This text is in standout mode (smso)." 55 | tput rmso 56 | 57 | tput sgr0 58 | echo 59 | } 60 | 61 | colors256 62 | style 63 | 64 | for fgbg in 38 48 ; do # Foreground / Background 65 | for color in {0..255} ; do # Colors 66 | # Display the color 67 | printf "\e[${fgbg};5;%sm %3s \e[0m" $color $color 68 | # Display 6 colors per lines 69 | if [ $((($color + 1) % 6)) == 4 ] ; then 70 | echo # New line 71 | fi 72 | done 73 | echo # New line 74 | done 75 | 76 | exit 0 77 | -------------------------------------------------------------------------------- /.bash_aliases: -------------------------------------------------------------------------------- 1 | # git aliases 2 | alias gsh='git push' 3 | alias gll='git pull' 4 | alias gia='git-add' 5 | alias gis='git status' 6 | alias gic='git-commit' 7 | alias gicl='git clone' 8 | 9 | alias gib='git branch' 10 | alias gibs='git-switch' 11 | alias giws='source git-worktree-switch' 12 | alias giw='source git-worktree-all' 13 | 14 | alias gir='git restore' 15 | alias gil='git log --graph --decorate --pretty=oneline --abbrev-commit' 16 | alias gid='git diff' 17 | # go aliases 18 | alias gb="go build" 19 | alias gr="go run" 20 | alias gd="go doc -all" 21 | alias gg="go get" 22 | alias gt="go test ./... -v -coverpkg=./... -coverprofile=coverage.out" 23 | alias gtc="go tool cover -html=coverage.out" 24 | alias dc="docker-compose" 25 | # python aliases 26 | alias p='python3' 27 | alias venv="python3 -m venv" 28 | alias pdb="python3 -m pdb" 29 | alias serve="python3 -m http.server" 30 | # miscellaneous 31 | alias dotman='$HOME/dotman/dotman.sh' 32 | alias update='sudo apt-get update' 33 | alias upgrade='sudo apt-get upgrade' 34 | # alias cd="vcd" 35 | alias sys="watch -ct -n0 sys" 36 | alias bb="jekyll serve --watch" 37 | alias lt="ls --human-readable --size -1 -S --classify" 38 | alias lh="ls -ld .*" 39 | # open a random file from current dir 40 | alias amaze="find . -type f -print0 | shuf -z -n 1 | xargs -0 browse > /dev/null 2>&1" 41 | alias bro="xfi | fzf --exact --prompt='Search File: ' --preview '(eye {} || tree -C {}) 2> /dev/null || cat {}' --pointer='🡆' --height 60% --reverse --color 'fg:#E6E1CF,fg+:#ddeeff,prompt:#A9DC76,pointer:#FF6188,header:#AB9DF2,query:#FFD866,hl+:#FFEE99' | xargs -I FILEP browse \"FILEP\"" 42 | alias til="locate -e '/home/bhupesh/Documents/til' | fzf | xargs glow --pager" 43 | alias fbro="locate $HOME | fzf --exact --prompt='Search File: ' --pointer=🡆 --height 60% --reverse --color fg:#E6E1CF,fg+:#ddeeff,prompt:#A9DC76,pointer:#FF6188,header:#AB9DF2,query:#FFD866,hl+:#FFEE99 | xargs -I FILEP browse FILEP" 44 | alias dot="git --git-dir=$HOME/.dotfiles --work-tree=$HOME" -------------------------------------------------------------------------------- /snippets/python.snippets: -------------------------------------------------------------------------------- 1 | snippet req "Network Request" b 2 | def request(url, data=None, method=None): 3 | if method == "PATCH": 4 | req = urllib.request.Request(url, data=data, headers=HEADERS) 5 | req.get_method = lambda: "PATCH" 6 | elif method == "POST": 7 | req = urllib.request.Request(url, data=data, headers=HEADERS) 8 | else: 9 | req = urllib.request.Request(url, headers=HEADERS) 10 | try: 11 | with urllib.request.urlopen(req) as response: 12 | res = json.loads(response.read().decode("utf-8")) 13 | except urllib.error.URLError as e: 14 | print(e.reason) 15 | exit() 16 | return res, response.code 17 | endsnippet 18 | 19 | snippet valid_date "Validate Date" 20 | def is_valid(date): 21 | try: 22 | if isinstance(parse(date), datetime.datetime): 23 | return True 24 | except ValueError: 25 | return False 26 | endsnippet 27 | 28 | snippet flask "Flask Starter app.py" b 29 | from flask import Flask, render_template 30 | 31 | app = Flask(__name__, instance_relative_config=True) 32 | 33 | @app.route("/") 34 | def index(): 35 | return render_template("index.html") 36 | # return "Hello, World!" 37 | 38 | @app.route('/post', methods=['POST']) 39 | def post(): 40 | return render_template("post.html") 41 | 42 | 43 | if __name__ == "__main__": 44 | app.run() 45 | endsnippet 46 | 47 | snippet prf "Print Statement f-string" b 48 | print(f"${1}") 49 | endsnippet 50 | 51 | 52 | snippet head "Network Request Header" b 53 | HEADERS = { 54 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36", 55 | "Content-Type": "application/json", 56 | } 57 | endsnippet 58 | 59 | snippet main "Python Main" b 60 | def ${2:functionName}(): 61 | $0 62 | 63 | 64 | if __name__ == '__main__': 65 | ${1:functionName}() 66 | endsnippet 67 | 68 | 69 | snippet jsonreadfile "Read JSON from file" b 70 | with open("${1}") as file: 71 | data = json.loads(file) 72 | endsnippet 73 | -------------------------------------------------------------------------------- /.config/git/config: -------------------------------------------------------------------------------- 1 | [includeIf "gitdir:~/Documents/work/"] 2 | path = ~/Documents/work/.gitconfig-work 3 | [includeIf "gitdir:~/Documents/personal/"] 4 | path = ~/Documents/personal/.gitconfig-personal 5 | [includeIf "gitdir:~/.dotfiles"] 6 | path = ~/Documents/personal/.gitconfig-personal 7 | [commit] 8 | template = $HOME/.gitmessage 9 | [core] 10 | editor = nano 11 | excludesFile = ~/.config/git/ignore 12 | [credential] 13 | helper = store 14 | [alias] 15 | wip = for-each-ref --sort='authordate:iso8601' --format=' %(color:green)%(authordate:relative)%09%(color:white)%(refname:short)' refs/heads 16 | # find file creation date: git cake 17 | cake = log --date=format:'%d %b %Y' --diff-filter=A --name-only --pretty='%n%C(yellow bold)🎂️ %ad%Creset by (%C(blue bold)%h%Creset)' 18 | # find commits that changed a file: git his 19 | his = log --follow --color=always --date=format:'%d %b, %Y' --pretty=format:'(%C(blue bold)%h%Creset)[%ad - %cn] %C(yellow bold)%s%Creset' 20 | # search code in commit history: git wot :function_name:filepath 21 | wot = log --date=format:'%d %b, %Y' --pretty='%n%C(yellow bold)📅️ %ad%Creset by (%C(green bold)%an%Creset) %C(cyan bold)%h%Creset' --graph -L 22 | # top 10 most edited files 23 | top10 = ! git log --pretty=format: --name-only | sort | uniq -c | sort -rg | head -10 24 | # generate changelog from commit messages 25 | chglg = "!f() { git log --since=2weeks --pretty=format:\"- [%h]($(git config --get remote.origin.url)/commit/%H) _%s_ (%cr) by (%an)\" | grep -v Merge > CHANGELOG.md;}; f" 26 | # git stash list with relative time 27 | sl = !git --no-pager stash list --pretty=format:'%C(bold blue)%gd%C(reset) %C(bold green) (%cr)%C(reset) - %s' 28 | # use custom script to browse git stash 29 | stach = !git-stash-checkout 30 | # single line log 31 | lo = !git --no-pager log --oneline 32 | 33 | [color] 34 | diff = auto 35 | ui = auto 36 | [push] 37 | autoSetupRemote = true 38 | [help] 39 | # run correct git command after 0.7 seconds 40 | autocorrect = 7 41 | [init] 42 | defaultBranch = main 43 | [gc] 44 | reflogExpireUnreachable = 90 45 | reflogExpire = 200 46 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/conform.lua: -------------------------------------------------------------------------------- 1 | -- Module for configuring the "conform" plugin for formatting using LSP 2 | 3 | return { 4 | "stevearc/conform.nvim", 5 | event = { "LspAttach", "BufReadPost", "BufNewFile" }, 6 | opts = { 7 | formatters_by_ft = { 8 | html = { "prettier" }, 9 | javascript = { "prettier" }, 10 | go = { "goimports-reviser", "golines", "gofmt" }, 11 | hcl = { "hclfmt" }, 12 | markdown = { "prettier" }, 13 | lua = { "stylua" }, 14 | scss = { "prettier" }, 15 | sh = { "shfmt" }, 16 | -- python = { "ruff_organize_imports", "ruff_format" }, 17 | typescript = { "prettier" }, 18 | vue = { "prettier" }, 19 | yaml = { "prettier" }, 20 | }, 21 | format_on_save = function(bufnr) 22 | local bufname = vim.api.nvim_buf_get_name(bufnr) 23 | 24 | -- Disable file formatting on any temporary buffer contents 25 | if bufname:match("/tmp/") then 26 | return 27 | else 28 | return { 29 | timeout_ms = 10000, 30 | lsp_fallback = true, 31 | } 32 | end 33 | end, 34 | }, 35 | config = function(_, opts) 36 | local conform = require("conform") 37 | 38 | -- Setup "conform.nvim" to work 39 | conform.setup(opts) 40 | 41 | -- Customise the default "prettier" command to format Markdown files as well 42 | conform.formatters.prettier = { 43 | prepend_args = { "--prose-wrap", "always" }, 44 | } 45 | 46 | -- Add proper indents to the formatted Shell files 47 | conform.formatters.shfmt = { 48 | prepend_args = { 49 | "--indent=4", 50 | "--binary-next-line", 51 | "--case-indent", 52 | "--space-redirects", 53 | "--keep-padding", 54 | }, 55 | } 56 | 57 | -- Format long lines in Go source code 58 | conform.formatters.golines = { 59 | prepend_args = { 60 | "--max-len=88", 61 | "--reformat-tags", 62 | "--shorten-comments", 63 | }, 64 | } 65 | 66 | -- Format the import statements in Go source code 67 | conform.formatters["goimports-reviser"] = { 68 | prepend_args = { 69 | -- FIXME: It removes "used" statements too!!!! 70 | -- "-rm-unused", -- Remove unused imports 71 | "-set-alias", -- Create aliases for versioned imports 72 | }, 73 | } 74 | end, 75 | dependencies = { "neovim/nvim-lspconfig" }, 76 | } 77 | -------------------------------------------------------------------------------- /.config/nvim/lazy-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "auto-save.nvim": { "branch": "main", "commit": "979b6c82f60cfa80f4cf437d77446d0ded0addf0" }, 3 | "blink.cmp": { "branch": "main", "commit": "bae4bae0eedd1fa55f34b685862e94a222d5c6f8" }, 4 | "conform.nvim": { "branch": "master", "commit": "9ddab4e14c44196d393a72b958b4da6dab99ecef" }, 5 | "fzf-lua": { "branch": "main", "commit": "5d2ba91230356dce4dac52df32ddc6cf5a940d56" }, 6 | "gitsigns.nvim": { "branch": "main", "commit": "6e3c66548035e50db7bd8e360a29aec6620c3641" }, 7 | "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, 8 | "lualine.nvim": { "branch": "master", "commit": "b8c23159c0161f4b89196f74ee3a6d02cdc3a955" }, 9 | "mason-tool-installer.nvim": { "branch": "main", "commit": "517ef5994ef9d6b738322664d5fdd948f0fdeb46" }, 10 | "mason.nvim": { "branch": "main", "commit": "7dc4facca9702f95353d5a1f87daf23d78e31c2a" }, 11 | "miramare": { "branch": "master", "commit": "04330816640c3162275d69e7094126727948cd0d" }, 12 | "neoscroll.nvim": { "branch": "master", "commit": "f957373912e88579e26fdaea4735450ff2ef5c9c" }, 13 | "neovim-ayu": { "branch": "master", "commit": "cc78e880cce5dfc1187d144ed7251c746feff259" }, 14 | "nvim-lspconfig": { "branch": "master", "commit": "0e268f5e0a398e77b2188aa94472b63daaa793b8" }, 15 | "nvim-tree.lua": { "branch": "master", "commit": "f4fa6ebd3cbfa299fb554766c56b2f7cc1233f27" }, 16 | "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, 17 | "nvim-web-devicons": { "branch": "master", "commit": "c2599a81ecabaae07c49ff9b45dcd032a8d90f1a" }, 18 | "palenight.vim": { "branch": "master", "commit": "5552a6349bcd927df9f17db34f017b77b963e503" }, 19 | "papercolor-theme": { "branch": "master", "commit": "0cfe64ffb24c21a6101b5f994ca342a74c977aef" }, 20 | "sonokai": { "branch": "master", "commit": "45481a54f9e44b8b9d89509df514b86bbf22aa07" }, 21 | "vim-floaterm": { "branch": "master", "commit": "fd4bdd66eca56c6cc59f2119e4447496d8cde2ea" }, 22 | "vim-gruvbox8": { "branch": "master", "commit": "9ac7db13bfe3cffb836f844e567efad71174238a" }, 23 | "vim-surround": { "branch": "master", "commit": "3d188ed2113431cf8dac77be61b842acb64433d9" }, 24 | "zen-mode.nvim": { "branch": "main", "commit": "863f150ca321b3dd8aa1a2b69b5f411a220e144f" } 25 | } 26 | -------------------------------------------------------------------------------- /snippets/sh.snippets: -------------------------------------------------------------------------------- 1 | snippet script "Shell Script Template" b 2 | 3 | SCRIPT_NAME="$0" 4 | # SCRIPT_URL="" 5 | TMP_FILE="/tmp/script.sh" 6 | VERSION="1.0" 7 | 8 | installed() { 9 | cmd=$(command -v "${1}") 10 | 11 | [[ -n "${cmd}" ]] && [[ -f "${cmd}" ]] 12 | return ${?} 13 | } 14 | 15 | die() { 16 | >&2 echo "Fatal: $*" 17 | exit 1 18 | } 19 | 20 | [[ "${BASH_VERSINFO[0]}" -lt 4 ]] && die "Bash >=4 required" 21 | 22 | deps=(fzf git awk xargs cut nl tput) 23 | for dep in "${deps[@]}"; do 24 | installed "${dep}" || die "Missing dependency: '${dep}'" 25 | done 26 | 27 | show_version() { 28 | printf "script version %s\n" "$VERSION" 29 | } 30 | 31 | print_help() { 32 | cat < "$TMP_FILE" 47 | NEW_VER=$(grep "^VERSION" "$TMP_FILE" | awk -F'[="]' '{print $3}') 48 | 49 | if [[ "$VERSION" < "$NEW_VER" ]]; then 50 | printf "Updating script \e[31;1m%s\e[0m -> \e[32;1m%s\e[0m\n" "$VERSION" "$NEW_VER" 51 | chmod +x "$TMP_FILE" 52 | # WIP 53 | if cp "$TMP_FILE" "$SCRIPT_NAME"; then printf "%s\n" "Done"; fi 54 | rm -f "$TMP_FILE" 55 | else 56 | printf "%s\n" "script is already at the latest version ($VERSION)" 57 | rm -f "$TMP_FILE" 58 | fi 59 | exit 0 60 | } 61 | 62 | main() { 63 | if [[ $# -gt 0 ]]; then 64 | local key="$1" 65 | case "$key" in 66 | --version|-v) 67 | show_version 68 | ;; 69 | --update|-u) 70 | update 71 | ;; 72 | --help|-h) 73 | print_help 74 | exit 75 | ;; 76 | *) 77 | printf "%s\n" "ERROR: Unrecognized argument $key" 78 | exit 1 79 | ;; 80 | esac 81 | else 82 | # do something 83 | fi 84 | } 85 | 86 | main "$@" 87 | endsnippet 88 | -------------------------------------------------------------------------------- /.config/karabiner/karabiner.json: -------------------------------------------------------------------------------- 1 | { 2 | "global": { 3 | "show_additional_menu_items": true, 4 | "show_profile_name_in_menu_bar": true 5 | }, 6 | "profiles": [ 7 | { 8 | "complex_modifications": { 9 | "rules": [ 10 | { 11 | "description": "Caps Lock to Escape on single press, Caps Lock on press and hold.", 12 | "manipulators": [ 13 | { 14 | "from": { 15 | "key_code": "caps_lock", 16 | "modifiers": { "optional": ["any"] } 17 | }, 18 | "to": [{ "key_code": "escape" }], 19 | "to_if_held_down": [{ "key_code": "caps_lock" }], 20 | "type": "basic" 21 | } 22 | ] 23 | } 24 | ] 25 | }, 26 | "devices": [ 27 | { 28 | "disable_built_in_keyboard_if_exists": true, 29 | "fn_function_keys": [ 30 | { 31 | "from": { "key_code": "f5" }, 32 | "to": [{ "key_code": "f5" }] 33 | } 34 | ], 35 | "identifiers": { 36 | "is_keyboard": true, 37 | "product_id": 20233, 38 | "vendor_id": 1008 39 | }, 40 | "ignore_vendor_events": true, 41 | "simple_modifications": [ 42 | { 43 | "from": { "key_code": "left_command" }, 44 | "to": [{ "key_code": "left_option" }] 45 | }, 46 | { 47 | "from": { "key_code": "left_option" }, 48 | "to": [{ "key_code": "left_command" }] 49 | } 50 | ] 51 | } 52 | ], 53 | "name": "Default", 54 | "selected": true, 55 | "virtual_hid_keyboard": { "keyboard_type_v2": "ansi" } 56 | }, 57 | { "name": "HP 350 Compact" } 58 | ] 59 | } -------------------------------------------------------------------------------- /.config/nvim/lua/utils.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | -- Utlity function to make autocommands easily 4 | M.autocmd = vim.api.nvim_create_autocmd 5 | 6 | -- Utlity function to make augroups more easily 7 | M.augroup = function(name) 8 | return vim.api.nvim_create_augroup("augroup" .. name, { clear = true }) 9 | end 10 | 11 | -- Utlity function to make keybind mappings easier & DRY 12 | M.map = function(mode, lhs, rhs, opts) 13 | local keys = require("lazy.core.handler").handlers.keys 14 | 15 | if not keys.active[keys.parse({ lhs, mode = mode }).id] then 16 | opts = opts or {} 17 | opts.silent = opts.silent ~= false 18 | vim.keymap.set(mode, lhs, rhs, opts) 19 | end 20 | end 21 | 22 | -- Setup highlight groups for Neovim easily 23 | M.highlight = vim.api.nvim_set_hl 24 | 25 | -- Check if the current directory is version-controlled using Git 26 | M.is_git_repo = function() 27 | local handle = io.popen("git rev-parse --is-inside-work-tree 2>/dev/null") 28 | local output = handle:read("*a") 29 | handle:close() 30 | 31 | if output:match("true") then 32 | return true 33 | else 34 | return false 35 | end 36 | end 37 | 38 | -- Check if the ".git" directory exists in the current directory 39 | M.has_git_dir = function() 40 | local handle = io.popen("ls -a 2>/dev/null") 41 | local output = handle:read("*a") 42 | handle:close() 43 | 44 | if output:match("%.git") then 45 | return true 46 | else 47 | return false 48 | end 49 | end 50 | 51 | -- Utlity to get current visual selection along with start and end positions 52 | M.get_visual_selection = function() 53 | -- Source: https://github.com/kristijanhusak/neovim-config/blob/a84dd777a3c202df880c075f89644b919f4efacb/nvim/lua/partials/utils.lua#L26-L38 54 | local s_start = vim.fn.getpos("'<") 55 | local s_end = vim.fn.getpos("'>") 56 | 57 | if s_start[2] == 0 and s_end[2] == 0 then 58 | -- fresh neovim boot, visual markers are empty 59 | return {}, 0, 0 60 | end 61 | 62 | local n_lines = math.abs(s_end[2] - s_start[2]) + 1 63 | local lines = vim.api.nvim_buf_get_lines(0, s_start[2] - 1, s_end[2], false) 64 | 65 | lines[1] = string.sub(lines[1], s_start[3], -1) 66 | 67 | if n_lines == 1 then 68 | lines[n_lines] = string.sub(lines[n_lines], 1, s_end[3] - s_start[3] + 1) 69 | else 70 | lines[n_lines] = string.sub(lines[n_lines], 1, s_end[3]) 71 | end 72 | --return table.concat(lines, "\n") 73 | return lines, s_start, s_end 74 | end 75 | 76 | -- Utlity function to trim a lua string 77 | M.trim = function(s) 78 | return (string.gsub(s, "^%s*(.-)%s*$", "%1")) 79 | end 80 | 81 | return M 82 | -------------------------------------------------------------------------------- /scripts/git/git-feed: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # A python utility to generate a feed of recently committed files in a git repository 4 | 5 | # TODO: Add Commit Author # 6 | # TODO: Add CLI flag to pass a custom git repo # 7 | # TODO: Check Valid .git repo # 8 | 9 | import subprocess as sp 10 | import pathlib 11 | import os 12 | import datetime 13 | from dateutil.parser import parse 14 | 15 | HEAD = """ 16 | 17 | 18 | """ 19 | 20 | FOOTER = """ 21 | 22 | """ 23 | 24 | # Assuming your current working dir is the repo 25 | repo_name = f"""{os.path.basename(os.getcwd())}.git""" 26 | last_build_date = datetime.datetime.now().strftime("%a, %d %b %Y") 27 | 28 | 29 | def get_recent_files(no_of_items): 30 | cmd = f"""git log --no-color -n {no_of_items} --date=rfc --diff-filter=A --name-status --pretty='%ad'""" 31 | 32 | result = sp.Popen(cmd, shell=True, stdout=sp.PIPE, stderr=sp.PIPE) 33 | out, err = result.communicate() 34 | clean_output = out.decode("utf-8").replace("A\t", "").split("\n") 35 | clean_output = list(filter(lambda x: x != "", clean_output)) 36 | 37 | files = [] 38 | for item in clean_output: 39 | if is_valid(item): 40 | date = item 41 | elif pathlib.Path(item).exists(): 42 | entry = item, date 43 | files.append(entry) 44 | return files 45 | 46 | 47 | def is_valid(date): 48 | try: 49 | if isinstance(parse(date), datetime.datetime): 50 | return True 51 | except ValueError: 52 | return False 53 | 54 | 55 | def get_repo_origin(): 56 | repo_origin = "git config --get remote.origin.url" 57 | result = sp.Popen(repo_origin, shell=True, stdout=sp.PIPE, stderr=sp.PIPE) 58 | result, err = result.communicate() 59 | return result.decode("utf-8").strip() 60 | 61 | 62 | if __name__ == "__main__": 63 | # use this to configure no of items in feed.xml 64 | FEED_ITEMS = 10 65 | files = get_recent_files(FEED_ITEMS) 66 | with open("feed.xml", "w") as feed: 67 | feed.write(HEAD) 68 | feed.write( 69 | f"""{repo_name}\n{get_repo_origin()}\n""" 70 | ) 71 | feed.write( 72 | f"""Recently committed files in {repo_name}\n""" 73 | ) 74 | feed.write(f"""{last_build_date}""") 75 | for item in files: 76 | feed.write("""\n""") 77 | feed.write(f"""{item[0]}\n""") 78 | feed.write(f"""{item[1]}\n""") 79 | feed.write("""\n""") 80 | feed.write(FOOTER) 81 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/blink.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 'saghen/blink.cmp', 3 | 4 | lazy = false, 5 | 6 | -- use a release tag to download pre-built binaries 7 | version = '1.6.0', 8 | 9 | opts = { 10 | -- 'default' (recommended) for mappings similar to built-in completions (C-y to accept) 11 | -- 'super-tab' for mappings similar to vscode (tab to accept) 12 | -- 'enter' for enter to accept 13 | -- 'none' for no mappings 14 | -- 15 | -- All presets have the following mappings: 16 | -- C-space: Open menu or open docs if already open 17 | -- C-n/C-p or Up/Down: Select next/previous item 18 | -- C-e: Hide menu 19 | -- C-k: Toggle signature help (if signature.enabled = true) 20 | -- 21 | -- See :h blink-cmp-config-keymap for defining your own keymap 22 | keymap = { 23 | preset = 'super-tab' 24 | }, 25 | 26 | appearance = { 27 | -- 'mono' (default) for 'Nerd Font Mono' or 'normal' for 'Nerd Font' 28 | -- Adjusts spacing to ensure icons are aligned 29 | nerd_font_variant = 'mono' 30 | }, 31 | snippets = { 32 | -- Function to use when expanding LSP provided snippets 33 | expand = function(snippet) 34 | vim.snippet.expand(snippet) 35 | end, 36 | -- Function to use when checking if a snippet is active 37 | active = function(filter) 38 | return vim.snippet.active(filter) 39 | end, 40 | -- Function to use when jumping between tab stops in a snippet, where direction can be negative or positive 41 | jump = function(direction) 42 | vim.snippet.jump(direction) 43 | end 44 | }, 45 | 46 | -- (Default) Only show the documentation popup when manually triggered 47 | completion = { 48 | documentation = { 49 | auto_show = true, 50 | auto_show_delay = 250, 51 | window = { 52 | border = "rounded", 53 | winblend = 0 54 | } 55 | }, 56 | trigger = { 57 | prefetch_on_insert = true, 58 | show_on_keyword = true, 59 | show_on_insert = true 60 | }, 61 | accept = { 62 | create_undo_point = true 63 | } 64 | }, 65 | 66 | -- Default list of enabled providers defined so that you can extend it 67 | -- elsewhere in your config, without redefining it, due to `opts_extend` 68 | sources = { 69 | default = {'lsp', 'path', 'snippets', 'buffer'} 70 | } 71 | }, 72 | opts_extend = {"sources.default"} 73 | } 74 | -------------------------------------------------------------------------------- /scripts/aws/get-aws-token: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Script to get AWS session access tokens 4 | 5 | # Dependencies 6 | # 1. jq 7 | # 2. AWS CLI 8 | # 3. awk 9 | # 4. GNU date 10 | 11 | tmp_store="aws_token.txt" 12 | work_profile_path="$HOME/.work_profile" 13 | # the top line of the file should be the role ARN 14 | role=$(head -1 "$work_profile_path" | awk '{print $2}') 15 | 16 | # Maximum possible duration "36 hours" (129,600 seconds) 17 | # Read: https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html 18 | duration="1 hours" 19 | # convert to UNIX epoch and find appropriate expire limit 20 | duration_seconds=$(( $(gdate -d "$duration" +%s) - $(gdate +%s) )) 21 | AWS_REGION="us-west-1" 22 | now=$(gdate "+%d %B, %Y (%r)") 23 | 24 | 25 | _init(){ 26 | # unexport any existing keys 27 | unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN 28 | } 29 | 30 | _cleanup(){ 31 | # remove the temp file we created for storing keys 32 | rm "$tmp_store" 33 | } 34 | 35 | _update_vscode_launch(){ 36 | # Make sure that the launch.json file exists and it has an empty key "env" 37 | if test -f .vscode/launch.json;then 38 | launch_file_path=".vscode/launch.json" 39 | json=$(cat $launch_file_path) 40 | if jq ".configurations[].env += { AWS_ACCESS_KEY_ID: \"$1\", AWS_SECRET_ACCESS_KEY:\"$2\", AWS_SESSION_TOKEN: \"$3\", AWS_REGION: \"$AWS_REGION\" }" <<< "$json" > $launch_file_path; then 41 | printf "%s\n" "Updated VSCode Launch Config" 42 | else 43 | # rollback json in case of errors 44 | echo "$json" > $launch_file_path 45 | fi 46 | fi 47 | } 48 | 49 | _get_secrets() { 50 | if aws sts assume-role --role-arn "$role" --role-session-name AWSCLI-Session --duration-seconds $duration_seconds > "$tmp_store"; then 51 | AWS_ACCESS_KEY_ID=$(jq -r '.Credentials.AccessKeyId' < "$tmp_store") 52 | AWS_SECRET_ACCESS_KEY=$(jq -r '.Credentials.SecretAccessKey' < "$tmp_store") 53 | AWS_SESSION_TOKEN=$(jq -r '.Credentials.SessionToken' < "$tmp_store") 54 | EXPIRE_TIME=$(gdate --date="$(jq -r '.Credentials.Expiration' < "$tmp_store")" "+%d %B, %Y (%r)") 55 | 56 | { 57 | echo "# $role" 58 | echo "export AWS_ACCESS_KEY_ID=\"${AWS_ACCESS_KEY_ID}"\" 59 | echo "export AWS_SECRET_ACCESS_KEY=\"${AWS_SECRET_ACCESS_KEY}"\" 60 | echo "export AWS_SESSION_TOKEN=\"${AWS_SESSION_TOKEN}"\" 61 | echo "export AWS_REGION=\"${AWS_REGION}"\" 62 | 63 | echo "# Keys requested on $now" 64 | echo "# Keys valid till $EXPIRE_TIME" 65 | } > "$work_profile_path" 66 | 67 | printf "Expiring on %s\n" "$EXPIRE_TIME" 68 | printf "%s\n" "Exported as environment variables in $work_profile_path" 69 | 70 | _update_vscode_launch "${AWS_ACCESS_KEY_ID}" "${AWS_SECRET_ACCESS_KEY}" "${AWS_SESSION_TOKEN}" 71 | fi 72 | } 73 | 74 | _init 75 | printf "%s\n" "Getting AWS Session Token valid for $duration" 76 | _get_secrets 77 | _cleanup 78 | -------------------------------------------------------------------------------- /scripts/file/pdftrim: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Thanks to Mickaël 4 | # src: https://superuser.com/a/1217306 5 | 6 | # gs options: 7 | # -dPDFSETTINGS=/screen (screen-view-only quality, 72 dpi images) 8 | # -dPDFSETTINGS=/ebook (low quality, 150 dpi images) 9 | # -dPDFSETTINGS=/printer (high quality, 300 dpi images) 10 | # -dPDFSETTINGS=/prepress (high quality, color preserving, 300 dpi imgs) 11 | # -dPDFSETTINGS=/default (almost identical to /screen) 12 | 13 | pdftrim_usage() { 14 | printf "%s\n" 'Usage: pdftrim [input file] [output file] [screen|ebook|printer|prepress]' 15 | printf "\n%s\n\n" 'Example: pdftrim input.pdf output.pdf ebook' 16 | printf "%s\n" "Trim Options:" 17 | printf "%s\n" " screen - Screen-view-only quality, 72 dpi images" 18 | printf "%s\n" " ebook - Low quality, 150 dpi images" 19 | printf "%s\n" " printer - High quality, 300 dpi images" 20 | printf "%s\n" " prepress - High quality, color preserving, 300 dpi images" 21 | printf "%s\n" " default - Almost identical to /screen" 22 | } 23 | 24 | pdftrim() { 25 | if [ $# -lt 2 ]; then 26 | printf "%s\n" 'Error: Not enough arguments provided.' 27 | pdftrim_usage 28 | return 1 29 | fi 30 | if [ ! -f "$1" ]; then 31 | printf "%s\n" "Error: Input file '$1' does not exist." 32 | pdftrim_usage 33 | return 1 34 | fi 35 | if [ -z "$2" ]; then 36 | printf "%s\n" 'Error: Output file must be specified.' 37 | pdftrim_usage 38 | return 1 39 | fi 40 | 41 | # if not specified, use "screen" as default 42 | if [ -z "$3" ]; then 43 | printf "\n%s\n" 'Warning: No quality setting specified, using "screen" as default.' 44 | fi 45 | 46 | # gs -sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH -dPDFSETTINGS=/${3:-"screen"} -dCompatibilityLevel=1.4 -sOutputFile="$2" "$1" 47 | 48 | #TODO: ask user for gray scale or color conversion based on that try filters 49 | 50 | # [EXPERIMENT] Use the following command to build a opinionated PDF based on the input file 51 | 52 | # pdfimages -list file.pdf | awk '$1 ~ /^[0-9]+$/ && $7 != 1 { found=1 } END { print (found ? "Color" : "Grayscale") }' 53 | # Download pdfimages @ https://poppler.freedesktop.org/ 54 | 55 | # Docs: https://ghostscript.readthedocs.io/en/latest/VectorDevices.html#distiller-parameters 56 | 57 | gs -sDEVICE=pdfwrite \ 58 | -dCompatibilityLevel=1.4 \ 59 | -dPDFSETTINGS=/${3:-"screen"} \ 60 | -dNOPAUSE -dQUIET -dBATCH \ 61 | -dDownsampleColorImages=true \ 62 | -dColorImageResolution=320 \ 63 | -dColorImageDownsampleType=/Bicubic \ 64 | -dDownsampleMonoImages=true \ 65 | -dMonoImageResolution=1000 \ 66 | -dMonoImageDownsampleType=/Subsample \ 67 | -dDownsampleGrayImages=true \ 68 | -dGrayImageDownsampleType=/Bicubic \ 69 | -dGrayImageResolution=200 \ 70 | -sOutputFile="$2" "$1" 71 | } 72 | 73 | if ! command -v gs &>/dev/null; then 74 | printf "%s\n" 'Error: Ghostscript (gs) is not installed.' 75 | return 1 76 | fi 77 | 78 | pdftrim "$@" 79 | -------------------------------------------------------------------------------- /.config/nvim/init.lua: -------------------------------------------------------------------------------- 1 | -- ├── init.lua 2 | -- ├── lazy-lock.json 3 | -- └── lua 4 | -- ├── autocmds.lua 5 | -- ├── keymaps.lua 6 | -- ├── options.lua 7 | -- └── plugins 8 | -- ├── colorscheme.lua 9 | -- ├── conform.lua 10 | -- ├── devicons.lua 11 | -- ├── filetree.lua 12 | -- ├── floatterm.lua 13 | -- ├── gitsigns.lua 14 | -- ├── lualine.lua 15 | -- ├── neoscroll.lua 16 | -- ├── surround.lua 17 | -- ├── telescope.lua 18 | -- ├── treesitter.lua 19 | -- └── zen.lua 20 | -- Original Vimscript Config: https://github.com/Bhupesh-V/.Varshney/blob/master/init.vim 21 | -- References from: https://github.com/Jarmos-san/dotfiles 22 | 23 | -- TODO 24 | -- 1. Debugging for Typescript and Go 25 | -- 2. Formatters 26 | 27 | -- Path to install "lazy.nvim" at 28 | local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" 29 | 30 | if not (vim.uv or vim.loop).fs_stat(lazypath) then 31 | local lazyrepo = "https://github.com/folke/lazy.nvim.git" 32 | local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }) 33 | if vim.v.shell_error ~= 0 then 34 | vim.api.nvim_echo( 35 | { { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, { out, "WarningMsg" }, { "\nPress any key to exit..." } }, 36 | true, 37 | {} 38 | ) 39 | vim.fn.getchar() 40 | os.exit(1) 41 | end 42 | end 43 | 44 | -- Update the Neovim runtimepath for "lazy.nvim" to source the plugins. 45 | vim.opt.rtp:prepend(lazypath) 46 | 47 | -- Map the key to . 48 | vim.g.mapleader = " " 49 | 50 | -- Disable some in-built features which are unnecessary (and probably affects performance?) 51 | vim.g.loaded_python3_provider = 0 52 | vim.g.loaded_ruby_provider = 0 53 | vim.g.loaded_perl_provider = 0 54 | vim.g.loaded_node_provider = 0 55 | 56 | -- Install the necessary plugins through "lazy.nvim" 57 | require("lazy").setup("plugins", { 58 | defaults = { 59 | lazy = true, 60 | }, -- Make all plugins to be lazy-loaded. 61 | ui = { 62 | border = "rounded", -- Enable rounded borders for the "lazy.nvim" UI. 63 | }, 64 | performance = { 65 | rtp = { 66 | disabled_plugins = { -- Disable certain in-built plugins which are useful af. 67 | "gzip", 68 | "matchit", 69 | "matchparen", -- "tarPlugin", 70 | "tohtml", -- "tutor", 71 | -- "zipPlugin", 72 | "rplugin", 73 | "man", 74 | "spellfile", 75 | }, 76 | }, 77 | }, 78 | rocks = { 79 | enabled = false, 80 | }, 81 | change_detection = { 82 | -- enabled = false, -- disable config change detection notifications 83 | notify = false, -- also disables the annoying message 84 | }, 85 | }) 86 | 87 | -- Safely load the necessary user-defined Lua modules meant to customise Neovim. 88 | for _, module in ipairs({ "options", "autocmds", "keymaps", "extras" }) do 89 | local ok, error = pcall(require, module) 90 | 91 | if not ok then 92 | print("Error loading module: " .. error) 93 | end 94 | end 95 | 96 | --vim.cmd.colorscheme("ayu") 97 | vim.cmd.colorscheme("gruvbox8_hard") 98 | 99 | -- INFO: Enable an experimental fast module loader. See the PR for more information: 100 | -- https://github.com/neovim/neovim/pull/22668 101 | -- vim.loader.enable() 102 | -------------------------------------------------------------------------------- /scripts/git/git-prs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # FZF Wrapper over github CLI to interactively view PRs that modify a filepath 4 | 5 | 6 | # 1. Get local file path from the user 7 | # 2. Find all open PRs 8 | # 3. For files changed in each PR find PR which changes the user provided file path 9 | # 4. Output the PR (id, url) and its diff 10 | 11 | # TODO: how to provide permalink to diff on the pull-request (limited by github's API) 12 | # TODO: support for fetching closed/merged PRs as well (gh pr list --state all --limit 40), figure out merging json data 13 | 14 | set -e 15 | 16 | # Color definitions 17 | BOLD=$(tput bold) 18 | RESET=$(tput sgr0) 19 | BLUE_FG=$(tput setaf 87) 20 | ORANGE_FG=$(tput setaf 190) 21 | 22 | prs_count=0 23 | show_diff=0 24 | pr_fetch_limit=100 25 | all_open_prs="" 26 | total_prs="" 27 | 28 | 29 | git_file=$(git ls-files | fzf \ 30 | --prompt="Choose File: " \ 31 | --height 40% --reverse \ 32 | --header="Choose a file to find pull requests on github that modify it" 33 | ) 34 | 35 | 36 | get_diff() { 37 | printf "%s\n" "Getting diff for PR #$2" 38 | # filepath with escaped slashes / 39 | escaped_filepath=${1//\//\\/} 40 | gh pr diff --color always "$2" | sed -n "/diff --git a\/$escaped_filepath/d;/diff/q;p" 41 | printf "\n" 42 | } 43 | 44 | fetch_prs() { 45 | printf "%s\n\n" "Hold tight while we look for PRs ✋👀 that modify $BOLD$git_file$RESET" 46 | all_open_prs=$(gh pr list --limit $pr_fetch_limit --json number,title,url,files,author,baseRefName,headRefName) 47 | total_prs=$(jq length <<< "$all_open_prs") 48 | } 49 | 50 | find_files_prs(){ 51 | for (( pri=0; pri 6 | # Note that you will need commonmarker to render this md file (or just paste it in github readme) 7 | # 8 | 9 | import urllib.request 10 | import json, sys, os 11 | from datetime import datetime 12 | from collections.abc import Mapping 13 | 14 | HEADERS = {"User-Agent": "Mozilla/5.0"} 15 | 16 | 17 | def parse_link_header(link_header): 18 | header_links = link_header.split(",")[0].split(";") 19 | if header_links[1] == ' rel="next"': 20 | next_page = header_links[0] 21 | # yo why tf response headers are not normal ? 22 | next_page = next_page[1 : len(next_page) - 1] 23 | else: 24 | next_page = None 25 | 26 | return next_page 27 | 28 | 29 | def request(url): 30 | req = urllib.request.Request(url, headers=HEADERS) 31 | with urllib.request.urlopen(req) as response: 32 | res = json.loads(response.read()) 33 | if response.headers["link"] is not None: 34 | next_url = parse_link_header(response.headers["link"]) 35 | else: 36 | next_url = None 37 | 38 | return res, next_url 39 | 40 | 41 | def handle_pagination(url): 42 | res_list = [] 43 | while True: 44 | res, next_url = request(url) 45 | if isinstance(res, Mapping): 46 | # check if response is dict like 47 | res_list += res["items"] 48 | else: 49 | res_list += res 50 | if next_url is None: 51 | break 52 | url = next_url 53 | 54 | return res_list 55 | 56 | 57 | def get_user_repos(username): 58 | # eliminate contributions to self repos 59 | print("Fetching User Repositories ...") 60 | repos = handle_pagination( 61 | f"https://api.github.com/users/{username}/repos?type=owner&per_page=100" 62 | ) 63 | repo_list = [repo["url"] for repo in repos] 64 | 65 | return repo_list 66 | 67 | 68 | def get_user_prs(username): 69 | # get all pull requests of a user 70 | print(f"Fetching {username}'s Pull Requests ...") 71 | pull_requests = handle_pagination( 72 | f"https://api.github.com/search/issues?q=author%3A{username}+type%3Apr&per_page=100" 73 | ) 74 | return pull_requests 75 | 76 | 77 | def generate_report(repos, prs): 78 | totalPRs = 0 79 | with open(f"{user}-pull-requests.md", "w") as file: 80 | file.write( 81 | f"## [{user}](https://github.com/{user})'s open source contributions 🌟\n\n" 82 | ) 83 | file.write("
    ") 84 | for pr in prs: 85 | if pr["repository_url"] not in repos: 86 | totalPRs = totalPRs + 1 87 | created_date = datetime.strptime( 88 | pr["created_at"], "%Y-%m-%dT%H:%M:%SZ" 89 | ).strftime("%d %b, %Y") 90 | file.write("\n
  1. ") 91 | file.write( 92 | f"""{pr['title']} in {os.path.basename(pr['repository_url'])} on {created_date} \n\n""" 93 | ) 94 | file.write(f"
    Description\n\n") 95 | file.write(f"{pr['body']}\n
    \n\n") 96 | file.write("
  2. ") 97 | file.write("
\n\n") 98 | 99 | print(f"Total PRs: {totalPRs}") 100 | print(f"Saving context in {user}-pull-requests.md ✅") 101 | 102 | 103 | if __name__ == "__main__": 104 | if len(sys.argv) != 2: 105 | print("Needs a github username as an argument") 106 | exit() 107 | else: 108 | user = sys.argv[1] 109 | 110 | user_repos = get_user_repos(user) 111 | user_prs = get_user_prs(user) 112 | generate_report(user_repos, user_prs) 113 | -------------------------------------------------------------------------------- /snippets/go.snippets: -------------------------------------------------------------------------------- 1 | snippet json "Prettify/Indent JSON" b 2 | // import "encoding/json" 3 | func Indent(v interface{}) string { 4 | b, err := json.MarshalIndent(v, "", " ") 5 | if err != nil { 6 | return fmt.Sprintf("%#v", v) 7 | } 8 | return string(b) 9 | } 10 | endsnippet 11 | 12 | # Check Item in Slice/List 13 | snippet in 14 | func In(item $1, list []$2) bool { 15 | for _, b := range list { 16 | if b == item { 17 | return true 18 | } 19 | } 20 | return false 21 | } 22 | endsnippet 23 | 24 | # Insert a CLI Flag 25 | snippet flag "Insert a CLI flag" 26 | flag.StringVar(&${1:var}, "${2:flag}", "${3:defaultValue}", "${4:description}") 27 | endsnippet 28 | 29 | snippet go "Go Starter/Boilerplate" b 30 | package main 31 | 32 | import ( 33 | "fmt" 34 | ) 35 | 36 | func main() { 37 | fmt.Println("code") 38 | } 39 | endsnippet 40 | 41 | snippet post "Go HTTP POST Request" b 42 | // import bytes 43 | // impor net/http 44 | body := bytes.NewReader(payloadBytes) 45 | req, err := http.NewRequest("POST", "${1:URL}", body) 46 | if err != nil { 47 | fmt.Println(err) 48 | } 49 | // req.Header.Set("Content-Type", "application/json") 50 | 51 | resp, err := http.DefaultClient.Do(req) 52 | if err != nil { 53 | fmt.Println(err) 54 | } 55 | defer resp.Body.Close() 56 | endsnippet 57 | 58 | 59 | snippet get "Go HTTP GET Request" b 60 | req, err := http.NewRequest("GET", "${1:URL}", nil) 61 | // req.Header.Add("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36") 62 | resp, err := http.DefaultClient.Do(req) 63 | if err != nil { 64 | // err.Error() 65 | return 66 | } 67 | endsnippet 68 | 69 | 70 | snippet rjson "Read JSON from File to Go Map" b 71 | // import os 72 | // import "encoding/json" 73 | func readJSONToken(fileName string, filter func(map[string]interface{}) bool) []map[string]interface{} { 74 | file, _ := os.Open(fileName) 75 | defer file.Close() 76 | 77 | decoder := json.NewDecoder(file) 78 | 79 | filteredData := []map[string]interface{}{} 80 | 81 | // Read the array open bracket 82 | decoder.Token() 83 | 84 | data := map[string]interface{}{} 85 | for decoder.More() { 86 | decoder.Decode(&data) 87 | 88 | if filter(data) { 89 | filteredData = append(filteredData, data) 90 | } 91 | } 92 | 93 | return filteredData 94 | } 95 | endsnippet 96 | 97 | snippet rfile "Read entire file" 98 | content, err := os.ReadFile("${1:filepath}") 99 | if err != nil { 100 | fmt.Println("Err") 101 | } 102 | fmt.Println(string(content)) 103 | endsnippet 104 | 105 | snippet rcfile "Read file in chunks" b 106 | file, err := os.Open("${1:filepath}") 107 | if err != nil { 108 | fmt.Println("Error opening file!!!") 109 | } 110 | defer file.Close() 111 | 112 | // declare chunk size 113 | const maxSz = 4 114 | 115 | // create buffer 116 | b := make([]byte, maxSz) 117 | 118 | for { 119 | // read content to buffer 120 | readTotal, err := file.Read(b) 121 | if err != nil { 122 | if err != io.EOF { 123 | fmt.Println(err) 124 | } 125 | break 126 | } 127 | // print content from buffer 128 | fmt.Println(string(b[:readTotal])) 129 | } 130 | endsnippet 131 | 132 | snippet rfilel "Read file line by line / word by word" b 133 | file, err := os.Open("${1:filepath}") 134 | if err != nil { 135 | fmt.Println(err) 136 | } 137 | defer file.Close() 138 | 139 | // import bufio 140 | scanner := bufio.NewScanner(file) 141 | // scanner.Split(bufio.ScanWords) // use scanwords 142 | for scanner.Scan() { 143 | fmt.Println(scanner.Text()) 144 | } 145 | 146 | if err := scanner.Err(); err != nil { 147 | fmt.Println(err) 148 | } 149 | endsnippet 150 | 151 | snippet rjson "Read JSON file" b 152 | content, err := os.ReadFile("${1:filepath}") 153 | if err != nil { 154 | log.Fatal("Error opening file: ", err) 155 | } 156 | 157 | // unmarshall the data into `payload` 158 | var payload map[string]interface{} 159 | err = json.Unmarshal(content, &payload) 160 | if err != nil { 161 | log.Fatal("Error during Unmarshal(): ", err) 162 | } 163 | endsnippet 164 | 165 | 166 | snippet ctime "Current Time in Readable foramt" 167 | fmt.Printf("Current Time: %v\n", time.Now().Format(time.RFC850)) 168 | endsnippet 169 | -------------------------------------------------------------------------------- /.zshrc: -------------------------------------------------------------------------------- 1 | # If you come from bash you might have to change your $PATH. 2 | # export PATH=$HOME/bin:/usr/local/bin:$PATH 3 | 4 | # Path to your oh-my-zsh installation. 5 | export ZSH="/home/bhupesh/.oh-my-zsh" 6 | 7 | # Set name of the theme to load --- if set to "random", it will 8 | # load a random theme each time oh-my-zsh is loaded, in which case, 9 | # to know which specific one was loaded, run: echo $RANDOM_THEME 10 | # See https://github.com/robbyrussell/oh-my-zsh/wiki/Themes 11 | ZSH_THEME="agnoster" 12 | 13 | # Set list of themes to pick from when loading at random 14 | # Setting this variable when ZSH_THEME=random will cause zsh to load 15 | # a theme from this variable instead of looking in ~/.oh-my-zsh/themes/ 16 | # If set to an empty array, this variable will have no effect. 17 | # ZSH_THEME_RANDOM_CANDIDATES=( "robbyrussell" "agnoster" ) 18 | 19 | # Uncomment the following line to use case-sensitive completion. 20 | # CASE_SENSITIVE="true" 21 | 22 | # Uncomment the following line to use hyphen-insensitive completion. 23 | # Case-sensitive completion must be off. _ and - will be interchangeable. 24 | # HYPHEN_INSENSITIVE="true" 25 | 26 | # Uncomment the following line to disable bi-weekly auto-update checks. 27 | # DISABLE_AUTO_UPDATE="true" 28 | 29 | # Uncomment the following line to automatically update without prompting. 30 | # DISABLE_UPDATE_PROMPT="true" 31 | 32 | # Uncomment the following line to change how often to auto-update (in days). 33 | # export UPDATE_ZSH_DAYS=13 34 | 35 | # Uncomment the following line if pasting URLs and other text is messed up. 36 | # DISABLE_MAGIC_FUNCTIONS=true 37 | 38 | # Uncomment the following line to disable colors in ls. 39 | # DISABLE_LS_COLORS="true" 40 | 41 | # Uncomment the following line to disable auto-setting terminal title. 42 | # DISABLE_AUTO_TITLE="true" 43 | 44 | # Uncomment the following line to enable command auto-correction. 45 | ENABLE_CORRECTION="true" 46 | 47 | # Uncomment the following line to display red dots whilst waiting for completion. 48 | # COMPLETION_WAITING_DOTS="true" 49 | 50 | # Uncomment the following line if you want to disable marking untracked files 51 | # under VCS as dirty. This makes repository status check for large repositories 52 | # much, much faster. 53 | # DISABLE_UNTRACKED_FILES_DIRTY="true" 54 | 55 | # Uncomment the following line if you want to change the command execution time 56 | # stamp shown in the history command output. 57 | # You can set one of the optional three formats: 58 | # "mm/dd/yyyy"|"dd.mm.yyyy"|"yyyy-mm-dd" 59 | # or set a custom format using the strftime function format specifications, 60 | # see 'man strftime' for details. 61 | HIST_STAMPS="dd.mm.yyyy" 62 | 63 | # Would you like to use another custom folder than $ZSH/custom? 64 | # ZSH_CUSTOM=/path/to/new-custom-folder 65 | 66 | # Which plugins would you like to load? 67 | # Standard plugins can be found in ~/.oh-my-zsh/plugins/* 68 | # Custom plugins may be added to ~/.oh-my-zsh/custom/plugins/ 69 | # Example format: plugins=(rails git textmate ruby lighthouse) 70 | # Add wisely, as too many plugins slow down shell startup. 71 | plugins=(git) 72 | plugins=(zsh-autosuggestions) 73 | ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=2' 74 | source $ZSH/oh-my-zsh.sh 75 | 76 | # User configuration 77 | 78 | # export MANPATH="/usr/local/man:$MANPATH" 79 | 80 | # You may need to manually set your language environment 81 | # export LANG=en_US.UTF-8 82 | 83 | # Preferred editor for local and remote sessions 84 | # if [[ -n $SSH_CONNECTION ]]; then 85 | # export EDITOR='vim' 86 | # else 87 | # export EDITOR='mvim' 88 | # fi 89 | 90 | # Compilation flags 91 | # export ARCHFLAGS="-arch x86_64" 92 | 93 | # Set personal aliases, overriding those provided by oh-my-zsh libs, 94 | # plugins, and themes. Aliases can be placed here, though oh-my-zsh 95 | # users are encouraged to define aliases within the ZSH_CUSTOM folder. 96 | # For a full list of active aliases, run `alias`. 97 | # 98 | # Example aliases 99 | alias zshconfig="nvim ~/.zshrc" 100 | alias ohmyzsh="nvim ~/.oh-my-zsh" 101 | 102 | if [ -f ~/.bash_aliases ]; then 103 | . ~/.bash_aliases 104 | fi 105 | 106 | if [ -f ~/.bash_functions ]; then 107 | . ~/.bash_functions 108 | fi 109 | 110 | # To customize prompt, run `p10k configure` or edit ~/.p10k.zsh. 111 | [[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh 112 | 113 | export TERM=xterm-256color 114 | export DOT_REPO=https://github.com/Bhupesh-V/.Varshney 115 | export DOT_DEST=Documents 116 | export CDPATH=".:/home/bhupesh" 117 | -------------------------------------------------------------------------------- /scripts/github/contributors: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Find total contributors on all repositories of a github user (WIP) 4 | 5 | # TODO 6 | # 1. Add basic auth handlers (Done) 7 | # 2. Generate & write reports to a file 8 | # 3. Handle pagination (Done) 9 | # 4. Clean up error handling 10 | # 5. Fetch User's Organisation 11 | 12 | import urllib.parse 13 | import urllib.request 14 | import json 15 | import sys 16 | 17 | HEADERS = {"User-Agent": "Mozilla/5.0"} 18 | 19 | base_url = "https://api.github.com" 20 | repo_contributors_url = "" 21 | 22 | 23 | def parse_link_header(link_header): 24 | header_links = link_header.split(",")[0].split(";") 25 | if header_links[1] == ' rel="next"': 26 | next_page = header_links[0] 27 | # yo why tf response headers are normal ? 28 | next_page = next_page[1 : len(next_page) - 1] 29 | else: 30 | next_page = None 31 | 32 | return next_page 33 | 34 | 35 | def request(url): 36 | req = urllib.request.Request(url, headers=HEADERS) 37 | with urllib.request.urlopen(req) as response: 38 | res = json.loads(response.read().decode("utf-8")) 39 | if response.headers["link"] is not None: 40 | next_url = parse_link_header(response.headers["link"]) 41 | else: 42 | next_url = None 43 | 44 | return res, next_url 45 | 46 | 47 | # with open('contributors.json', 'w') as file: 48 | # json.dump(repo_list, file) 49 | 50 | 51 | def handle_pagination(url): 52 | res_list = [] 53 | while True: 54 | res, next_url = request(url) 55 | res_list += res 56 | if next_url is None: 57 | break 58 | url = next_url 59 | 60 | return res_list 61 | 62 | 63 | def find_user_repos(user): 64 | repo_list = [] 65 | try: 66 | repos = handle_pagination( 67 | f"{base_url}/users/{user}/repos?type=owner&per_page=100" 68 | ) 69 | for repo in repos: 70 | if repo["fork"] is False: 71 | repo_list.append(repo) 72 | except urllib.error.HTTPError as e: 73 | if e.code == 403: 74 | print("GitHub API rate limit exceeded. Only 60 requests/hour") 75 | exit() 76 | elif e.code == 404: 77 | print("User doesn't exist. Please re-check username") 78 | exit() 79 | else: 80 | pass 81 | 82 | return repo_list 83 | 84 | 85 | def find_contributors(repo_list, user): 86 | contributor_list = [] 87 | total_contributors = 0 88 | for repo in repo_list: 89 | try: 90 | contributors = handle_pagination( 91 | f"""{base_url}/repos/{user}/{repo["name"]}/contributors?per_page=100""" 92 | ) 93 | ccon = 0 94 | for con in contributors: 95 | if con["login"] != user and con["type"] != "Bot": 96 | ccon += 1 97 | print(f"""Contributors in {repo["name"]}: {ccon}""") 98 | except urllib.error.HTTPError as e: 99 | if e.code == 403: 100 | print("GitHub API rate limit exceeded. Only 60 requests/hour") 101 | exit() 102 | else: 103 | print(f"No contributors in {repo['name']}") 104 | pass 105 | total_contributors += ccon 106 | 107 | print(f"Total Contributors in {user}'s repos : {total_contributors} ✨") 108 | 109 | 110 | def find_first_contributors(contributors, user, user_repos): 111 | contributor_list = [] 112 | for contrib in contributors: 113 | first_pr, paginate = request( 114 | f"{base_url}/search/issues?q=author%3A{user}+is:pr&sort=created&order=asc" 115 | ) 116 | contributor_list.append(first_pr[0]) 117 | 118 | for pr in contributor_list: 119 | if pr["repository_url"] in user_repos: 120 | count += 1 121 | 122 | print( 123 | f"Total Contributors who made their first ever PR in {user}'s repos : {count}" 124 | ) 125 | 126 | 127 | if __name__ == "__main__": 128 | # yeah i will use argparse later 129 | if len(sys.argv) < 2: 130 | print("Please provide Github username") 131 | exit() 132 | elif len(sys.argv) == 3: 133 | HEADERS["Authorization"] = f"token {sys.argv[2]}" 134 | else: 135 | print("No token provided, requests will be limited by GitHub (60/hr)") 136 | 137 | user = sys.argv[1] 138 | print(f"Fetching {user}'s repositories ...") 139 | repositories = find_user_repos(user) 140 | print("Fetching contributors ...") 141 | find_contributors(repositories, user) 142 | -------------------------------------------------------------------------------- /.config/nvim/lua/plugins/lspconfig.lua: -------------------------------------------------------------------------------- 1 | -- Module for configuring the plugin responsible for handling LSP configurations 2 | return { 3 | -- Official plugin for more ease in configuring the in-built LSP client. 4 | "neovim/nvim-lspconfig", 5 | event = "LspAttach", 6 | init = function() 7 | vim.opt.updatetime = 250 -- Make Neovim to display the diagnostic hover window as fast as possible. 8 | -- Setup the LSP plugin to log only error messages else the log file grows too large eventually! 9 | vim.lsp.set_log_level(vim.log.levels.ERROR) 10 | vim.diagnostic.config({ 11 | underline = true, -- Show diagnostic errors with a squigly underline 12 | update_in_insert = true, -- Update the diagnostic message even when in Insert mode 13 | severity_sort = true, -- Configure Neovim to sort the error messages according to the severity. 14 | virtual_lines = true, -- Display prettier diagnostics on the buffer 15 | }) 16 | -- Configure the floating window containing information about the object under the cursor 17 | --vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { 18 | -- border = "double", -- Enable a distinguishable border for the window 19 | -- max_width = math.floor(vim.o.columns * 0.5), -- Cap the width of window at 50% of the terminal size 20 | --}) 21 | local hover_opts = { 22 | border = "double", 23 | max_width = math.floor(vim.o.columns * 0.5), 24 | } 25 | vim.lsp.buf.hover(hover_opts) 26 | end, 27 | config = function() 28 | local lspconfig = require("lspconfig") 29 | local map = require("utils").map 30 | local fzf = require("fzf-lua") 31 | 32 | require("lspconfig.ui.windows").default_options.border = "rounded" 33 | 34 | local on_attach = function(_, bufnr) 35 | map("n", "gd", fzf.lsp_definitions, { 36 | desc = "Jump to the object definition", 37 | }) 38 | map("n", "gD", fzf.lsp_declarations, { 39 | desc = "Jump to the object declaration", 40 | }) 41 | map("n", "gT", fzf.lsp_typedefs, { 42 | desc = "Get the type documentations", 43 | }) 44 | map("n", "gi", fzf.lsp_implementations, { 45 | desc = "Jump to the implementation", 46 | }) 47 | map("n", "gR", fzf.lsp_references, { 48 | desc = "Jump to the reference of the object", 49 | }) 50 | map("n", "gra", fzf.lsp_code_actions, { 51 | desc = "Open available code actions", 52 | }) 53 | map("n", "d", fzf.lsp_document_diagnostics, { 54 | desc = "Show diagnostics", 55 | }) 56 | map("n", "K", vim.lsp.buf.hover, { 57 | desc = "Open the documentations of the object", 58 | }) 59 | map("n", "", vim.lsp.buf.signature_help, { 60 | desc = "Get the help documentations", 61 | }) 62 | map("n", "gr", vim.lsp.buf.rename, { 63 | desc = "Rename the object under the cursor", 64 | }) 65 | map("n", "wa", vim.lsp.buf.add_workspace_folder, { 66 | desc = "Add workspace folder", 67 | }) 68 | map("n", "wr", vim.lsp.buf.remove_workspace_folder, { 69 | desc = "Remove workspace folder", 70 | }) 71 | map("n", "wl", vim.lsp.buf.list_workspace_folders, { 72 | desc = "List workspace folders", 73 | }) 74 | 75 | -- Configurations for showing diagnostics in a hover window instead. See the documentations at: 76 | -- https://github.com/neovim/nvim-lspconfig/wiki/UI-Customization#show-line-diagnostics-automatically-in-hover-window 77 | vim.api.nvim_create_autocmd("CursorHold", { 78 | buffer = bufnr, 79 | callback = function() 80 | local hover_window_configs = { 81 | focusable = false, 82 | close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" }, 83 | border = "rounded", 84 | source = "always", 85 | prefix = " ", 86 | scope = "cursor", 87 | } 88 | 89 | vim.diagnostic.open_float(nil, hover_window_configs) 90 | end, 91 | }) 92 | end 93 | -- Setup LSP servers 94 | -- Load LSP configurations using dofile (keeps your directory structure) 95 | local function load_lsp_config(config_name) 96 | local config_path = vim.fn.stdpath("config") .. "/lsp/" .. config_name .. ".lua" 97 | return dofile(config_path) 98 | end 99 | 100 | local servers = { 101 | gopls = load_lsp_config("gopls"), 102 | lua_ls = load_lsp_config("lua_ls"), 103 | ts_ls = load_lsp_config("typescript-language-server"), 104 | } 105 | 106 | for server, config in pairs(servers) do 107 | config.on_attach = on_attach 108 | lspconfig[server].setup(config) 109 | end 110 | end, 111 | dependencies = { -- This plugin needs to be loaded as well otherwise Neovim can't find the LSP binary on $PATH. 112 | "williamboman/mason.nvim", 113 | }, 114 | } 115 | -------------------------------------------------------------------------------- /scripts/github/gists: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Find all gists of a github user 4 | 5 | # Usage 6 | # Fetch only public gists 7 | # ./gists -u Bhupesh-V 8 | # Fetch all gists (including private) 9 | # ./gists -au Bhupesh-V 10 | 11 | 12 | import urllib.parse 13 | import urllib.request 14 | import json 15 | import argparse 16 | from pathlib import Path 17 | 18 | HEADERS = { 19 | "User-Agent": "Mozilla/5.0", 20 | "Accept": "application/vnd.github.v3+json", 21 | "Content-Type": "application/json", 22 | } 23 | 24 | BASE_URL = "https://api.github.com" 25 | 26 | 27 | def parse_link_header(link_header): 28 | header_links = link_header.split(",")[0].split(";") 29 | if header_links[1] == ' rel="next"': 30 | next_page = header_links[0] 31 | next_page = next_page[1 : len(next_page) - 1] 32 | else: 33 | next_page = None 34 | 35 | return next_page 36 | 37 | 38 | def make_request(url): 39 | req = urllib.request.Request(url, headers=HEADERS) 40 | with urllib.request.urlopen(req) as response: 41 | res = json.loads(response.read().decode("utf-8")) 42 | if response.headers["link"] is not None: 43 | next_url = parse_link_header(response.headers["link"]) 44 | else: 45 | next_url = None 46 | 47 | return res, next_url 48 | 49 | 50 | def request(url): 51 | res_list = [] 52 | while True: 53 | res, next_url = make_request(url) 54 | res_list += res 55 | if next_url is None: 56 | break 57 | url = next_url 58 | 59 | return res_list 60 | 61 | 62 | def find_all_gists(user, show_all): 63 | try: 64 | gists = request(f"{BASE_URL}/users/{user}/gists?per_page=100") 65 | if show_all: 66 | filtered_gists = gists 67 | else: 68 | filtered_gists = [gist for gist in gists if gist["public"]] 69 | 70 | except urllib.error.HTTPError as e: 71 | if e.code == 403: 72 | print("GitHub API rate limit exceeded. Only 60 requests/hour") 73 | exit() 74 | elif e.code == 404: 75 | print("User doesn't exist. Please verify username") 76 | exit() 77 | else: 78 | return None 79 | return filtered_gists 80 | 81 | 82 | def show_gists(gists): 83 | """ 84 | Output all gists in following format 85 | first filename or gist description, 86 | """ 87 | for gist in gists: 88 | if gist["description"] == "": 89 | first_filename = list(gist["files"].keys()) 90 | print(f"{first_filename[0]},", end="") 91 | else: 92 | print(f"{gist['description']},", end="") 93 | print(f"{gist['html_url']}") 94 | 95 | 96 | def read_token(): 97 | """ 98 | Read GitHub token either from .git-credentials or .env.json 99 | .git-credentials = https://username:TOKEN@github.com 100 | .env.json = {"GITHUB_TOKEN":"TOKEN"} 101 | """ 102 | env_path = Path.home() / ".env.json" 103 | credentials_file = Path.home() / ".git-credentials" 104 | if env_path.is_file(): 105 | secrets = json.loads(env_path.read_text()) 106 | if "GITHUB_TOKEN" in secrets: 107 | HEADERS["Authorization"] = f"token {secrets['GITHUB_TOKEN']}" 108 | else: 109 | print("GITHUB_TOKEN not found in .env.json") 110 | exit() 111 | elif credentials_file.is_file(): 112 | token_string = Path(credentials_file).read_text() 113 | # or use regex 114 | # token = re.search('[^https://].*:(.*)@', token_string).group(1) 115 | token = token_string.split(":")[2].split("@")[0] 116 | if token is None or token == "": 117 | print( 118 | "Error reading token from .git-credentials. Please check if the file has valid content" 119 | ) 120 | exit() 121 | HEADERS["Authorization"] = f"token {token}" 122 | else: 123 | print("No .env.json or .git-credentials file found in home directory") 124 | exit() 125 | 126 | 127 | if __name__ == "__main__": 128 | parser = argparse.ArgumentParser(description="List GitHub gists") 129 | parser.epilog = """Help/Bug Report: varshneybhupesh@gmail.com""" 130 | parser.add_argument("-u", "--user", type=str, help="Github Username", required=True) 131 | parser.add_argument( 132 | "-a", 133 | "--all", 134 | action="store_true", 135 | default=False, 136 | help="Fetch all gists", 137 | ) 138 | args = parser.parse_args() 139 | 140 | read_token() 141 | gists = find_all_gists(args.user, args.all) 142 | show_gists(gists) 143 | # print(json.dumps(gists, indent = 4)) 144 | -------------------------------------------------------------------------------- /scripts/git/git-worktree-all: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # FZF Wrapper over git to interactively work with git worktrees 4 | # Automate your git worktrees create & switch lifecycle 5 | 6 | # Dependencies: 7 | # 1. FZF 8 | # 2. Bash>=4 9 | # 3. Basic Utils: AWK, dirname, basename, grep, column, comm 10 | 11 | # READ BEFORE USE 12 | # 13 | # This script assumes the following git worktree flow 14 | # 15 | # SOME_DIRECTORY 16 | # │ 17 | # ├────beepbop (main git repository or main worktree) 18 | # │ │ 19 | # │ ├────.git (dir) 20 | # │ │ 21 | # │ └────README.md 22 | # │ 23 | # └────beepbop-worktrees (all linked worktrees) 24 | # │ 25 | # ├────a1 (linked worktree) 26 | # │ │ 27 | # │ ├────.git (file) 28 | # │ │ 29 | # │ └────README.md 30 | # └────a2 (linked worktree) 31 | # │ 32 | # ├────.git (file) 33 | # │ 34 | # └────README.md 35 | 36 | # Installation & Usage: 37 | # 38 | # $ curl -s https://raw.githubusercontent.com/Bhupesh-V/.Varshney/master/scripts/git/git-worktree-all -o giw 39 | # 40 | # $ source giw 41 | # 42 | # TODO: set $GIT_WORK_TREE env variable 43 | # TODO: set config for core.worktree 44 | # TODO: highlight the main worktree branch? 45 | 46 | RESET=$(tput sgr0) 47 | BOLD=$(tput bold) 48 | 49 | create_worktree() { 50 | # avoid nesting of worktrees by switching to main worktree 😅 51 | switch_to_main_tree 52 | 53 | # TODO check if main worktree is in sync with remote 54 | common_dir=$(dirname "$(pwd)") 55 | git_main_dir=$(basename "$(pwd)") 56 | new_worktree="$common_dir/$git_main_dir-worktrees/$1" 57 | 58 | source_branch=$(git for-each-ref --format='%(refname:short)' refs/heads | fzf\ 59 | --prompt="Choose a source branch for $1: " \ 60 | --height 40% --reverse --ansi\ 61 | --header="Create a worktree from pre-existing branch. (Ctrl+C to use main)" | awk '{print $1}' 62 | ) 63 | 64 | if [[ -z $source_branch ]]; then 65 | git worktree add "$new_worktree" 66 | else 67 | # create worktree from custom branch 68 | if git branch "$1" "$source_branch"; then 69 | git worktree add "$new_worktree" "$1" 70 | fi 71 | fi 72 | 73 | find_copy_gitignored_paths "$new_worktree" 74 | 75 | printf "%s\n" "Switching to worktree, $BOLD$1${RESET}" 76 | switch_worktree "$1" 77 | } 78 | 79 | switch_worktree() { 80 | # switch current worktree in the terminal 81 | worktree=$(git worktree list | grep -m 1 -w "$1" | awk '{print $1}') 82 | 83 | cd "$worktree" || printf "%s\n" "Can't find the linked worktree" && return 84 | } 85 | 86 | switch_to_main_tree() { 87 | if file .git | grep -w "ASCII text" 1> /dev/null; then 88 | printf "%s" "Switching to main worktree: " 89 | linked_tree_path=$(cat .git | awk '{print $2}') 90 | # gitdir: SOME_PATH/.git/worktrees/PWD 91 | current_linked_tree=$(basename "$(pwd)") 92 | main_worktree_path=${linked_tree_path%.git/worktrees/$current_linked_tree} 93 | printf "%s\n" "$BOLD$main_worktree_path$RESET" 94 | 95 | cd "$main_worktree_path" || return 96 | 97 | # verify if we are in main worktree 98 | if file .git | grep -w ".git: directory" 1> /dev/null; then 99 | return 100 | else 101 | printf "%s\n" "Failed to switch to main worktree" 102 | exit 1 103 | fi 104 | fi 105 | } 106 | 107 | # copy any gitignored paths to a worktree 108 | # Good for copying paths like .vscode/, .env 109 | find_copy_gitignored_paths() { 110 | 111 | # Get all the files which are tracked 112 | tracked_files=$(git ls-tree --name-only $(git branch --show-current) > /tmp/tracked_files) 113 | # Get list of all files in repository, hidden or not 114 | all_filepaths=$(find . -mindepth 1 -maxdepth 1 -mtime -14 -not -path "./.git" -printf '%f\n' > /tmp/all_files) 115 | # Difference b/w these 2 lists 116 | difference=$(comm -23 <(sort /tmp/all_files) <(sort /tmp/tracked_files)) 117 | 118 | [[ -z $difference ]] && return 119 | 120 | # Ask the user what they want to copy 121 | readarray -t choice_paths_to_copy < <(printf "%s" "$difference" | fzf \ 122 | --prompt="Choose filepaths to copy (TAB to select): " \ 123 | --height 40% --reverse --multi \ 124 | --header="These files are ignored by git while creating a worktree (Ctrl+C to skip)" 125 | ) 126 | 127 | [[ -z $choice_paths_to_copy ]] && return 128 | 129 | # Copy the choosen files 130 | for ignored_file in "${choice_paths_to_copy[@]}" 131 | do 132 | if cp -r "$ignored_file" "$new_worktree"; then 133 | printf "%s\n" "Copied $BOLD$ignored_file$RESET to worktree" 134 | fi 135 | done 136 | 137 | } 138 | 139 | init_worktree_menu() { 140 | # list available branches that have a worktree associated with them 141 | # in any case the default tree with "main" branch is printed 142 | 143 | worktree=$( 144 | git for-each-ref --color=always \ 145 | --format='%(if)%(worktreepath)%(then)%(color:bold)%(refname:short)%(color:reset) [%(color: bold 154)%(objectname:short)%(color:reset)] %(color:bold 208)%(align:63,left)%(worktreepath)%(end)%(color:reset) %(end)' |\ 146 | column -t | fzf \ 147 | --prompt="Choose a Worktree or Create One: " \ 148 | --height 40% --reverse --exact --ansi\ 149 | --header="If a worktree doesn't exist, git will create it for you." \ 150 | --bind=enter:replace-query+print-query | awk '{print $1}' 151 | ) 152 | 153 | [[ -z $worktree ]] && return 154 | 155 | # find existing worktrees once again 156 | available_worktrees=$(git worktree list | awk '{print $3}' | tr -d "[]") 157 | 158 | if grep -w "$worktree" <<< $available_worktrees 1> /dev/null; then 159 | switch_worktree "$worktree" 160 | else 161 | printf "%s\n" "Worktree named ${BOLD}$worktree${RESET} doesn't exist. Creating one..." 162 | create_worktree $worktree 163 | fi 164 | } 165 | 166 | init_worktree_menu 167 | -------------------------------------------------------------------------------- /scripts/github/bkp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # File Backup as Gist 4 | # Script to backup files as a GitHub Gist with 0 dependency 5 | 6 | # Usage: 7 | # 1. Make sure you have a Personal Access Token with Gist Scope 8 | # 2. Create a file named .env.json in your home directory with contents: 9 | # {"GITHUB_TOKEN": "" } 10 | # Alternatively you can check if a .git-credentials file exists in your $HOME. 11 | # The script will automatically read it from there 12 | # 3. Run script: ./bkp 13 | 14 | import urllib.request 15 | import json 16 | import os 17 | import re 18 | import argparse 19 | from datetime import datetime 20 | from pathlib import Path 21 | 22 | HEADERS = { 23 | "Accept": "application/vnd.github.v3+json", 24 | "Content-Type": "application/json", 25 | } 26 | base_url = "https://api.github.com" 27 | 28 | # By default upload gist as a Secret 29 | content = { 30 | "description": "", 31 | "public": False, 32 | # "files": {"test": {"content": "# title"}}, 33 | } 34 | 35 | 36 | 37 | def request(url, data=None, method=None): 38 | if method == "PATCH": 39 | req = urllib.request.Request(url, data=data, headers=HEADERS) 40 | req.get_method = lambda: "PATCH" 41 | elif method == "DELETE": 42 | req = urllib.request.Request(url, headers=HEADERS) 43 | req.get_method = lambda: "DELETE" 44 | elif method == "POST": 45 | req = urllib.request.Request(url, data=data, headers=HEADERS) 46 | else: 47 | req = urllib.request.Request(url, headers=HEADERS) 48 | try: 49 | with urllib.request.urlopen(req) as response: 50 | res = json.loads(response.read().decode("utf-8")) 51 | if response.headers["link"] is not None: 52 | next_url = parse_link_header(response.headers["link"]) 53 | else: 54 | next_url = None 55 | except urllib.error.URLError as e: 56 | print(e.reason) 57 | exit() 58 | return res, response.code, next_url 59 | 60 | 61 | def parse_link_header(link_header): 62 | header_links = link_header.split(",")[0].split(";") 63 | if header_links[1] == ' rel="next"': 64 | next_page = header_links[0] 65 | # yo why tf response headers are normal ? 66 | next_page = next_page[1 : len(next_page) - 1] 67 | else: 68 | next_page = None 69 | 70 | return next_page 71 | 72 | 73 | def handle_pagination(url): 74 | res_list = [] 75 | while True: 76 | res, res_code, next_url = request(url) 77 | res_list += res 78 | if next_url is None: 79 | break 80 | url = next_url 81 | 82 | return res_list 83 | 84 | def get_backup(filename): 85 | # Get Gist id if we already have a backup 86 | print("📦 Checking for backup ...") 87 | res = handle_pagination(url=f"{base_url}/gists") 88 | for gist in res: 89 | if filename in gist["files"]: 90 | updated_date = datetime.strptime( 91 | gist["updated_at"], "%Y-%m-%dT%H:%M:%SZ" 92 | ).strftime("%d %b %Y") 93 | print(f"""✔️ Found File backup ({updated_date})""") 94 | gid = gist["id"] 95 | break 96 | gid = None 97 | return gid 98 | 99 | 100 | def read_token(): 101 | env_path = Path.home() / ".env.json" 102 | credentials_file = Path.home() / ".git-credentials" 103 | if env_path.is_file(): 104 | secrets = json.loads(env_path.read_text()) 105 | if "GITHUB_TOKEN" in secrets: 106 | HEADERS["Authorization"] = f"token {secrets['GITHUB_TOKEN']}" 107 | else: 108 | print("GITHUB_TOKEN not found in .env.json") 109 | exit() 110 | elif credentials_file.is_file(): 111 | print("Reading token from .git-credentials") 112 | token_string = Path(credentials_file).read_text() 113 | r = re.compile(".*github.com") 114 | token_list = list(filter(r.match, token_string.split("\n"))) 115 | token = token_list[0].split(":")[2].split("@")[0] 116 | HEADERS["Authorization"] = f"token {token}" 117 | else: 118 | print("No .env.json or .git-credentials file found in home directory") 119 | exit() 120 | 121 | 122 | def delete_gist(filepath): 123 | userfile = Path(filepath) 124 | gist_id = get_backup(userfile.name) 125 | 126 | print("🚮️ Purging Gist ...") 127 | res, code = request(f"{base_url}/gists/{gist_id}", method="DELETE") 128 | 129 | print(res, code) 130 | if code == 204: 131 | print("Backup Successfully Deleted") 132 | 133 | 134 | def controller(filepath): 135 | userfile = Path(filepath) 136 | content["files"] = {userfile.name: {"content": userfile.read_text()}} 137 | gist_id = get_backup(userfile.name) 138 | 139 | if gist_id is not None: 140 | print("📤 Updating ...") 141 | res, code, _ = request( 142 | f"{base_url}/gists/{gist_id}", json.dumps(content).encode("utf-8"), "PATCH" 143 | ) 144 | else: 145 | print(f"No backup found for file: {os.path.basename(filepath)}") 146 | print("Creating Backup ...") 147 | res, code, _ = request( 148 | f"{base_url}/gists", json.dumps(content).encode("utf-8"), "POST" 149 | ) 150 | if code == 200 or code == 201: 151 | print("Success! 😃") 152 | 153 | return res 154 | 155 | 156 | if __name__ == "__main__": 157 | parser = argparse.ArgumentParser(description="Backup text files as a GitHub Gist") 158 | parser.add_argument("filepath", type=str, help="Absolute file path") 159 | parser.add_argument( 160 | "-s", 161 | "--show-url", 162 | action="store_true", 163 | default=False, 164 | help="Show github gist url", 165 | ) 166 | parser.add_argument( 167 | "-d", 168 | "--delete", 169 | action="store_true", 170 | default=False, 171 | help="Delete Gist", 172 | ) 173 | args = parser.parse_args() 174 | 175 | read_token() 176 | 177 | if args.delete: 178 | delete_gist(args.filepath) 179 | else: 180 | data = controller(args.filepath) 181 | 182 | if args.show_url: 183 | print(f"""Gist url: {data["html_url"]}""") 184 | -------------------------------------------------------------------------------- /.config/nvim/lua/extras.lua: -------------------------------------------------------------------------------- 1 | local get_visual_selection = require("utils").get_visual_selection 2 | local trim = require("utils").trim 3 | 4 | -- Toggle transparent mode (make sure this is always below colorscheme setting) 5 | function ToggleTransparent() 6 | if vim.g.is_transparent == 0 then 7 | vim.cmd("hi Normal guibg=NONE ctermbg=NONE ctermfg=NONE guifg=NONE") 8 | vim.g.is_transparent = 1 9 | else 10 | vim.g.is_transparent = 0 11 | vim.o.background = "dark" 12 | end 13 | end 14 | vim.api.nvim_create_user_command("ToggleTransparent", ToggleTransparent, {}) 15 | 16 | -- Run command on the current line and paste its output in next line inside a markdown code block 17 | function AddCmdOutput() 18 | local line_num = vim.fn.line(".") 19 | local cmd = vim.fn.getline(".") 20 | local ok, cmd_output = pcall(vim.fn.systemlist, cmd) 21 | 22 | if not ok or not cmd_output then 23 | print("Not a command") 24 | return 25 | end 26 | 27 | vim.fn.append(line_num, "```") 28 | vim.fn.append(line_num + 1, cmd_output) 29 | vim.fn.append(line_num + 1 + #cmd_output, "```") 30 | end 31 | vim.api.nvim_create_user_command("AddCmdOutput", AddCmdOutput, {}) 32 | 33 | -- Auto pair brackets and stuff 34 | -- Helper function to eat whitespace characters 35 | local function eatchar(pat) 36 | local c = vim.fn.nr2char(vim.fn.getchar(0)) 37 | return (c:match(pat) and "") or c 38 | end 39 | 40 | -- Bracket pairs map 41 | local bracket_pairs = { 42 | ["("] = ")", 43 | ["{"] = "}", 44 | ["["] = "]", 45 | ['"'] = '"', 46 | ["'"] = "'", 47 | ["`"] = "`", 48 | ["<"] = ">", 49 | } 50 | -- Set keymaps dynamically 51 | for open, close in pairs(bracket_pairs) do 52 | vim.keymap.set("i", open, function() 53 | local _, col = unpack(vim.api.nvim_win_get_cursor(0)) 54 | local line = vim.api.nvim_get_current_line() 55 | 56 | -- Get chars before/after cursor 57 | local before = col > 0 and line:sub(col, col) or "" 58 | local after = line:sub(col + 1, col + 1) 59 | 60 | -- Only insert the pair if both before and after are non-whitespace chars 61 | if before:match("%S") or after:match("%S") then 62 | return open -- insert the typed char 63 | end 64 | return open .. close .. "" .. eatchar("%s") 65 | end, { silent = true, expr = true }) 66 | end 67 | 68 | local comment_chars = { 69 | -- languages with no special multi-line comment markers 70 | vim = { prefix = '"', suffix = "", isUnified = true }, 71 | html = { prefix = "", isUnified = true }, 72 | markdown = { prefix = "", isUnified = true }, 73 | css = { prefix = "/*", suffix = "*/", isUnified = true }, 74 | python = { prefix = "#", suffix = "", isUnified = true }, 75 | sh = { prefix = "#", suffix = "", isUnified = true }, 76 | yaml = { prefix = "#", suffix = "", isUnified = true }, 77 | graphql = { prefix = "#", suffix = "", isUnified = true }, 78 | toml = { prefix = "#", suffix = "", isUnified = true }, 79 | gitignore = { prefix = "#", suffix = "", isUnified = true }, 80 | elixir = { prefix = "#", suffix = "", isUnified = true }, 81 | -- languages with special multi-line comment markers 82 | go = { single = { prefix = "//", suffix = "" }, multi = { prefix = "/*", suffix = "*/" } }, 83 | javascript = { single = { prefix = "//", suffix = "" }, multi = { prefix = "/*", suffix = "*/" } }, 84 | typescript = { single = { prefix = "//", suffix = "" }, multi = { prefix = "/*", suffix = "*/" } }, 85 | lua = { single = { prefix = "--", suffix = "" }, multi = { prefix = "--[[", suffix = "]]" } }, 86 | } 87 | 88 | function ToggleComment() 89 | -- TODO: Set an undo point? 90 | -- TODO: [Optional] fix cursor position b/w toggles 91 | -- TODO: fix detection of comment markers in a combination of HTML/CSS/JS code. 92 | local ft = vim.bo.filetype 93 | if ft == nil or ft == "" then 94 | error("Not a valid filetype") 95 | end 96 | 97 | local comment = comment_chars[ft] 98 | if comment == nil then 99 | error("Comment toggle not supported for filetype:" .. ft) 100 | end 101 | 102 | local prefix, suffix 103 | local isUnified = false 104 | local lines, s_start, s_end = get_visual_selection() 105 | 106 | if comment["isUnified"] then 107 | -- Yeah, I know! 108 | isUnified = true 109 | end 110 | 111 | print(vim.fn.mode()) 112 | if #lines > 1 then 113 | -- its a visual selection 114 | 115 | local start_lnum = s_start[2] - 1 116 | local end_lnum = s_end[2] 117 | 118 | if start_lnum > end_lnum then 119 | start_lnum, end_lnum = end_lnum, start_lnum 120 | end 121 | 122 | -- TODO: fix for HTML 123 | if isUnified then 124 | prefix = comment["prefix"] 125 | suffix = comment["suffix"] 126 | 127 | local newLine 128 | 129 | for index, value in ipairs(lines) do 130 | if value ~= "" then 131 | -- remove prefix 132 | if string.sub(trim(value), 1, #prefix) == prefix then 133 | -- remove prefix 134 | newLine = string.sub(value, #prefix + 1) 135 | -- remove suffix 136 | newLine = string.sub(newLine, 1, #newLine - #suffix) 137 | lines[index] = newLine 138 | else 139 | lines[index] = prefix .. value .. suffix 140 | end 141 | end 142 | end 143 | else 144 | local currentfirstLine = lines[1] 145 | local currentLastLine = lines[#lines] 146 | 147 | prefix = comment["multi"]["prefix"] 148 | suffix = comment["multi"]["suffix"] 149 | 150 | local newFirstLine, newLastLine 151 | 152 | if 153 | string.sub(trim(currentfirstLine), 1, #prefix) == prefix 154 | and string.sub(trim(currentLastLine), -#suffix) == suffix 155 | then 156 | -- current line is already commented, un-comment it 157 | newFirstLine = string.sub( 158 | currentfirstLine, 159 | #prefix + 1 + (#currentfirstLine - #trim(currentfirstLine)), 160 | #currentfirstLine 161 | ) 162 | newLastLine = string.sub(currentLastLine, 1, #currentLastLine - #suffix) 163 | else 164 | newFirstLine = prefix .. currentfirstLine 165 | newLastLine = currentLastLine .. suffix 166 | end 167 | lines[1] = newFirstLine 168 | lines[#lines] = newLastLine 169 | end 170 | vim.api.nvim_buf_set_lines(0, start_lnum, end_lnum, false, lines) 171 | else 172 | -- Only support single line toggle on normal mode or visual mode with only single line selection 173 | local line = vim.api.nvim_get_current_line() 174 | local trimmed = trim(line) 175 | local newCurrentLine 176 | 177 | if isUnified then 178 | prefix = comment["prefix"] 179 | suffix = comment["suffix"] 180 | else 181 | prefix = comment["single"]["prefix"] 182 | suffix = comment["single"]["suffix"] 183 | end 184 | 185 | if string.sub(trimmed, 1, #prefix) == prefix then 186 | newCurrentLine = string.sub(line, #prefix + 1 + (#line - #trimmed), #line - #suffix) 187 | else 188 | newCurrentLine = prefix .. line .. suffix 189 | end 190 | vim.api.nvim_set_current_line(newCurrentLine) 191 | end 192 | end 193 | vim.api.nvim_create_user_command("ToggleComment", ToggleComment, {}) 194 | vim.keymap.set("v", "", ":lua ToggleComment()", { noremap = true, silent = true }) 195 | vim.keymap.set("n", "", ":lua ToggleComment()", { noremap = true, silent = true }) 196 | 197 | -- vim.keymap.set("v", "", ToggleComment, { noremap = true, silent = true }) 198 | 199 | -- Normal mode mapping that works on the *last* visual selection 200 | -- vim.keymap.set("n", "", "gvlua ToggleComment()", { noremap = true, silent = true }) 201 | 202 | function GotLife() 203 | local start_pos = vim.fn.getpos("v") 204 | local end_pos = vim.fn.getpos(".") 205 | print(vim.inspect({ start_pos, end_pos })) 206 | end 207 | vim.api.nvim_create_user_command("GotLife", GotLife, {}) 208 | -------------------------------------------------------------------------------- /scripts/shell/surf: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | surf: A standalone script to surf web (Powered by searx) 5 | 6 | Copyright © 2021 Bhupesh Varshney 7 | 8 | This program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see . 20 | 21 | """ 22 | 23 | import urllib.request 24 | import urllib.parse 25 | import json 26 | import platform 27 | import argparse 28 | from random import choice 29 | from pathlib import Path 30 | from sys import stdin 31 | from os import isatty, getenv 32 | 33 | HEADERS = { 34 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36", 35 | "Content-Type": "application/json", 36 | } 37 | 38 | USAGE = """surf\n 39 | (Assuming surf is in your current working directory) 40 | > For better experience, add surf to your PATH or move it to $HOME/.local/bin 41 | 42 | 1. Just run the script, without any arguments: 43 | $ ./surf 44 | 45 | 2. Show link description: 46 | $ ./surf -d 47 | 48 | 3. Provide search query as parameter: 49 | $ ./surf -dq "how to change the world" 50 | 51 | 4. You can also pipe data to surf ¯\_(ツ)_/¯: 52 | $ echo "search this" | ./surf 53 | 54 | 5. Use -c to specify search category (default: general): 55 | $ ./surf -c "videos" -sq "how to make a pizza" 56 | Other categories include: "news", "files", "images", "map" 57 | 58 | 6. Update instance cache: 59 | $ ./surf -udq "when is doomsday" 60 | 61 | 7. Show only top N results (--top): 62 | $ ./surf -t 5 -dq "check if key exists in map" 63 | """ 64 | 65 | # TODO: Use a priority based approach (account response time) while selecting a random instance # 66 | # TODO: Add option to use only 1 user-specified instance (--searx) # 67 | # TODO: Add option to show all instances in cache # 68 | # TODO: Automatically append "go" if the instance supports results from google # 69 | 70 | 71 | def read_cache(cache): 72 | return set(cache.read_text().splitlines()) 73 | 74 | 75 | def get_cache_path(): 76 | # searx instances cache path 77 | user_home = Path.home() 78 | cache_name = ".searx_instances" 79 | os_name = platform.system() 80 | 81 | if os_name == "Linux": 82 | xdg_cache_home = Path(getenv("XDG_CACHE_HOME", user_home / ".cache")) 83 | return xdg_cache_home / cache_name 84 | if os_name == "Darwin": 85 | return user_home / "Library" / "Caches" / cache_name 86 | return user_home / "AppData" / "Local" / "Temp" / cache_name 87 | 88 | 89 | class colors: 90 | """ 91 | Define your fav colors here 92 | """ 93 | 94 | CYAN = "\033[1;36m" 95 | GREEN = "\033[40;38;5;154m" 96 | # gray bg + orange fg 97 | TITLE_STYLE = "\033[;1m\033[38;5;220m\033[48;5;238m" 98 | RESET = "\033[m" 99 | BOLD = "\033[;1m" 100 | 101 | 102 | def request(url): 103 | """Send a GET to url""" 104 | req = urllib.request.Request(url, headers=HEADERS) 105 | try: 106 | with urllib.request.urlopen(req) as response: 107 | res = json.loads(response.read().decode("utf-8")) 108 | except urllib.error.URLError as e: 109 | return e.reason, e.code 110 | except urllib.error.HTTPError as e: 111 | return e.reason, e.code 112 | return res, response.code 113 | 114 | 115 | def update_instances_cache(): 116 | """ 117 | Check https://searx.space/ for exact count 118 | surf additionally ignores instances based on parameters like 119 | - HTTP Status Codes 120 | - Any reported Errors 121 | - Fishy Behaviour (e.g using analytics for user tracking) 122 | """ 123 | print("Updating cache ...", end="\r") 124 | data = request("https://searx.space/data/instances.json") 125 | instances = data[0]["instances"] 126 | with open(get_cache_path(), "w") as cache: 127 | for server in instances: 128 | if ( 129 | instances[server]["http"]["status_code"] == 200 130 | and instances[server]["http"]["error"] is None 131 | and not instances[server]["comments"] 132 | ): 133 | cache.write(f"{server}\n") 134 | return read_cache(get_cache_path()) 135 | 136 | 137 | def list_instances(): 138 | with open(get_cache_path(), "r") as cache: 139 | for server in cache: 140 | print(f"{server}", end="") 141 | 142 | 143 | def get_instances(): 144 | """ 145 | read searx instances cache 146 | """ 147 | instance_cache = get_cache_path() 148 | if instance_cache.is_file(): 149 | return read_cache(instance_cache) 150 | print("Searx Instances cache not found!") 151 | return update_instances_cache() 152 | 153 | 154 | def dont_hurt_instance(query, category): 155 | # searx is fighting to block bot traffic, we need to be nice 156 | # but we also need search results in case the user searches more frequently 157 | searx_instances = get_instances() 158 | overloaded_instance = set() 159 | print("Pinging a random instance ...", end="\r") 160 | while True: 161 | instance = choice(tuple(searx_instances)) 162 | current_instance = urllib.parse.urlparse(instance).netloc 163 | data, code = request( 164 | f"""{instance}search?q={urllib.parse.quote_plus(query)}&categories={category.lower()}&format=json""" 165 | ) 166 | if code == 429: 167 | overloaded_instance.add(instance) 168 | print( 169 | f"Oh Snap! {colors.BOLD}{current_instance}{colors.RESET} says {data} :(" 170 | ) 171 | searx_instances = searx_instances - overloaded_instance 172 | continue 173 | elif code == 200 and len(data["results"]) > 0: 174 | print( 175 | f"""Found {colors.BOLD}{len(data["results"])}{colors.RESET} results on {colors.BOLD}{current_instance}{colors.RESET}\n""" 176 | ) 177 | break 178 | return data 179 | 180 | 181 | def search(query, args): 182 | print(f"Searching for {colors.BOLD}{query}{colors.RESET}") 183 | data = dont_hurt_instance(query, args.category) 184 | 185 | if len(data["corrections"]) == 2: 186 | print( 187 | f"""Did you mean {colors.BOLD}{data["corrections"][1]}{colors.RESET}?\n""" 188 | ) 189 | 190 | if args.top is not None: 191 | top_results_count = args.top 192 | print(f"Showing only top {top_results_count} results\n") 193 | else: 194 | top_results_count = len(data["results"]) 195 | 196 | for res in data["results"][:top_results_count]: 197 | print(f"""{colors.BOLD}{colors.TITLE_STYLE} {res["title"]} {colors.RESET}""") 198 | if args.show_description and "content" in res: 199 | print(f"""\t{colors.GREEN}{res["content"]}{colors.RESET}""") 200 | print( 201 | f"{colors.BOLD}► ", 202 | f"""{colors.CYAN}{res["url"]}{colors.RESET}""", 203 | ) 204 | 205 | 206 | if __name__ == "__main__": 207 | is_pipe = not isatty(stdin.fileno()) 208 | parser = argparse.ArgumentParser(description="Surf Internet on Command line") 209 | parser.usage = USAGE 210 | parser.epilog = """Help/Bug Report: varshneybhupesh@gmail.com""" 211 | parser.add_argument( 212 | "-q", 213 | "--query", 214 | type=str, 215 | help="Search query", 216 | ) 217 | parser.add_argument( 218 | "-c", 219 | "--category", 220 | type=str, 221 | default="general", 222 | help="Search Category", 223 | ) 224 | parser.add_argument( 225 | "-t", 226 | "--top", 227 | type=int, 228 | help="Show only top N results", 229 | ) 230 | parser.add_argument( 231 | "-d", 232 | "--show-description", 233 | action="store_true", 234 | default=False, 235 | help="Show link description", 236 | ) 237 | parser.add_argument( 238 | "-u", 239 | "--update-cache", 240 | action="store_true", 241 | default=False, 242 | help="Update searx instances cache list", 243 | ) 244 | parser.add_argument( 245 | "-l", 246 | "--list-instances", 247 | action="store_true", 248 | default=False, 249 | help="List all available searx instances", 250 | ) 251 | args = parser.parse_args() 252 | 253 | if args.update_cache: 254 | update_instances_cache() 255 | exit() 256 | if args.list_instances: 257 | list_instances() 258 | exit() 259 | 260 | if is_pipe: 261 | query = stdin.read() 262 | elif not args.query: 263 | query = str(input("\nSearch 🔍️ : ")) 264 | else: 265 | query = args.query 266 | search(query, args) 267 | -------------------------------------------------------------------------------- /.nanorc: -------------------------------------------------------------------------------- 1 | ## Sample initialization file for GNU nano. 2 | ## 3 | ## Please note that you must have configured nano with --enable-nanorc 4 | ## for this file to be read! Also note that this file should not be in 5 | ## DOS or Mac format, and that characters specially interpreted by the 6 | ## shell should not be escaped here. 7 | ## 8 | ## To make sure an option is disabled, use "unset