├── dotfiles
├── .config
│ ├── git
│ │ ├── ignore
│ │ └── config
│ ├── nvim
│ │ ├── colors
│ │ │ ├── tansai.lua
│ │ │ └── shinkai.vim
│ │ ├── after
│ │ │ ├── ftplugin
│ │ │ │ ├── javascript.lua
│ │ │ │ ├── caddy.lua
│ │ │ │ ├── gosum.lua
│ │ │ │ ├── hcl.lua
│ │ │ │ ├── gomod.lua
│ │ │ │ ├── typescriptreact.lua
│ │ │ │ ├── astro.lua
│ │ │ │ ├── json.lua
│ │ │ │ ├── help.lua
│ │ │ │ ├── scss.lua
│ │ │ │ ├── sh.lua
│ │ │ │ ├── typst.lua
│ │ │ │ ├── dockerfile.lua
│ │ │ │ ├── query.lua
│ │ │ │ ├── terraform.lua
│ │ │ │ ├── yaml.lua
│ │ │ │ ├── lua.lua
│ │ │ │ ├── markdown.lua
│ │ │ │ ├── vue.lua
│ │ │ │ ├── go.lua
│ │ │ │ ├── typescript.lua
│ │ │ │ └── python.lua
│ │ │ └── queries
│ │ │ │ └── markdown
│ │ │ │ ├── injections.scm
│ │ │ │ └── highlights.scm
│ │ ├── skeletons
│ │ │ ├── component.tsx
│ │ │ ├── taskfile.yml
│ │ │ ├── bash.sh
│ │ │ ├── sfc.vue
│ │ │ ├── main.py
│ │ │ ├── dependabot.yml
│ │ │ ├── github-workflow.yml
│ │ │ ├── editorconfig.txt
│ │ │ ├── license.txt
│ │ │ └── readme.md
│ │ ├── lua
│ │ │ ├── plugins
│ │ │ │ ├── devicons.lua
│ │ │ │ ├── schemastore.lua
│ │ │ │ ├── gitsigns.lua
│ │ │ │ ├── neoscroll.lua
│ │ │ │ ├── luasnip.lua
│ │ │ │ ├── nvim-lint.lua
│ │ │ │ ├── colorscheme.lua
│ │ │ │ ├── notify.lua
│ │ │ │ ├── smartcolumn.lua
│ │ │ │ ├── lualine.lua
│ │ │ │ ├── telescope.lua
│ │ │ │ ├── treesitter.lua
│ │ │ │ ├── cmp.lua
│ │ │ │ ├── mason.lua
│ │ │ │ ├── conform.lua
│ │ │ │ ├── mini-nvim.lua
│ │ │ │ └── lspconfig.lua
│ │ │ ├── highlights.lua
│ │ │ ├── tansai.lua
│ │ │ ├── utils.lua
│ │ │ ├── terminal.lua
│ │ │ ├── options.lua
│ │ │ ├── keymaps.lua
│ │ │ ├── autocmds.lua
│ │ │ └── statusline.lua
│ │ ├── lsp
│ │ │ ├── terraformls.lua
│ │ │ ├── vale-ls.lua
│ │ │ ├── bashls.lua
│ │ │ ├── yamlls.lua
│ │ │ ├── tinymist.lua
│ │ │ ├── jsonls.lua
│ │ │ ├── cssls.lua
│ │ │ ├── dockerls.lua
│ │ │ ├── astro.lua
│ │ │ ├── lua_ls.lua
│ │ │ ├── pyright.lua
│ │ │ └── gopls.lua
│ │ ├── luasnippets
│ │ │ ├── vue.lua
│ │ │ ├── lua.lua
│ │ │ ├── python.lua
│ │ │ └── go.lua
│ │ ├── filetype.lua
│ │ ├── lazy-lock.json
│ │ └── init.lua
│ ├── pip
│ │ └── pip.conf
│ ├── flameshot
│ │ └── flameshot.ini
│ ├── bat
│ │ └── config
│ ├── gh
│ │ └── config.yml
│ ├── tmux
│ │ ├── statusline
│ │ │ ├── statusline.conf
│ │ │ └── battery-status
│ │ └── tmux.conf
│ ├── wezterm
│ │ └── wezterm.lua
│ └── starship
│ │ └── starship.toml
├── .vim
│ └── vimrc
├── .zsh
│ ├── functions
│ └── aliases
├── .ssh
│ └── config
├── .homebrew
│ └── linux.Brewfile
├── .local
│ └── bin
│ │ ├── music-sort
│ │ ├── tag
│ │ ├── update
│ │ └── mkblog
└── .zshrc
├── .stylua.toml
├── selene.toml
├── vim.toml
├── assets
├── neovim.png
├── starship.png
└── wezterm.png
├── .github
├── DISCUSSION_TEMPLATE
│ └── general.yml
├── ISSUE_TEMPLATE
│ ├── feature-enhancement.yml
│ ├── config.yml
│ └── bug-report.yml
├── dependabot.yml
├── stale.yml
├── workflows
│ ├── auto-dependabot.yaml
│ └── qa-checks.yml
├── SUPPORT.md
├── SECURITY.md
├── PULL_REQUEST_TEMPLATE.md
└── CONTRIBUTING.md
├── .editorconfig
├── .gitattributes
├── LICENSE
├── .pre-commit-config.yaml
├── .gitignore
├── README.md
└── bootstrap.sh
/dotfiles/.config/git/ignore:
--------------------------------------------------------------------------------
1 | *scratch*
2 |
--------------------------------------------------------------------------------
/.stylua.toml:
--------------------------------------------------------------------------------
1 | indent_type = "Spaces"
2 | indent_width = 2
3 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/colors/tansai.lua:
--------------------------------------------------------------------------------
1 | require("tansai").load()
2 |
--------------------------------------------------------------------------------
/selene.toml:
--------------------------------------------------------------------------------
1 | std="vim"
2 |
3 | [lints]
4 | mixed_table = "allow"
5 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/javascript.lua:
--------------------------------------------------------------------------------
1 | vim.treesitter.start()
2 |
--------------------------------------------------------------------------------
/vim.toml:
--------------------------------------------------------------------------------
1 | [selene]
2 | base = "lua51"
3 | name = "vim"
4 |
5 | [vim]
6 | any = true
7 |
--------------------------------------------------------------------------------
/assets/neovim.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jarmos-san/dotfiles/HEAD/assets/neovim.png
--------------------------------------------------------------------------------
/assets/starship.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jarmos-san/dotfiles/HEAD/assets/starship.png
--------------------------------------------------------------------------------
/assets/wezterm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jarmos-san/dotfiles/HEAD/assets/wezterm.png
--------------------------------------------------------------------------------
/dotfiles/.config/pip/pip.conf:
--------------------------------------------------------------------------------
1 | [global]
2 | require-virtualenv=true
3 | disable-pip-version-check=true
4 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/caddy.lua:
--------------------------------------------------------------------------------
1 | vim.treesitter.start() -- Start the Treesitter parsing process for Caddyfiles
2 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/gosum.lua:
--------------------------------------------------------------------------------
1 | -- Start the Treesitter parser for "go.sum" files
2 | vim.treesitter.start()
3 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/hcl.lua:
--------------------------------------------------------------------------------
1 | -- Start the Treesitter parsing process for HCL files
2 | vim.treesitter.start()
3 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/gomod.lua:
--------------------------------------------------------------------------------
1 | -- Start the Treesitter parsing process for "go.mod" files
2 | vim.treesitter.start()
3 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/queries/markdown/injections.scm:
--------------------------------------------------------------------------------
1 | ; extends
2 | ((inline) @_inline (#match? @_inline "^\(import\|export\)")) @tsx
3 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/queries/markdown/highlights.scm:
--------------------------------------------------------------------------------
1 | ; extends
2 | ((inline) @_inline (#match? @_inline "^\(import\|export\)")) @nospell
3 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/typescriptreact.lua:
--------------------------------------------------------------------------------
1 | vim.opt.iskeyword:append("-") -- Make Neovim recognise dash-seperated words as a single word
2 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/skeletons/component.tsx:
--------------------------------------------------------------------------------
1 | function SomeComponent() {
2 | return
Hello World!
;
3 | }
4 |
5 | export default SomeComponent;
6 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/devicons.lua:
--------------------------------------------------------------------------------
1 | -- Module for adding devicon support to Neovim
2 |
3 | return {
4 | "nvim-tree/nvim-web-devicons",
5 | name = "devicons",
6 | }
7 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/skeletons/taskfile.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 |
3 | tasks:
4 | build:
5 | description: Build the project
6 | cmds:
7 | - echo "Running build command..."
8 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/astro.lua:
--------------------------------------------------------------------------------
1 | -- Start the Treesitter parsing process
2 | vim.treesitter.start()
3 |
4 | -- Start the "astro" LSP server
5 | vim.lsp.enable("astro", true)
6 |
--------------------------------------------------------------------------------
/dotfiles/.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 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/skeletons/bash.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | # Add the rest of the contents for the script below this line
6 |
7 | echo "Hello World!"
8 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/terraformls.lua:
--------------------------------------------------------------------------------
1 | return {
2 | cmd = { "terraform-ls", "serve" },
3 | filetypes = { "terraform", "terraform-vars" },
4 | root_markers = { ".terraform", ".git" },
5 | }
6 |
--------------------------------------------------------------------------------
/dotfiles/.config/flameshot/flameshot.ini:
--------------------------------------------------------------------------------
1 | [General]
2 | copyAndCloseAfterUpload=true
3 | disabledTrayIcon=false
4 | drawColor=#ff0000
5 | drawThickness=0
6 | filenamePattern=%F%H%M
7 | startupLaunch=true
8 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/schemastore.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring the schemas for various JSON files
2 |
3 | return {
4 | "b0o/schemastore.nvim",
5 | event = "BufRead",
6 | ft = "json",
7 | }
8 |
--------------------------------------------------------------------------------
/dotfiles/.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 |
--------------------------------------------------------------------------------
/dotfiles/.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 |
--------------------------------------------------------------------------------
/dotfiles/.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 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/typst.lua:
--------------------------------------------------------------------------------
1 | -- Start the Treesitter parsing process
2 | vim.treesitter.start()
3 |
4 | -- Enable the "tinymist" LSP server for Typst files
5 | vim.lsp.enable("tinymist", true)
6 |
--------------------------------------------------------------------------------
/dotfiles/.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 | }
8 |
--------------------------------------------------------------------------------
/dotfiles/.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 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/vale-ls.lua:
--------------------------------------------------------------------------------
1 | -- Configurations for "vale-ls", the LSP for Vale (a linter for prose)
2 | return {
3 | cmd = { "vale-ls" },
4 | filetypes = { "markdown", "text", "rst" },
5 | root_markers = { ".vale.ini" },
6 | }
7 |
--------------------------------------------------------------------------------
/dotfiles/.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 |
--------------------------------------------------------------------------------
/.github/DISCUSSION_TEMPLATE/general.yml:
--------------------------------------------------------------------------------
1 | title: "[General Discussion] "
2 | labels: ["discussion"]
3 | body:
4 | - type: markdown
5 | attributes:
6 | value: Share your ideas or questions or random banter here!
7 | validations:
8 | required: true
9 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/skeletons/sfc.vue:
--------------------------------------------------------------------------------
1 |
2 | Hello World!
3 |
4 |
5 |
8 |
9 |
14 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/bashls.lua:
--------------------------------------------------------------------------------
1 | return {
2 | cmd = { "bash-language-server", "start" },
3 | filetypes = { "bash", "sh" },
4 | root_markers = { ".git" },
5 | settings = {
6 | bashIde = {
7 | globPattern = "*@(.sh|.inc|.bash|.command)",
8 | },
9 | },
10 | }
11 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/skeletons/main.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """The entrypoint file of the Python script."""
4 |
5 |
6 | def main() -> None:
7 | """Invoke this function as the entrypoint of the script."""
8 | pass
9 |
10 |
11 | if __name__ == "__main__":
12 | main()
13 |
--------------------------------------------------------------------------------
/dotfiles/.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 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-enhancement.yml:
--------------------------------------------------------------------------------
1 | name: Feature Enhancement
2 | description: Request or improve an existing feature
3 | labels: ["enhancement"]
4 | assignees:
5 | - Jarmos-san
6 | body:
7 | - type: textarea
8 | attributes:
9 | label: "Provide details of the feature enhancement"
10 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/yamlls.lua:
--------------------------------------------------------------------------------
1 | return {
2 | cmd = { "yaml-language-server", "--stdio" },
3 | filetypes = { "yaml" },
4 | root_markers = { ".git" },
5 | settings = {
6 | redhat = {
7 | telemetry = false,
8 | },
9 | schemas = require("schemastore").yaml.schemas(),
10 | validate = true,
11 | },
12 | }
13 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/skeletons/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | updates:
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | interval: "daily"
8 | time: "06:00"
9 | timezone: "Asia/Kolkata"
10 | commit-message:
11 | prefix: "🔀"
12 | labels:
13 | - "dependencies"
14 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/tinymist.lua:
--------------------------------------------------------------------------------
1 | -- LSP configurations for the "tinymist" LSP server to be used by Typst files
2 | -- TODO: Add the user commands to invoke some of the inbuilt tinymist commands
3 | return {
4 | cmd = { "tinymist" },
5 | filetypes = { "typst" },
6 | root_markers = { ".git" },
7 | settings = {
8 | formatterMode = "typstyle",
9 | },
10 | }
11 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/skeletons/github-workflow.yml:
--------------------------------------------------------------------------------
1 | name: GitHub Workflow Template
2 |
3 | on: [push]
4 |
5 | jobs:
6 | workflow-job:
7 | name: Sample GitHub Workflow
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Checkout Repository
11 | uses: actions/checkout@v3
12 |
13 | - name: Run "Hello World!"
14 | run: echo "Hello World!"
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 4
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.lua]
12 | indent_size = 2
13 |
14 | [*.py]
15 | indent_size = 4
16 |
17 | [*.{json,md,toml,yml,yaml}]
18 | indent_size = 2
19 |
20 | [*.{sh,bash_profile}]
21 | indent_size = 2
22 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/neoscroll.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring the plugin for smooth scrolling
2 |
3 | return {
4 | "karb94/neoscroll.nvim",
5 | event = { "BufRead", "BufNewFile" },
6 | opts = {
7 | respect_scrolloff = true,
8 | cursor_scrolls_alone = false,
9 | },
10 | config = function(_, opts)
11 | require("neoscroll").setup(opts)
12 | end,
13 | }
14 |
--------------------------------------------------------------------------------
/dotfiles/.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 |
--------------------------------------------------------------------------------
/dotfiles/.config/bat/config:
--------------------------------------------------------------------------------
1 | # Specify desired highlighting theme (e.g. "TwoDark"). Run `bat --list-themes`
2 | # for a list of all available themes
3 | --theme="gruvbox-dark"
4 |
5 | # Uncomment the following line if you are using less version >= 551 and want to
6 | # enable mouse scrolling support in `bat` when running inside tmux. This might
7 | # disable text selection, unless you press shift.
8 | --pager="less -R"
9 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/jsonls.lua:
--------------------------------------------------------------------------------
1 | local schemastore = require("schemastore")
2 |
3 | return {
4 | cmd = { "vscode-json-language-server", "--stdio" },
5 | filetypes = { "json", "jsonc" },
6 | init_options = {
7 | provideFormatter = true,
8 | },
9 | root_markers = { ".git" },
10 | settings = {
11 | json = {
12 | schemas = schemastore.json.schemas(),
13 | validate = { enable = true },
14 | },
15 | },
16 | }
17 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/cssls.lua:
--------------------------------------------------------------------------------
1 | return {
2 | cmd = { "vscode-css-language-server", "--stdio" },
3 | filetypes = { "css", "scss", "less" },
4 | init_options = {
5 | provideFormatter = true,
6 | },
7 | root_markers = { "package.json", ".git" },
8 | settings = {
9 | css = {
10 | validate = true,
11 | },
12 | less = {
13 | validate = true,
14 | },
15 | scss = {
16 | validate = true,
17 | },
18 | },
19 | }
20 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/luasnip.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring the Luasnip snippets engine
2 |
3 | return {
4 | "L3MON4D3/LuaSnip",
5 | event = "InsertEnter",
6 | build = "make install_jsregexp",
7 | opts = {
8 | region_check_events = "InsertEnter",
9 | delete_check_events = "InsertEnter",
10 | },
11 | config = function(_, opts)
12 | require("luasnip").setup(opts)
13 | require("luasnip.loaders.from_lua").load()
14 | end,
15 | }
16 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/lua.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring Lua specific buffer contents
2 |
3 | local autocmd = require("utils").autocmd
4 | local augroup = require("utils").augroup
5 |
6 | autocmd("BufWritePost", {
7 | desc = "Lint Lua files using Stylua",
8 | group = augroup("lint_lua_files"),
9 | callback = function()
10 | require("lint").try_lint()
11 | end,
12 | })
13 |
14 | -- Start the Treesitter parser process
15 | vim.treesitter.start()
16 |
--------------------------------------------------------------------------------
/dotfiles/.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 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/nvim-lint.lua:
--------------------------------------------------------------------------------
1 | -- Module to configure the plugin which handles the various linters used with the editor
2 |
3 | return {
4 | "mfussenegger/nvim-lint",
5 | event = { "BufReadPre", "InsertLeave", "BufNewFile", "LspAttach" },
6 | config = function()
7 | require("lint").linters_by_ft = {
8 | lua = { "selene" },
9 | sh = { "shellcheck" },
10 | python = { "ruff", "mypy" },
11 | ["yaml.ansible"] = { "ansible-lint", "yamllint" },
12 | yaml = { "yamllint" },
13 | }
14 | end,
15 | }
16 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | updates:
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | interval: "daily"
8 | time: "06:00"
9 | timezone: "Asia/Kolkata"
10 | commit-message:
11 | prefix: "🔀"
12 | labels:
13 | - "dependencies"
14 |
15 | - package-ecosystem: "pip"
16 | directory: "/"
17 | schedule:
18 | interval: "daily"
19 | time: "06:00"
20 | timezone: "Asia/Kolkata"
21 | commit-message:
22 | prefix: "🔀"
23 | labels:
24 | - "dependencies"
25 |
--------------------------------------------------------------------------------
/dotfiles/.vim/vimrc:
--------------------------------------------------------------------------------
1 | set background=dark
2 | set nocp
3 | set clipboard=unnamed
4 | set wildmenu
5 | set backspace=indent,eol,start
6 | set gdefault
7 | set encoding=utf-8 nobomb
8 | set number relativenumber
9 | set tabstop=2
10 | set hlsearch incsearch
11 | set ignorecase
12 | set noerrorbells
13 | set nostartofline
14 | set ruler
15 | set shortmess=atI
16 | set showcmd
17 | set scrolloff=6
18 |
19 | inoremap jk
20 | nnoremap :write!
21 | nnoremap :ggVG
22 | nnoremap
23 | nnoremap
24 |
25 | syntax on
26 |
27 | colorscheme slate
28 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/highlights.lua:
--------------------------------------------------------------------------------
1 | -- Custom highlights to override the highlights set by whatever colorscheme is used
2 | -- at any given moment
3 |
4 | local M = {}
5 |
6 | M.setup = function()
7 | -- Apply a black border around the completion menu
8 | vim.api.nvim_set_hl(0, "BlinkCmpMenuBorder", { fg = "#000000" })
9 |
10 | -- Apply whitish foreground to the selected item in the completion menu and a darker
11 | -- background to the background for better visibility
12 | vim.api.nvim_set_hl(0, "BlinkCmpMenuSelection", { fg = "#dce0dc", bg = "#434543", bold = true })
13 | end
14 |
15 | return M
16 |
--------------------------------------------------------------------------------
/dotfiles/.zsh/functions:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env zsh
2 |
3 | # This script contains a bunch of utility functions to make life on the terminal easier
4 |
5 | # Create a directory and then "cd" into
6 | mkc() {
7 | if [[ -n "$1" ]]; then
8 | mkdir --parents "$1" && cd "$1"
9 | else
10 | echo "usage: mkc "
11 | fi
12 | }
13 |
14 | # Stop and remove a running Docker Container
15 | dcs() {
16 | if [[ -n "$1" ]]; then
17 | docker container stop $1
18 | docker container remove $1 --volumes
19 | else
20 | echo "usage: dcs "
21 | fi
22 | }
23 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/colorscheme.lua:
--------------------------------------------------------------------------------
1 | return {
2 | "comfysage/evergarden",
3 | priority = 1000,
4 | opts = {
5 | theme = {
6 | variant = "fall",
7 | accent = "green",
8 | },
9 | editor = {
10 | transparent_background = false,
11 | sign = { color = "none" },
12 | float = {
13 | color = "mantle",
14 | invert_border = true,
15 | },
16 | completion = {
17 | color = "surface0",
18 | },
19 | },
20 | integrations = {
21 | blink_cmp = true,
22 | gitsigns = true,
23 | telescope = true,
24 | },
25 | },
26 | }
27 |
--------------------------------------------------------------------------------
/dotfiles/.ssh/config:
--------------------------------------------------------------------------------
1 | # Configurations for all other remote servers
2 | Host *
3 | AddKeysToAgent yes
4 | IdentitiesOnly yes
5 | PreferredAuthentications publickey
6 | Compression yes
7 | HashKnownHosts yes
8 | StrictHostKeyChecking ask
9 | ServerAliveInterval 20
10 | ServerAliveCountMax 3
11 | TCPKeepAlive yes
12 | PasswordAuthentication no
13 |
14 | # Configurations for SSH functionality on GitHub
15 | Host github.com
16 | HostName github.com
17 | User Jarmos-san
18 | IdentityFile ~/.ssh/id_ed25519
19 |
20 | Host plane
21 | HostName 130.61.29.84
22 | User ubuntu
23 | IdentityFile ~/.ssh/id_ed25519
24 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 |
3 | contact_links:
4 | - name: Community Support
5 | url: https://github.com/Jarmos-san/dotfiles/discussions
6 | about: Please ask and answer questions here.
7 |
8 | - name: Report Issues and/or Bugs
9 | url: https://github.com/Jarmos-san/dotfiles/issues
10 | about: Please report bugs & other issues here.
11 |
12 | - name: Security Policy
13 | url: https://github.com/Jarmos-san/dotfiles/security/policy
14 | about:
15 | Refer to the Security Policy to report security vulnerabilities or if you
16 | would like to know about how your personal information is used.
17 |
--------------------------------------------------------------------------------
/dotfiles/.config/gh/config.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | # What protocol to use when performing git operations. Supported values: ssh, https
4 | git_protocol: ssh
5 |
6 | # What editor gh should run when creating issues, pull requests, etc. If blank, will
7 | # refer to environment.
8 | editor: nvim
9 |
10 | # When to interactively prompt. This is a global config that cannot be overridden by
11 | # hostname. Supported values: enabled, disabled
12 | prompt: enabled
13 |
14 | # A pager program to send command output to, e.g. "less". Set the value to "cat" to
15 | # disable the pager.
16 | pager: bat
17 |
18 | # Aliases allow you to create nicknames for gh commands
19 | aliases:
20 | co: pr checkout
21 |
--------------------------------------------------------------------------------
/dotfiles/.homebrew/linux.Brewfile:
--------------------------------------------------------------------------------
1 | tap "eth-p/software"
2 | tap "go-task/tap"
3 | tap "homebrew/bundle"
4 | tap "xo/xo"
5 | tap "hashicorp/tap"
6 |
7 | brew "gcc"
8 | brew "btop"
9 | brew "cmatrix"
10 | brew "eza"
11 | brew "gcc@11"
12 | brew "gh"
13 | brew "httpie"
14 | brew "jq"
15 | brew "node"
16 | brew "neovim"
17 | brew "poetry"
18 | brew "pre-commit"
19 | brew "ripgrep"
20 | brew "selene"
21 | brew "starship"
22 | brew "vim"
23 | brew "zsh"
24 | brew "eth-p/software/bat-extras-batdiff"
25 | brew "go-task/tap/go-task"
26 | brew "xo/xo/usql"
27 | brew "hashicorp/tap/terraform"
28 | brew "hashicorp/tap/packer"
29 | brew "pnpm"
30 | brew "webp"
31 | brew "azure-cli"
32 | brew "tmux"
33 | brew "ansible"
34 | brew "typst"
35 | brew "uv"
36 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/notify.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring the notifications plugin
2 |
3 | return {
4 | -- UI plugin for showing notifications appropriately instead of taking up the message space
5 | "rcarriga/nvim-notify",
6 | event = "VeryLazy",
7 | init = function()
8 | -- Set Neovim to use 24-bit colours
9 | vim.opt.termguicolors = true
10 | end,
11 | config = function()
12 | local notify = require("notify")
13 |
14 | notify.setup({
15 | -- Configure the plugin to fade in/out w/o distractions
16 | stages = "fade",
17 |
18 | -- Add a "transparent" background to stop the plugin from complaining too much
19 | background_colour = "#000000",
20 | })
21 |
22 | vim.notify = notify
23 | end,
24 | }
25 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/luasnippets/vue.lua:
--------------------------------------------------------------------------------
1 | local luasnip = require("luasnip")
2 | local snippet = luasnip.snippet
3 | local insert_node = luasnip.insert_node
4 | local fmt = require("luasnip.extras.fmt").fmt
5 |
6 | return {
7 | -- Snippet to create the script template
8 | snippet(
9 | { trig = "script", desc = "Create a script block" },
10 | fmt(
11 | [[
12 |
15 | ]],
16 | { insert_node(1, "") }
17 | )
18 | ),
19 |
20 | -- Snippet for creating the style template
21 | snippet(
22 | { trig = "style", desc = "Create a style template block" },
23 | fmt(
24 | [[
25 |
28 | ]],
29 | { insert_node(1, "") }
30 | )
31 | ),
32 | }
33 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/dockerls.lua:
--------------------------------------------------------------------------------
1 | return {
2 | cmd = { "docker-langserver", "--stdio" },
3 | filetypes = { "dockerfile" },
4 | root_markers = { "Dockerfile" },
5 | settings = {
6 | docker = {
7 | languageServer = {
8 | formatter = {
9 | ignoreMultilineInstructions = false,
10 | },
11 | diagnostics = {
12 | deprecatedMaintainer = "warning",
13 | directiveCasing = "warning",
14 | emptyContinuationLine = "error",
15 | instructionCasing = "error",
16 | instructionCmdMultiple = "error",
17 | instructionEntrypointMultiple = "error",
18 | instructionHealthcheckMultiple = "error",
19 | instructionJSONInSingleQuotes = "error",
20 | },
21 | },
22 | },
23 | },
24 | }
25 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Common settings that generally should always be used with your language specific settings
2 |
3 | # Auto detect text files and perform LF normalization
4 | * text=auto
5 |
6 | #
7 | # The above will handle all files NOT found below
8 | #
9 |
10 | # Documents
11 | *.bibtex text diff=bibtex
12 | *.doc diff=astextplain
13 | *.DOC diff=astextplain
14 | *.docx diff=astextplain
15 | *.DOCX diff=astextplain
16 | *.dot diff=astextplain
17 | *.DOT diff=astextplain
18 | *.pdf diff=astextplain
19 | *.PDF diff=astextplain
20 | *.rtf diff=astextplain
21 | # Basic .gitattributes for a Vim repo.
22 | # Vim on Linux works with LF only, Vim on Windows works with both LF and CRLF
23 |
24 | # Source files
25 | # ============
26 | *.vim text eol=lf
27 | .vimrc text eol=lf
28 | .gvimrc text eol=lf
29 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/skeletons/editorconfig.txt:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: https://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | end_of_line = lf
9 | insert_final_newline = true
10 |
11 | # Matches multiple files with brace expansion notation
12 | # Set default charset
13 | [*.{js,py}]
14 | charset = utf-8
15 |
16 | # 4 space indentation
17 | [*.py]
18 | indent_style = space
19 | indent_size = 4
20 |
21 | # Tab indentation (no size specified)
22 | [Makefile]
23 | indent_style = tab
24 |
25 | # Indentation override for all JS under lib directory
26 | [lib/**.js]
27 | indent_style = space
28 | indent_size = 2
29 |
30 | # Matches the exact files either package.json or .travis.yml
31 | [{package.json,.travis.yml}]
32 | indent_style = space
33 | indent_size = 2
34 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 20
3 |
4 | # Number of days of inactivity before a stale issue is closed
5 | daysUntilClose: 7
6 |
7 | # Issues with these labels will never be considered stale
8 | exemptLabels:
9 | - pinned
10 |
11 | # Label to use when marking an issue as stale
12 | staleLabel: stale
13 |
14 | # Comment to post when marking an issue as stale. Set to `false` to disable
15 | markComment: >
16 | This issue has been automatically marked as stale because it has not had
17 | recent activity. It will be closed within a week if no further activity
18 | occurs. Thank you for your contributions.
19 |
20 | # Comment to post when closing a stale issue. Set to `false` to disable
21 | closeComment: >
22 | This thread will now be closed since it hasn't seen any activity for a week.
23 |
--------------------------------------------------------------------------------
/.github/workflows/auto-dependabot.yaml:
--------------------------------------------------------------------------------
1 | name: Dependabot Auto-Merge
2 |
3 | on: pull_request
4 |
5 | permissions:
6 | contents: write
7 | pull-requests: write
8 |
9 | jobs:
10 | dependabot:
11 | name: Dependabot
12 | runs-on: ubuntu-latest
13 | if: github.event.pull_request.user.login == 'dependabot[bot]'
14 | steps:
15 | - name: Fetch Dependabot Metadata
16 | id: metadata
17 | uses: dependabot/fetch-metadata@v2.4.0
18 | with:
19 | github-token: "${{ secrets.GITHUB_TOKEN }}"
20 |
21 | - name: Enable Auto-Merge
22 | if:
23 | contains(steps.metadata.outputs.dependency-names, 'dependencies') &&
24 | steps.metadata.outputs.update-type == 'version-update:semver-patch'
25 | env:
26 | PR_URL: ${{github.event.pull_request.html_url}}
27 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
28 | run: gh pr merge --auto --merge "$PR_URL"
29 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/vue.lua:
--------------------------------------------------------------------------------
1 | -- Folding configurations for Neovim
2 | if vim.api.nvim_buf_line_count(0) >= 100 then
3 | vim.o.foldmethod = "expr" -- Allow folding using the "nvim-treesitter" plugin
4 | vim.o.foldexpr = "nvim_treesitter#foldexpr()" -- Configure the folding algorithm to be from the plugin
5 | vim.o.foldlevel = 0 -- Configure the maximum indenting for the folding
6 | end
7 |
8 | vim.treesitter.start()
9 |
10 | -- TODO: Move this autocommand to its own module/package
11 | vim.api.nvim_create_autocmd("CursorHold", {
12 | buffer = vim.api.nvim_get_current_buf(),
13 | callback = function()
14 | local hover_window_configs = {
15 | focusable = false,
16 | close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" },
17 | border = "rounded",
18 | source = "always",
19 | prefix = " ",
20 | scope = "cursor",
21 | }
22 |
23 | vim.diagnostic.open_float(nil, hover_window_configs)
24 | end,
25 | })
26 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/astro.lua:
--------------------------------------------------------------------------------
1 | local get_typescript_server_path = function(root_dir)
2 | local project_roots = vim.fs.find("node_modules", { path = root_dir, upward = true, limit = math.huge })
3 | for _, project_root in ipairs(project_roots) do
4 | local typescript_path = project_root .. "/typescript"
5 | local stat = vim.loop.fs_stat(typescript_path)
6 | if stat and stat.type == "directory" then
7 | return typescript_path .. "/lib"
8 | end
9 | end
10 | return ""
11 | end
12 |
13 | return {
14 | before_init = function(_, config)
15 | if config.init_options and config.init_options.typescript and not config.init_options.typescript.tsdk then
16 | config.init_options.typescript.tsdk = get_typescript_server_path(config.root_dir)
17 | end
18 | end,
19 | cmd = { "astro-ls", "--stdio" },
20 | filetypes = { "astro" },
21 | init_options = {
22 | typescript = {},
23 | },
24 | root_markers = { "package.json", "tsconfig.json", "jsconfig.json", ".git" },
25 | }
26 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/go.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring Golang filetypes
2 |
3 | local autocmd = require("utils").autocmd
4 | local augroup = require("utils").augroup
5 | local map = require("utils").map
6 |
7 | autocmd("BufWritePost", {
8 | desc = "Format the buffer contents after save",
9 | group = augroup("format_go_files"),
10 | callback = function()
11 | require("lint").try_lint()
12 | end,
13 | })
14 |
15 | map("n", "", "terminal go run %")
16 |
17 | -- Configure the indent-based folds for Go buffers
18 | if vim.api.nvim_buf_line_count(0) >= 100 then
19 | vim.opt.foldmethod = "expr"
20 | vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
21 | vim.opt.foldlevel = 0 -- Start with folds closed
22 | vim.opt.foldcolumn = "auto" -- Show fold indicators on the left margin
23 | vim.opt.foldnestmax = 99 -- Maximum depth of folds
24 | end
25 |
26 | -- Start the Treesitter parsing process
27 | vim.treesitter.start()
28 |
29 | -- Start the "gopls" LSP server
30 | vim.lsp.enable("gopls", true)
31 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/luasnippets/lua.lua:
--------------------------------------------------------------------------------
1 | local luasnip = require("luasnip")
2 | local snippet = luasnip.snippet
3 | local insert_node = luasnip.insert_node
4 | local fmt = require("luasnip.extras.fmt").fmt
5 |
6 | return {
7 | snippet(
8 | { trig = "func", desc = "Create a Lua function" },
9 | fmt(
10 | [[
11 | local {1} = function({2})
12 | {3}
13 | end
14 | ]],
15 | {
16 | insert_node(1, "function_name"),
17 | insert_node(2, "args"),
18 | insert_node(3, ""),
19 | }
20 | )
21 | ),
22 |
23 | snippet(
24 | { trig = "req", desc = "Create a require statement" },
25 | fmt(
26 | [[
27 | local {1} = require('{2}')
28 | ]],
29 | { insert_node(1, ""), insert_node(2, "module_name") }
30 | )
31 | ),
32 |
33 | snippet(
34 | { trig = "if", desc = "Create an if statement" },
35 | fmt(
36 | [[
37 | if {1} then
38 | {2}
39 | end
40 | ]],
41 | { insert_node(1, "condition"), insert_node(2, "body") }
42 | )
43 | ),
44 | }
45 |
--------------------------------------------------------------------------------
/.github/SUPPORT.md:
--------------------------------------------------------------------------------
1 | # Dotfiles
2 |
3 | This repository hosts a couple of shell scripts for automating setting up a
4 | fresh new development environment on a system. Refer to the
5 | [README](../README.md) for more information on what all will be downloaded &
6 | installed on to your machine _automatically_.
7 |
8 | ## Contributing
9 |
10 | Please read [CONTRIBUTING](./CONTRIBUTING.md) guidelines for details on our code
11 | of conduct, and the process for submitting pull requests to us.
12 |
13 | ## Versioning
14 |
15 | The project is always under development & ever-changing according to my needs &
16 | requirements. Hence, I decided to not include versioning for the project, as
17 | such it's always tagged as `latest`.
18 |
19 | ## Authors
20 |
21 | - **Somraj Saha** - [Jarmos-san](https://github.com/jarmos-san)
22 |
23 | See also the list of
24 | [contributors](https://github.com/jarmos-san/dotfiles/contributors) who
25 | participated in this project.
26 |
27 | ## License
28 |
29 | This project is licensed under the GNU GPLv3.0 License - see the
30 | [LICENSE.md](./../LICENSE) file for details
31 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/after/ftplugin/typescript.lua:
--------------------------------------------------------------------------------
1 | -- Start the Treesitter parsing process for TypeScript files
2 | vim.treesitter.start()
3 |
4 | -- Folding configurations for Neovim
5 | if vim.api.nvim_buf_line_count(0) >= 100 then
6 | vim.o.foldmethod = "expr" -- Allow folding using the "nvim-treesitter" plugin
7 | vim.o.foldexpr = "nvim_treesitter#foldexpr()" -- Configure the folding algorithm to be from the plugin
8 | vim.o.foldlevel = 1 -- Configure the maximum indenting for the folding
9 | end
10 |
11 | vim.diagnostic.config({ virtual_text = true })
12 |
13 | -- TODO: Move this autocommand to its own module/package
14 | vim.api.nvim_create_autocmd("CursorHold", {
15 | buffer = vim.api.nvim_get_current_buf(),
16 | callback = function()
17 | local hover_window_configs = {
18 | focusable = false,
19 | close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" },
20 | border = "rounded",
21 | source = "always",
22 | prefix = " ",
23 | scope = "cursor",
24 | }
25 |
26 | vim.diagnostic.open_float(nil, hover_window_configs)
27 | end,
28 | })
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-Present Somraj Saha and contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/tansai.lua:
--------------------------------------------------------------------------------
1 | local M = {}
2 |
3 | -- Alias to the API for setting the syntax highlights
4 | local hl = vim.api.nvim_set_hl
5 |
6 | -- Table of colours
7 | local colours = {
8 | none = "none",
9 | grey = "#45413d",
10 | light_grey = "#6e6c69",
11 | white = "#ffffff",
12 | black = "#000000",
13 | blue = "blue",
14 | }
15 |
16 | M.load = function()
17 | -- Clear any syntax highlighting (if any) that exists
18 | if vim.g.colors_name then
19 | vim.cmd.hi("clear")
20 | end
21 |
22 | -- Set some basic configuration options for Neovim
23 | vim.g.colors_name = "tansai"
24 | vim.o.termguicolors = true
25 | vim.o.background = "dark"
26 |
27 | -- Basic highlighting unrelated to code (or syntax) highlights
28 | hl(0, "Normal", { bg = colours.none, fg = colours.none })
29 | hl(0, "NonText", { bg = colours.none, fg = colours.none })
30 | hl(0, "CursorLine", { bg = colours.grey, fg = colours.none })
31 | hl(0, "CursorLineNr", { bg = colours.grey, fg = colours.white })
32 | hl(0, "LineNr", { bg = colours.none, fg = colours.grey })
33 | hl(0, "Comment", { bg = colours.none, fg = colours.light_grey })
34 | end
35 |
36 | return M
37 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/skeletons/license.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Somraj Saha
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | **For any security concerns please refer to this.**
4 |
5 | This repository hosts the Shell scripts I use to handle creation/manipulation of
6 | the dotfiles on my personal development machines. When executed they download
7 | certain applications from the Internet & perform certain file manipulations.
8 | Hence use the scripts from this repository with discretion. The owner of this
9 | repository will not be held responsible for any damage and/or unintended actions
10 | to your personal development machine.
11 |
12 | But, if you're willing to use the scripts from this repository & find a bug or
13 | two, please report it to the owner immediately. You can drop an email or leave
14 | him a tweet at--[@Jarmosan](https:twitter.com/jarmosan).
15 |
16 | You can also open a PR if you think there's an urgent security concern. Please
17 | refer to the [Contributing Guidelines](./CONTRIBUTING.md) on how to contribute
18 | to the project.
19 |
20 | **_WARNING_**: Use the contents of this repository with care. They can change
21 | and/or manipulate stuff in your filesystem. **So know what you're doing before
22 | cloning this repository & using the scripts in it!**
23 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/smartcolumn.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring the colour column smartly
2 |
3 | return {
4 | "m4xshen/smartcolumn.nvim",
5 | event = "BufRead",
6 | opts = {
7 | disabled_filetypes = {
8 | "caddy",
9 | "checkhealth",
10 | "conf",
11 | "dosini",
12 | "dotenv",
13 | "gitattributes",
14 | "gitcommit",
15 | "gitconfig",
16 | "gitignore",
17 | "gitrebase",
18 | "gosum",
19 | "help",
20 | "json",
21 | "markdown",
22 | "mason",
23 | "mdx",
24 | "netrw",
25 | "lazy",
26 | "log",
27 | "lspinfo",
28 | "scss",
29 | "sh",
30 | "ministarter",
31 | "mermaid",
32 | "terraform",
33 | "text",
34 | "Trouble",
35 | "tmux",
36 | "toml",
37 | "typst",
38 | "zsh",
39 | },
40 | custom_colorcolumn = {
41 | lua = "120",
42 | dockerfile = "120",
43 | python = "88",
44 | yaml = "90",
45 | markdown = "80",
46 | typescriptreact = "81",
47 | rust = "100",
48 | go = "88",
49 | hcl = "120",
50 | jsonc = "90",
51 | vue = "89",
52 | },
53 | },
54 | }
55 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.yml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: File a bug report
3 | title: "[Bug]: "
4 | labels: ["bug"]
5 | assignees:
6 | - Jarmos-san
7 | body:
8 | - type: markdown
9 | attributes:
10 | value: |
11 | Thanks for taking the time to fill out this bug report!
12 | - type: textarea
13 | id: what-happened
14 | attributes:
15 | label: Explain the Bug
16 | description:
17 | Explain in details the bug you encountered and the expected behaviour.
18 | placeholder: Explain the bug and the intended behaviour in detail.
19 | value: "A bug happened!"
20 | validations:
21 | required: true
22 | - type: textarea
23 | id: logs
24 | attributes:
25 | label: Relevant log output
26 | description:
27 | Please copy and paste any relevant log output. This will be
28 | automatically formatted into code, so no need for backticks.
29 | render: Shell
30 | - type: textarea
31 | id: screenshots
32 | attributes:
33 | label: Share relevant screenshots, if possible
34 | description:
35 | Please share a screenshot or two, if possible for us to better
36 | understand the issue.
37 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | # Pull Request Template
2 |
3 | ## Description
4 |
5 | Please include a comprehensive summary of the change & how does the changes
6 | help. Also include relevant motivation and context. List any dependencies that
7 | are required for this change.
8 |
9 | ## Type of change
10 |
11 | Please delete options that are not relevant.
12 |
13 | - [ ] Bug fix (non-breaking change which fixes an issue)
14 | - [ ] New feature (non-breaking change which adds functionality)
15 | - [ ] Breaking change (fix or feature that would cause existing functionality to
16 | not work as expected)
17 | - [ ] This change requires a documentation update
18 |
19 | ## Is it Tested
20 |
21 | Have you tested it before making a PR?
22 |
23 | Does it work flawlessly on a Ubuntu Machine?
24 |
25 | - [ ] Yes
26 | - [ ] No
27 |
28 | **Test Configuration(s)**:
29 |
30 | - Ubuntu version:
31 | - Bash version:
32 | - Windows version:
33 |
34 | ## Checklist
35 |
36 | - [ ] My code follows the style guidelines of this project
37 | - [ ] I have performed a self-review of my own code
38 | - [ ] I have commented my code, particularly in hard-to-understand areas
39 | - [ ] My changes generate no new warnings
40 | - [ ] I have checked my code and corrected any misspellings
41 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/lualine.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring the statusline plugin - "lualine"
2 |
3 | return {
4 | "nvim-lualine/lualine.nvim",
5 | -- This needs to be loaded after the "VeryLazy" event otherwise an ugly
6 | -- unstyled statusline is created after Neovim startup
7 | event = "VeryLazy",
8 | opts = {
9 | -- Leaving an empty table renders the square-edged components, else the default angled ones are loaded
10 | section_separators = {},
11 | component_separator = "|",
12 | theme = "gruvbox",
13 | disabled_filetypes = {
14 | statusline = {
15 | "dashboard",
16 | "filesytem",
17 | "mason",
18 | "neo-tree",
19 | "neo-tree-popup",
20 | "null-ls-info",
21 | "lazy",
22 | "lspinfo",
23 | "ministarter",
24 | "TelescopePrompt",
25 | },
26 | },
27 | },
28 | config = function(_, opts)
29 | local sections = {
30 | -- Statusline components to showcase on the right-most end
31 | lualine_x = { "filetype" },
32 | lualine_y = { "progress" },
33 | lualine_z = { "location" },
34 | lualine_c = { -- INFO: This section shows the entire filepath relative to the project root
35 | { "filename", path = 1 },
36 | },
37 | }
38 |
39 | require("lualine").setup({ options = opts, sections = sections })
40 | end,
41 | disable = true,
42 | }
43 |
--------------------------------------------------------------------------------
/dotfiles/.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 = {
29 | version = "LuaJIT",
30 | path = vim.split(package.path, ";"),
31 | },
32 | path = { "lua/?.lua", "lua/?/init.lua" },
33 | workspace = {
34 | checkThirdParty = false,
35 | library = {
36 | vim.env.VIMRUNTIME,
37 | },
38 | },
39 | diagnostics = {
40 | globals = { "vim" },
41 | enable = true,
42 | },
43 | format = { enable = false },
44 | telemetry = {
45 | enable = false,
46 | },
47 | })
48 | end,
49 | settings = {
50 | Lua = {},
51 | },
52 | }
53 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/filetype.lua:
--------------------------------------------------------------------------------
1 | -- Module for defining new filetypes. I picked up these configurations based on inspirations from this dotfiles repo:
2 | -- https://github.com/davidosomething/dotfiles/blob/be22db1fc97d49516f52cef5c2306528e0bf6028/nvim/lua/dko/filetypes.lua
3 |
4 | vim.filetype.add({
5 | -- Detect and assign filetype based on the extension of the filename
6 | extension = {
7 | astro = "astro",
8 | mdx = "markdown",
9 | log = "log",
10 | conf = "conf",
11 | env = "dotenv",
12 | },
13 | -- Detect and apply filetypes based on the entire filename
14 | filename = {
15 | [".env"] = "dotenv",
16 | ["env"] = "dotenv",
17 | ["tsconfig.json"] = "jsonc",
18 | ["cloudbeaver.conf"] = "jsonc",
19 | ["playbook.yml"] = "yaml.ansible",
20 | ["site.yml"] = "yaml.ansible",
21 | },
22 | -- Detect and apply filetypes based on certain patterns of the filenames
23 | pattern = {
24 | -- INFO: Match filenames like - ".env.example", ".env.local" and so on
25 | ["%.env%.[%w_.-]+"] = "dotenv",
26 | [".*/ansible/.*%.ya?ml"] = "yaml.ansible", -- Match all YAML files under the "ansible" directory
27 | [".*/roles/.*%.ya?ml"] = "yaml.ansible",
28 | [".*/ansible/.*%.ya?ml%.j2"] = "yaml", -- Ansible template should be considered YAML files
29 | [".*/*.conf*"] = "conf", -- Config files (like "postgresql.conf" and so on)
30 | [".*/Caddyfile%.?.*"] = "caddy", -- Match files like "Caddyfile", "Caddyfile.j2", "Caddyfile.tmpl"
31 | },
32 | })
33 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/pyright.lua:
--------------------------------------------------------------------------------
1 | return {
2 | cmd = { "pyright-langserver", "--stdio" },
3 | filetypes = { "pyright-langserver", "--stdio" },
4 | root_markes = {
5 | "pyproject.toml",
6 | "setup.py",
7 | "setup.cfg",
8 | "requirements.txt",
9 | "Pipfile",
10 | "pyrightconfig.json",
11 | ".git",
12 | },
13 | settings = {
14 | python = {
15 | analysis = {
16 | autoSearchPaths = true,
17 | diagnosticMode = "openFilesOnly",
18 | useLibraryCodeForTypes = true,
19 | },
20 | },
21 | },
22 | on_attach = function(client, bufnr)
23 | vim.api.nvim_buf_create_user_command(bufnr, "LspPyrightOrganizeImports", function()
24 | client:exec_cmd({
25 | command = "pyright.oganizeimports",
26 | arguments = vim.url_from_bufnr(bufnr),
27 | })
28 | end, {
29 | desc = "Organize Python Imports",
30 | })
31 |
32 | vim.api.nvim_buf_create_user_command(bufnr, "LspPyrightSetPythonPath", function(path)
33 | if client.settings then
34 | client.settings.python = vim.tbl_deep_extend("force", client.settings.python, { pythonPath = path })
35 | else
36 | client.config.settings =
37 | vim.tbl_deep_extend("force", client.config.settings, { python = { pythonPath = path } })
38 | end
39 | vim.notify("workspace/didChangeConfiguration", { settings = nil })
40 | end, { desc = "Reconfigure Pyright with provided Python path", nargs = 1, complete = "file" })
41 | end,
42 | }
43 |
--------------------------------------------------------------------------------
/dotfiles/.config/tmux/statusline/statusline.conf:
--------------------------------------------------------------------------------
1 | ### General Statusline Settings ###
2 | # Enable the status bar
3 | set -g status on
4 |
5 | # Set the statusline to be rendered at the top of the screen and justified centred
6 | set -g status-position top
7 | set -g status-justify centre
8 |
9 | # Refresh the statusline every 5 seconds
10 | set -g status-interval 5
11 |
12 | # Set the background of the statusline to be of a darker shade of black
13 | set -g status-bg "#000000"
14 |
15 | # Set fixed width for the left and right-most sections
16 | set -g status-left-length 100
17 | set -g status-right-length 100
18 |
19 | # Configure left sections
20 | set -g status-left "\
21 | #[bg=#27215d,fg=#e7e6e9] #H #[fg=#868190](#(uptime --pretty)) \
22 | #{?#{==:#S,dotfiles},#[bg=#223a7d#,fg=#e7e6ed] #S,} \
23 | #[bg=#3c5397,fg=#e7e6e9] #I:#P \
24 | "
25 |
26 | # Active window
27 | set -g window-status-current-format "\
28 | #[bg=#a6cfd5,fg=#111515] #I: #W \
29 | #[default] \
30 | "
31 |
32 | # Configure the right section
33 | set -g status-right "\
34 | #[bg=#3c5397,fg=#e7e6e9] #(~/.config/tmux/statusline/battery-status) \
35 | #[bg=#223a7d#,fg=#e7e6ed] #(TZ="Asia/Kolkata" date "+%%H:%%M") IST |\
36 | #[bg=#223a7d#,fg=#e7e6ed] #(TZ="Europe/Sofia" date "+%%H:%%M") EET |\
37 | #[bg=#223a7d#,fg=#e7e6ed] #(TZ="Etc/Utc" date "+%%H:%%M") UTC \
38 | #[bg=#27215d,fg=#e7e6e9] %d-%b-%Y \
39 | "
40 |
41 | # Inactive windows
42 | set -g window-status-format "\
43 | #[fg=#868190]#I: #W \
44 | "
45 |
46 | # vim: ft=tmux
47 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | default_install_hook_types:
2 | - pre-commit
3 | - commit-msg
4 |
5 | repos:
6 | - repo: https://github.com/pre-commit/pre-commit-hooks
7 | rev: v6.0.0
8 | hooks:
9 | - id: trailing-whitespace
10 | - id: end-of-file-fixer
11 | exclude: ^dotfiles/.config/nvim/lazy-lock.json
12 | - id: check-yaml
13 | - id: check-added-large-files
14 | - id: detect-private-key
15 |
16 | - repo: https://github.com/jumanjihouse/pre-commit-hooks
17 | rev: 3.0.0
18 | hooks:
19 | - id: shfmt
20 | name: format shell scripts
21 | args:
22 | - "--indent=2"
23 | - "--case-indent"
24 | - "--binary-next-line"
25 | - "--space-redirects"
26 | - "--keep-padding"
27 |
28 | - repo: https://github.com/JohnnyMorganz/StyLua
29 | rev: v2.3.1
30 | hooks:
31 | - id: stylua
32 | name: format lua files
33 |
34 | - repo: https://github.com/astral-sh/ruff-pre-commit
35 | rev: v0.14.9
36 | hooks:
37 | - id: ruff
38 | name: format/lint python files
39 | args: [--fix, --exit-non-zero-on-fix]
40 |
41 | - repo: https://github.com/pre-commit/mirrors-mypy
42 | rev: v1.19.0
43 | hooks:
44 | - id: mypy
45 | name: type check python files
46 |
47 | # TODO: Add a pre-commit hook for Selene
48 |
49 | - repo: https://github.com/Weburz/crisp
50 | rev: v1.0.0
51 | hooks:
52 | - id: crisp
53 | name: lint commit messages
54 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/telescope.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring the Telescope plugin
2 |
3 | return {
4 | "nvim-telescope/telescope.nvim",
5 | event = "BufRead",
6 | cmd = "Telescope",
7 | opts = {
8 | defaults = {
9 | file_ignore_patterns = {
10 | "%.git",
11 | "node_modules",
12 | "%.venv",
13 | "^%.?env$",
14 | "%.terraform",
15 | "%.mypy_cache",
16 | "%.ruff_cache",
17 | "%.nuxt",
18 | "%.task",
19 | "dist",
20 | "%.pyc",
21 | "%.pytest_cache",
22 | "%.vitest",
23 | "%.tsbuildinfo",
24 | "coverage",
25 | "%.data",
26 | "pip",
27 | },
28 | },
29 | pickers = {
30 | find_files = {
31 | find_command = { "rg", "--files", "--hidden", "--glob", "!**/.git/*", "--no-ignore" },
32 | -- TODO: Figure a way out to make vertical splits through Telescope
33 | -- mappings = {
34 | -- i = {
35 | -- [""] = function(bufnr)
36 | -- if vim.bo[0].filetype ~= "ministarter" then
37 | -- require("telescope.actions").select_vertical(bufnr)
38 | -- end
39 | -- end,
40 | -- },
41 | -- },
42 | },
43 | },
44 | },
45 | config = function(_, opts)
46 | require("telescope").setup(opts)
47 | end,
48 | dependencies = {
49 | "devicons",
50 | "nvim-lua/plenary.nvim",
51 | "neovim/nvim-lspconfig",
52 | "nvim-treesitter/nvim-treesitter",
53 | },
54 | }
55 |
--------------------------------------------------------------------------------
/dotfiles/.local/bin/music-sort:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """
4 | Script to sort local music collection.
5 |
6 | Author: Somraj Saha
7 | License: MIT License (see https://github.com/Jarmos-san/dotfiles/blob/main/LICENSE for
8 | more information)
9 |
10 | INFO: This is a WIP script, it is not ready for usage yet!
11 | """
12 |
13 | from pathlib import Path
14 |
15 | # INFO: Labels for logging when printing to STDOUT
16 | ERROR = "\033[1;31mINFO\033[0m"
17 | SUCCESS = "\033[1;32mINFO\033[0m"
18 | WARN = "\033[1;33mINFO\033[0m"
19 | INFO = "\033[1;34mINFO\033[0m"
20 |
21 |
22 | def dir_exist(dirs: tuple[Path, Path]) -> bool:
23 | """Check whether a download location exists or not."""
24 | # INFO: Check if any of the aforementioned downloads folder exists, if not then
25 | # short-circuit the logic and return the function
26 | for dir in dirs:
27 | if dir.exists():
28 | return True
29 |
30 | return False
31 |
32 |
33 | def main() -> None:
34 | """Entrypoint of the script."""
35 | # Location of the home directory where the downloads directory is supposed to be in
36 | home_dir = Path.home()
37 |
38 | # Possible sets of download locations
39 | download_dirs = (home_dir / "Downloads", home_dir / "downloads")
40 |
41 | if not dir_exist(download_dirs):
42 | print(f"[{ERROR}] No download directory found...aborting!")
43 | else:
44 | print(f"[{SUCCESS}] Download directory found...sorting music right now!")
45 |
46 |
47 | if __name__ == "__main__":
48 | try:
49 | main()
50 | except Exception as err:
51 | print(f"[{ERROR}] Sorting music collection failed!\n{err}")
52 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/treesitter.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring the Treesitter plugin
2 |
3 | return {
4 | {
5 | "nvim-treesitter/nvim-treesitter",
6 | lazy = false,
7 | branch = "main",
8 | build = function()
9 | require("nvim-treesitter").update():wait(300000)
10 | end,
11 | config = function()
12 | local parsers = {
13 | -- "astro",
14 | -- "bash",
15 | -- "caddy",
16 | -- "comment",
17 | -- "css",
18 | -- "diff",
19 | -- "dockerfile",
20 | -- "editorconfig",
21 | -- "git_rebase",
22 | -- "gitattributes",
23 | -- "gitcommit",
24 | -- "gitignore",
25 | -- "go",
26 | -- "gomod",
27 | -- "gosum",
28 | -- "hcl",
29 | -- "html",
30 | -- "ini",
31 | -- "javascript",
32 | -- "jinja",
33 | -- "jinja_inline",
34 | -- "jsdoc",
35 | "json",
36 | -- "lua",
37 | -- "luadoc",
38 | -- "lua_patterns",
39 | -- "make",
40 | -- "markdown",
41 | -- "markdown_inline",
42 | -- "mermaid",
43 | "python",
44 | -- "regex",
45 | -- "robots",
46 | -- "rst",
47 | "scss",
48 | -- "terraform",
49 | -- "tsx",
50 | -- "toml",
51 | -- "typescript",
52 | -- "typst",
53 | -- "yaml",
54 | -- "vim",
55 | -- "vimdoc",
56 | "vue",
57 | }
58 | require("nvim-treesitter").setup()
59 | require("nvim-treesitter").install(parsers):wait(300000)
60 | end,
61 | -- TODO: Fix OOM issues which is crashing WSL entirely
62 | -- enabled = false,
63 | },
64 | }
65 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/cmp.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring the completion capabilities of Neovim
2 |
3 | return {
4 | "saghen/blink.cmp",
5 | version = "*",
6 | ---@module 'blink.cmp'
7 | ---@type blink.cmp.Config
8 | opts = {
9 | signature = {
10 | enabled = true,
11 | window = {
12 | border = "rounded",
13 | },
14 | },
15 | keymap = {
16 | preset = "enter",
17 | },
18 | appearance = {
19 | use_nvim_cmp_as_default = false,
20 | nerd_font_variant = "mono",
21 | },
22 | snippets = { preset = "luasnip" },
23 | sources = {
24 | default = { "lsp", "path", "snippets" },
25 | },
26 | completion = {
27 | accept = {
28 | auto_brackets = { enabled = true },
29 | },
30 | documentation = {
31 | auto_show = true,
32 | auto_show_delay_ms = 250,
33 | treesitter_highlighting = true,
34 | window = {
35 | border = "rounded",
36 | winblend = 0,
37 | },
38 | },
39 | list = {
40 | selection = {
41 | preselect = function(ctx)
42 | return ctx.mode ~= "cmdline"
43 | end,
44 | auto_insert = function(ctx)
45 | return ctx.mode ~= "cmdline"
46 | end,
47 | },
48 | },
49 | ghost_text = {
50 | enabled = true,
51 | },
52 | menu = {
53 | border = "rounded",
54 | winblend = 0,
55 | draw = {
56 | treesitter = { "lsp" },
57 | columns = {
58 | { "kind_icon" },
59 | { "label" },
60 | { "source_name" },
61 | },
62 | },
63 | },
64 | },
65 | },
66 | dependencies = "L3MON4D3/LuaSnip",
67 | }
68 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/powershell,visualstudiocode,vim,git
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=powershell,visualstudiocode,vim,git
3 |
4 | ### Git ###
5 | # Created by git for backups. To disable backups in Git:
6 | # $ git config --global mergetool.keepBackup false
7 | *.orig
8 |
9 | # Created by git when using merge tools for conflicts
10 | *.BACKUP.*
11 | *.BASE.*
12 | *.LOCAL.*
13 | *.REMOTE.*
14 | *_BACKUP_*.txt
15 | *_BASE_*.txt
16 | *_LOCAL_*.txt
17 | *_REMOTE_*.txt
18 |
19 | ### PowerShell ###
20 | # Exclude packaged modules
21 | *.zip
22 |
23 | # Exclude .NET assemblies from source
24 | *.dll
25 |
26 | ### Vim ###
27 | # Swap
28 | [._]*.s[a-v][a-z]
29 | !*.svg # comment out if you don't need vector files
30 | [._]*.sw[a-p]
31 | [._]s[a-rt-v][a-z]
32 | [._]ss[a-gi-z]
33 | [._]sw[a-p]
34 |
35 | # Session
36 | Session.vim
37 | Sessionx.vim
38 |
39 | # Temporary
40 | .netrwhist
41 | *~
42 | # Auto-generated tag files
43 | tags
44 | # Persistent undo
45 | [._]*.un~
46 |
47 | ### VisualStudioCode ###
48 | .vscode/*
49 | !.vscode/settings.json
50 | !.vscode/tasks.json
51 | !.vscode/launch.json
52 | !.vscode/extensions.json
53 | *.code-workspace
54 |
55 | # Local History for Visual Studio Code
56 | .history/
57 |
58 | ### VisualStudioCode Patch ###
59 | # Ignore all local history of files
60 | .history
61 | .ionide
62 |
63 | .luarc.json
64 | **/gh/hosts.yml
65 | scratch
66 | .venv
67 | .mypy_cache
68 | .ruff_cache
69 | **/adb
70 |
71 | **/.config/git/credentials
72 | **/cobra-cli
73 |
74 | **/.zsh/plugins
75 |
76 | **/.local/bin
77 | !**/.local/bin/update
78 | !**/.local/bin/git-clean
79 |
80 | **/tmux/plugins/**/*
81 | # End of https://www.toptal.com/developers/gitignore/api/powershell,visualstudiocode,vim,git
82 |
--------------------------------------------------------------------------------
/dotfiles/.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 | "astro-language-server",
26 | "ansible-language-server",
27 | "ansible-lint",
28 | "bash-language-server",
29 | "black",
30 | "css-lsp",
31 | "debugpy",
32 | "dockerfile-language-server",
33 | "eslint-lsp",
34 | "goimports-reviser",
35 | "golines",
36 | "gopls",
37 | "hadolint",
38 | "hclfmt",
39 | "json-lsp",
40 | "lua-language-server",
41 | "mypy",
42 | "prettier",
43 | "pyright",
44 | "ruff",
45 | "selene", -- FIXME: Broken on Ubuntu 20.04
46 | "shellcheck",
47 | "shfmt",
48 | "stylua",
49 | "stylelint",
50 | "sqlls",
51 | "terraform-ls",
52 | "typescript-language-server",
53 | "tinymist",
54 | "vale-ls",
55 | "vtsls",
56 | "vue-language-server",
57 | "yaml-language-server",
58 | "yamllint",
59 | },
60 | },
61 | config = function(_, opts)
62 | require("mason-tool-installer").setup(opts)
63 | end,
64 | },
65 | }
66 |
--------------------------------------------------------------------------------
/dotfiles/.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 | -- M.format = function(command)
23 | -- -- INFO: Get the current location of the cursor on the current window
24 | -- local cursor = vim.api.nvim_win_get_cursor(0)
25 | --
26 | -- -- INFO: The formatting command to invoke after the contents are saved
27 | -- vim.cmd(command)
28 | --
29 | -- -- INFO: In case the formatting got rid of the line we came from
30 | -- cursor[1] = math.min(cursor[1], vim.api.nvim_buf_line_count(0))
31 | --
32 | -- -- INFO: Update the current cursor location according to the caluclated values
33 | -- vim.api.nvim_win_set_cursor(0, cursor)
34 | -- end
35 |
36 | -- Setup highlight groups for Neovim easily
37 | M.highlight = vim.api.nvim_set_hl
38 |
39 | -- Check if the current directory is version-controlled using Git
40 | M.is_git_repo = function()
41 | local handle = io.popen("git rev-parse --is-inside-work-tree 2>/dev/null")
42 | local output = handle:read("*a")
43 | handle:close()
44 |
45 | if output:match("true") then
46 | return true
47 | else
48 | return false
49 | end
50 | end
51 |
52 | -- Check if the ".git" directory exists in the current directory
53 | M.has_git_dir = function()
54 | local handle = io.popen("ls -a 2>/dev/null")
55 | local output = handle:read("*a")
56 | handle:close()
57 |
58 | if output:match("%.git") then
59 | return true
60 | else
61 | return false
62 | end
63 | end
64 |
65 | return M
66 |
--------------------------------------------------------------------------------
/dotfiles/.config/wezterm/wezterm.lua:
--------------------------------------------------------------------------------
1 | local wezterm = require("wezterm")
2 | local mux = wezterm.mux
3 |
4 | -- Ensure the terminal is opened is in fullscreen mode right after startup
5 | wezterm.on("gui-startup", function(cmd)
6 | local _, _, window = mux.spawn_window(cmd or {})
7 | window:gui_window():toggle_fullscreen()
8 | end)
9 |
10 | -- This Lua module returns a table of configuration values which Wezterm reads to
11 | -- customise the aesthetics of the terminal.
12 | return {
13 | -- Reduce unnecessary padding on the window
14 | window_padding = { left = 1, right = 0, top = 8, bottom = 0 },
15 |
16 | -- Some bare basic key bindings for managing the terminal
17 | keys = {
18 | {
19 | -- Key binding to toggle fullscreen mode
20 | key = "F11",
21 | mods = "NONE",
22 | action = wezterm.action.ToggleFullScreen,
23 | },
24 | },
25 |
26 | -- INFO: Enable "light mode" on the desktop
27 | color_scheme = "Google Dark (base16)",
28 |
29 | -- Set a monospaced font for easier time when writing code
30 | font = wezterm.font("CaskaydiaCove Nerd Font Mono", {
31 | weight = "DemiBold",
32 | stretch = "Normal",
33 | style = "Normal",
34 | }),
35 |
36 | -- The default shell to invoke when launching the terminal
37 | default_prog = { "/home/linuxbrew/.linuxbrew/bin/zsh", "-l" },
38 |
39 | -- Make the font size of the terminal contents legible
40 | font_size = 11.0,
41 |
42 | -- Hide the tab bar if there's only one tab open
43 | hide_tab_bar_if_only_one_tab = true,
44 |
45 | -- Make the window background transparent
46 | window_background_opacity = 0.96,
47 |
48 | -- Make the cursor to blink on the terminal
49 | default_cursor_style = "BlinkingBlock",
50 |
51 | -- Set the rate at which the cursor will blink
52 | cursor_blink_rate = 600,
53 |
54 | -- Disable checking for updates every day (which is annoying af!)
55 | check_for_updates = false,
56 |
57 | -- Disable the annoying audio bell
58 | audible_bell = "Disabled",
59 |
60 | -- Disable warning about missing glyphs
61 | warn_about_missing_glyphs = false,
62 | }
63 |
--------------------------------------------------------------------------------
/dotfiles/.zshrc:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env zsh
2 |
3 | # The following lines were added by compinstall
4 | zstyle ":completion:*" completer _expand _complete _ignored _correct _approximate
5 | zstyle ":completion:*" matcher-list "" "" "m:{[:lower:]}={[:upper:]}" "m:{[:lower:][:upper:]}={[:upper:][:lower:]}"
6 | zstyle :compinstall filename "$HOME/.zshrc"
7 |
8 | autoload -Uz compinit
9 | compinit
10 | # End of lines added by compinstall
11 | # Lines configured by zsh-newuser-install
12 | setopt autocd beep extendedglob nomatch notify
13 | # End of lines configured by zsh-newuser-install
14 |
15 | # Update the default PATH
16 | export PATH="$HOME/.local/bin:$PATH"
17 |
18 | # Enable Starship
19 | eval "$(starship init zsh)"
20 |
21 | # Check if ~/.zsh directory exists
22 | if [[ -d "$HOME/.zsh" ]]; then
23 | # Source all files within the ~/.zsh directory
24 | for file in "$HOME/.zsh"/*; do
25 | source "$file"
26 | done
27 | fi
28 |
29 | # Various ZSH plugins to make the Shell usage experience better
30 | plugins=(
31 | "zsh-syntax-highlighting/zsh-syntax-highlighting.plugin.zsh"
32 | "zsh-autosuggestions/zsh-autosuggestions.plugin.zsh"
33 | "zsh-colored-man-pages/colored-man-pages.plugin.zsh"
34 | "zsh-completions/zsh-completions.plugin.zsh"
35 | )
36 |
37 | # Loop through the list of plugins mentioned above & source them for usage
38 | for plugin in "${plugins[@]}"; do
39 | source "$HOME/.zsh/plugins/${plugin}"
40 | done
41 |
42 | # Ensure the "plugins" array to removed from memory for safety reasons
43 | unset plugins
44 |
45 | # Configure some ZSH keybinds only if using the Kitty terminal
46 | if [[ $TERM == "kitty-xterm" ]]; then
47 | bindkey "^[[4~" end-of-line
48 | bindkey "^[[1~" beginning-of-line
49 | else
50 | bindkey "^[[H" beginning-of-line
51 | bindkey "^[[F" end-of-line
52 | bindkey "^[[3~" delete-char
53 | fi
54 |
55 | # INFO: See the thread here - "https://vi.stackexchange.com/a/7654" for more information
56 | if [[ -n $VIRTUAL_ENV && -e "${VIRTUAL_ENV}/bin/activate" ]]; then
57 | source "${VIRTUAL_ENV}/bin/activate"
58 | fi
59 |
60 | # TODO: Customise the prompt without using 'Starship'
61 | # https://www.makeuseof.com/customize-zsh-prompt-macos-terminal
62 |
63 | export UV_PYTHON_DOWNLOADS=never
64 |
--------------------------------------------------------------------------------
/.github/workflows/qa-checks.yml:
--------------------------------------------------------------------------------
1 | name: QA Checks
2 |
3 | on:
4 | push:
5 |
6 | jobs:
7 | runStyLua:
8 | name: Format Lua Files
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout Repository
12 | uses: actions/checkout@v6
13 |
14 | - name: Download and Setup Stylua
15 | env:
16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 | run: |
18 | gh release download --repo JohnnyMorganz/StyLua \
19 | --pattern "stylua-linux-x86_64.zip"
20 | unzip "stylua-linux-x86_64.zip"
21 | cp stylua /usr/local/bin/
22 | echo "Downloaded Stylua v$(stylua --version | grep --only-matching --perl-regexp '\d+\.\d+\.\d+')"
23 |
24 | - name: Run the Stylua formatter for Lua code
25 | run: stylua . --check
26 |
27 | runSeleneLinter:
28 | name: Lint Lua Files
29 | runs-on: ubuntu-latest
30 | steps:
31 | - name: Checkout Repository
32 | uses: actions/checkout@v6
33 |
34 | - name: Download and Setup Selene
35 | env:
36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37 | run: |
38 | gh release download --repo Kampfkarren/selene --pattern "selene-*-linux.zip"
39 | unzip "selene-light-*-linux.zip"
40 | cp selene /usr/local/bin/ && chmod u+x /usr/local/bin/selene
41 | echo "Downloaded Selene v$(selene --version | grep --only-matching --perl-regexp '\d+\.\d+\.\d+')"
42 |
43 | - name: Run Selene to Lint Lua Code
44 | run: selene .
45 |
46 | runRuff:
47 | name: Lint Python Files
48 | runs-on: ubuntu-latest
49 | steps:
50 | - name: Checkout Repository
51 | uses: actions/checkout@v6
52 |
53 | - name: Download and Setup Ruff
54 | env:
55 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
56 | run: pipx install ruff
57 |
58 | - name: Run the Ruff Linter for Python Code
59 | run: ruff check "$PWD"
60 |
61 | runBlackFormatter:
62 | name: Format Python Files
63 | runs-on: ubuntu-latest
64 | steps:
65 | - name: Checkout Repository
66 | uses: actions/checkout@v6
67 |
68 | - name: Run the Black Formatter on Python Files
69 | run: |
70 | pip install black
71 | black . --check
72 |
--------------------------------------------------------------------------------
/dotfiles/.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=2",
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 |
--------------------------------------------------------------------------------
/dotfiles/.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 autocmd = require("utils").autocmd
6 | local augroup = require("utils").augroup
7 | local map = require("utils").map
8 |
9 | -- INFO: Local keymap (specific to Python files) to execute the current Python script
10 | if os.getenv("VIRTUAL_ENV") ~= nil then
11 | map("n", "", "terminal pytest %")
12 | map("n", "", "terminal python %")
13 | else
14 | map("n", "", "terminal python3 %")
15 | end
16 |
17 | autocmd({ "BufWritePost" }, {
18 | desc = "Lint buffer contents after writing them",
19 | group = augroup("lint_python_files"),
20 | callback = function()
21 | require("lint").try_lint()
22 | end,
23 | })
24 |
25 | -- Wrap words at the EOL "cleanly" (i.e) ensure the words are wrapped and not just characters
26 | vim.opt.wrap = true
27 | vim.opt.linebreak = true
28 |
29 | -- Start the Treesitter parse process for highligting Python files
30 | vim.treesitter.start()
31 |
32 | -- Configure the indent-based folds for Python buffers
33 | if vim.api.nvim_buf_line_count(0) >= 100 then
34 | vim.opt.foldmethod = "expr"
35 | vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
36 | vim.opt.foldlevel = 0
37 | vim.opt.foldcolumn = "auto"
38 | end
39 |
40 | -- Configure and enable the LSP server for Python
41 | vim.diagnostic.config({
42 | float = true, -- Show the diagnostic messages in a floating window
43 | underline = true, -- Show squiggly lines under the statement with an error/warning
44 | update_in_insert = true, -- Update the message even when in Insert mode
45 | severity_sort = true, -- Configure Neovim to sort the error messages according to their severity
46 | virtual_text = true, -- Show virtual lines besides the statement with an error/warning
47 | })
48 |
49 | -- Enable the LSP server for Python
50 | vim.lsp.enable("pyright", true)
51 |
52 | -- TODO: Move this autocommand to its own module/package
53 | vim.api.nvim_create_autocmd("CursorHold", {
54 | buffer = vim.api.nvim_get_current_buf(),
55 | callback = function()
56 | local hover_window_configs = {
57 | focusable = false,
58 | close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" },
59 | border = "rounded",
60 | source = "always",
61 | prefix = " ",
62 | scope = "cursor",
63 | }
64 |
65 | vim.diagnostic.open_float(nil, hover_window_configs)
66 | end,
67 | })
68 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/skeletons/readme.md:
--------------------------------------------------------------------------------
1 | # 🍱 Name of the Project
2 |
3 |
4 |
5 | 
6 | 
7 | 
8 |
9 | About the project in not more than 5-10 sentences to keep the user engaged &
10 | give them a brief idea of the project as well.
11 |
12 | ## 🦮 How to Use the Project
13 |
14 | Share some usage guidelines here like:
15 |
16 | 1. How to download the project.
17 | 2. Once downloaded how to invoke the command & run it on the user's local
18 | machine.
19 | 3. How & where to find help once the user starts using the project.
20 |
21 | ## 🫂 Contributing & Supporting the Project
22 |
23 | Share detailed guidelines on how the interested user can start contributing to
24 | the project.
25 |
26 | ### How to Contribute to the Project
27 |
28 | There are numerous ways to contribute to the project & here are a few ways I can
29 | think of on the top of my head.
30 |
31 | - Found bugs? Report it by opening an [issue thread][4].
32 | - Have a better plugin or an enhancement suggestions? Let the author know about
33 | it.
34 | - Are you interested in writing Lua code or perhaps use this project as your
35 | own? Then feel free to share a PR or two.
36 | - Found the project useful to get started with working on Neovim ASAP? Then
37 | consider sponsoring the author as it keeps him motivated & pays the bills.
38 |
39 | To learn more about contributing to the project, refer to the "[Developer
40 | Guidelines][13]" section of the wiki. Also don't forget to check out the more
41 | detailed instructions as laid down in the "[Contributing Guidelines][14]" for
42 | the project.
43 |
44 | That said, if you've any questions related to the development of this project,
45 | please feel to reach out to author & maintainer of the project!
46 |
47 | ## 📄 Usage Terms & Conditions
48 |
49 | The project is licensed under the terms & conditions (T&Cs) for the MIT license.
50 | So, you free to use, distribute, copy, modify & such with the contents of this
51 | repository in whatever manner you want to. The caveat is, your usage should
52 | adhere to the T&Cs of the MIT license.
53 |
54 | For more information on the licensing T&Cs, feel free to refer to the
55 | [LICENSE](./LICENSE) document.
56 |
57 |
58 |
59 | [1]: https://www.example.com
60 |
--------------------------------------------------------------------------------
/dotfiles/.zsh/aliases:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env zsh
2 |
3 | # A bunch of custom aliases for easier terminal usage.
4 | alias ct="cookiecutter"
5 | alias pcs="pre-commit sample-config >> .pre-commit-config.yaml && pre-commit autoupdate &>/dev/null"
6 |
7 | # Docker commands
8 | alias compose="docker compose"
9 | alias dps="docker ps --format 'table {{ .ID }}\t{{ .Names }}\t{{ .Ports }}'"
10 | alias dimc="docker image prune --force"
11 | alias drmi="docker image rm"
12 | alias dcdown="docker compose down --remove-orphans --volumes"
13 | alias dcup="docker compose up --detach"
14 | alias dclogs="docker compose logs"
15 | alias dims="docker images"
16 |
17 | # Easy and utilitarian aliases for quick terminal usage
18 | alias reload="source $HOME/.zshrc"
19 | alias top="btop --utf-force"
20 | alias cm="cmatrix -abs"
21 | alias rands="openssl rand -base64 32"
22 | alias ll="eza --long --all --classify --icons --git --ignore-glob='.git'"
23 | alias loc="wc -l"
24 | alias tree="eza --tree --all --icons --ignore-glob='.git' --git-ignore"
25 | alias dateiso="date +%Y-%m-%dT%H:%M:%S%z"
26 |
27 | # Spin dev/experimental databases
28 | alias pgdb="docker run --detach --name postgresql --rm -p 5432:5432 \
29 | -e POSTGRESQL_USERNAME=psqladmin \
30 | -e POSTGRESQL_PASSWORD=admin \
31 | -e POSTGRESQL_DATABASE=postgres \
32 | bitnami/postgresql:16"
33 | alias rsdb="docker run --name redis --rm -p 6379:6379 \
34 | -e ALLOW_EMPTY_PASSWORD=yes \
35 | bitnami/redis:7.2"
36 |
37 | # Terraform related aliases
38 | alias tfinit="terraform init"
39 | alias tfval="terraform validate"
40 | alias tfplan="terraform plan"
41 |
42 | # NPM aliases
43 | alias npm="pnpm"
44 | alias npx="pnpm dlx"
45 |
46 | # Google's webp CLI alias
47 | alias webp="cwebp"
48 |
49 | # A bunch of Tmux aliases for easier multiplex usage
50 | alias tls="tmux list-session"
51 | alias tnew="tmux new-session"
52 | alias dots="tmux new-session -s dotfiles -n dotfiles -c ~/.dotfiles"
53 | alias tks="tmux kill-server"
54 | alias homelab="tmux new-session -s homelab -n homelab -c ~/projects/homelab"
55 |
56 | # Some complex Git aliases
57 | alias git-sync="git switch main && git fetch --prune && git branch -vv | awk '/: gone/ {print $1}' | xargs -r git branch --delete"
58 |
59 | # Some aliases for working with Python
60 | alias mkvenv="uv venv"
61 | # FIXME: Why does it get evaluated when creating an interactive shell environment?
62 | # alias penv="eval $(poetry env activate)"
63 | alias py="python3"
64 | alias python="python3"
65 |
66 | # Some aliases for working with Go
67 | alias goimports="goimports-reviser -use-cache -rm-unused -set-alias"
68 |
69 | # Alias to cd into the "blogs" directory
70 | alias blogs="cd ~/projects/blogposts"
71 |
--------------------------------------------------------------------------------
/dotfiles/.local/bin/tag:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """
4 | Simple script to make Git tagging easier.
5 |
6 | The script intelligently identifies the project configuration file (like "package.json"
7 | or "pyproject.toml"), updates the project version and applies a Git Tag as well!
8 |
9 | Author: Somraj Saha
10 | License: MIT License
11 | """
12 |
13 | # INFO: This is a WIP script, nothing is set in stone yet!
14 |
15 | import subprocess
16 | from argparse import ArgumentParser, Namespace
17 | from pathlib import Path
18 |
19 |
20 | def is_git_repository() -> bool | None:
21 | """Check if the current working directory is a Git repository or not."""
22 | try:
23 | command = subprocess.run(["git", "rev-parse", "--is-inside-work-tree"])
24 |
25 | if command.returncode == 0 and command.stdout.strip() == b"true":
26 | return True
27 | else:
28 | return False
29 | except FileNotFoundError as error:
30 | raise error
31 |
32 |
33 | def argument_parser() -> Namespace:
34 | """Parse the list of argument passed to the script and return them."""
35 | parser = ArgumentParser(description="Make Git tagging easy and quick.")
36 |
37 | parser.add_argument("name", help="The name of the tag")
38 | parser.add_argument("message", help="The message to annotate the tag with")
39 |
40 | return parser.parse_args()
41 |
42 |
43 | def run_git_tag() -> None:
44 | """Invoke the git-tag function to annotate a commit."""
45 | args = argument_parser()
46 |
47 | subprocess.run(
48 | ["git", "tag", "--annotate", "--sign", args.name, f"--message={args.message}"]
49 | )
50 |
51 |
52 | def main() -> None:
53 | """Entrypoint of the script."""
54 | # A list of the project configuration files to update with the latest version tag
55 | filename = ("package.json", "pyproject.toml", "Cargo.toml")
56 |
57 | if is_git_repository():
58 | run_git_tag()
59 |
60 | for file in filename:
61 | filepath = Path.cwd() / file
62 | if filepath.exists():
63 | match filepath.name:
64 | case "package.json":
65 | print('Update the "package.json" file!')
66 | case "pyproject.toml":
67 | print('Update the "pyproject.toml" file!')
68 | case "Cargo.toml":
69 | print('Update the "Cargo.toml" file!')
70 | case _:
71 | print("Failed to identify project configuration file!")
72 | else:
73 | print("Not a Git directory...not tagging anything!")
74 |
75 |
76 | if __name__ == "__main__":
77 | main()
78 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lazy-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "LuaSnip": { "branch": "master", "commit": "3732756842a2f7e0e76a7b0487e9692072857277" },
3 | "blink.cmp": { "branch": "main", "commit": "b19413d214068f316c78978b08264ed1c41830ec" },
4 | "conform.nvim": { "branch": "master", "commit": "41715945edf518ca73a9bd63ab6cdc23dd5c7b33" },
5 | "devicons": { "branch": "master", "commit": "8dcb311b0c92d460fac00eac706abd43d94d68af" },
6 | "evergarden": { "branch": "main", "commit": "ed86852e01f03853326c68961ff10bcaf8ff5f9c" },
7 | "gitsigns.nvim": { "branch": "main", "commit": "5813e4878748805f1518cee7abb50fd7205a3a48" },
8 | "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" },
9 | "lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" },
10 | "mason-tool-installer.nvim": { "branch": "main", "commit": "517ef5994ef9d6b738322664d5fdd948f0fdeb46" },
11 | "mason.nvim": { "branch": "main", "commit": "57e5a8addb8c71fb063ee4acda466c7cf6ad2800" },
12 | "mini.bufremove": { "branch": "main", "commit": "10857aa39160c127694151828914df3131ba83b6" },
13 | "mini.comment": { "branch": "main", "commit": "a0c721115faff8d05505c0a12dab410084d9e536" },
14 | "mini.indentscope": { "branch": "main", "commit": "0308f949f31769e509696af5d5f91cebb2159c69" },
15 | "mini.move": { "branch": "main", "commit": "4d214202d71e0a4066b6288176bbe88f268f9777" },
16 | "mini.pairs": { "branch": "main", "commit": "d5a29b6254dad07757832db505ea5aeab9aad43a" },
17 | "mini.splitjoin": { "branch": "main", "commit": "9fcd8856efb95a505090c3225726466494076127" },
18 | "mini.starter": { "branch": "main", "commit": "8ee6ce6a4c9be47682516908557cc062c4d595a2" },
19 | "mini.surround": { "branch": "main", "commit": "88c52297ed3e69ecf9f8652837888ecc727a28ee" },
20 | "neoscroll.nvim": { "branch": "master", "commit": "f957373912e88579e26fdaea4735450ff2ef5c9c" },
21 | "nvim-lint": { "branch": "master", "commit": "7a64f4067065c16a355d40d0d599b8ca6b25de6d" },
22 | "nvim-lspconfig": { "branch": "master", "commit": "c4f67bf85b01a57e3c130352c0a0e453ab8cd5b9" },
23 | "nvim-notify": { "branch": "master", "commit": "8701bece920b38ea289b457f902e2ad184131a5d" },
24 | "nvim-treesitter": { "branch": "main", "commit": "4fc09bee78e91bf4ba471cdab4bf9dfa37fde51c" },
25 | "nvim-ts-context-commentstring": { "branch": "main", "commit": "1b212c2eee76d787bbea6aa5e92a2b534e7b4f8f" },
26 | "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
27 | "schemastore.nvim": { "branch": "main", "commit": "806187c790d93625564708c286e16142d87a5cc9" },
28 | "smartcolumn.nvim": { "branch": "main", "commit": "b9cdbdf42f7ac5a659204cd5926017c7ff724a19" },
29 | "telescope.nvim": { "branch": "master", "commit": "3d757e586ff0bfc85bdb7b46c9d3d932147a0cde" }
30 | }
31 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/terminal.lua:
--------------------------------------------------------------------------------
1 | -- This module contains the Lua code to configure the inbuilt terminal
2 |
3 | local M = {}
4 |
5 | local buf, win
6 |
7 | local create_term = function()
8 | vim.fn.termopen(vim.o.shell, {
9 | on_exit = function()
10 | buf, win = nil, nil
11 | end,
12 | })
13 | end
14 |
15 | M.setup = {
16 | float = function()
17 | buf = vim.api.nvim_create_buf(false, true) -- Create a new buffer
18 |
19 | -- Various settings of the window
20 | local width = math.floor(vim.o.columns * 0.8) -- 80% of the screen size
21 | local height = math.floor(vim.o.lines * 0.5) -- 50% of the screen size
22 | local row = math.floor((vim.o.lines - height) / 2)
23 | local col = math.floor((vim.o.columns - width) / 2)
24 | local title = string.format("Terminal (%s)", vim.o.shell)
25 |
26 | -- Configure the settings of the window
27 | local opts = {
28 | relative = "editor",
29 | row = row,
30 | col = col,
31 | width = width,
32 | height = height,
33 | border = "rounded",
34 | title = title,
35 | title_pos = "center",
36 | }
37 |
38 | -- Create a floating window to render the terminal into
39 | win = vim.api.nvim_open_win(buf, true, opts)
40 |
41 | -- Open a terminal session in the floating window
42 | create_term()
43 | end,
44 |
45 | vertical = function()
46 | buf = vim.api.nvim_create_buf(false, true)
47 |
48 | -- Open a vertical split and switch to it
49 | vim.api.nvim_open_win(buf, true, { split = "right" })
50 |
51 | -- Open a terminal session in the floating window
52 | create_term()
53 | end,
54 |
55 | toggle = function()
56 | if win and vim.api.nvim_win_is_valid(win) then
57 | vim.api.nvim_win_close(win, true)
58 | buf, win = nil, nil
59 | return
60 | end
61 |
62 | buf = vim.api.nvim_create_buf(false, true) -- Create a new buffer
63 |
64 | -- Various settings of the window
65 | local width = math.floor(vim.o.columns * 0.8) -- 80% of the screen size
66 | local height = math.floor(vim.o.lines * 0.5) -- 50% of the screen size
67 | local row = math.floor((vim.o.lines - height) / 2)
68 | local col = math.floor((vim.o.columns - width) / 2)
69 | local title = string.format("Terminal (%s)", vim.o.shell)
70 |
71 | -- Configure the settings of the window
72 | local opts = {
73 | relative = "editor",
74 | row = row,
75 | col = col,
76 | width = width,
77 | height = height,
78 | border = "rounded",
79 | title = title,
80 | title_pos = "center",
81 | }
82 |
83 | -- Create a floating window to render the terminal into
84 | win = vim.api.nvim_open_win(buf, true, opts)
85 |
86 | -- Open a terminal session in the floating window
87 | create_term()
88 | end,
89 | }
90 |
91 | return M
92 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/mini-nvim.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring and managing the "mini.nvim" plugins
2 |
3 | return {
4 | {
5 | "nvim-mini/mini.comment",
6 | event = { "BufNewFile", "BufReadPost" },
7 | opts = {
8 | -- FIXME: Blank lines are also commented (need a fix someday)
9 | ignore_blank_lines = true,
10 | custom_commentstring = function()
11 | return require("ts_context_commentstring.internal").calculate_commentstring() or vim.bo.commentstring
12 | end,
13 | },
14 | config = function(_, opts)
15 | require("mini.comment").setup(opts)
16 | end,
17 | dependencies = { "JoosepAlviste/nvim-ts-context-commentstring" },
18 | },
19 |
20 | {
21 | "nvim-mini/mini.pairs",
22 | event = { "CmdwinEnter", "InsertEnter" },
23 | opts = {
24 | modes = {
25 | insert = true, -- "Insert" mode
26 | command = true, -- "Command" mode
27 | terminal = true, -- "Terminal" mode
28 | },
29 | },
30 | config = function(_, opts)
31 | require("mini.pairs").setup(opts)
32 | end,
33 | },
34 |
35 | {
36 | "nvim-mini/mini.surround",
37 | event = "BufReadPost",
38 | config = function()
39 | require("mini.surround").setup()
40 | end,
41 | },
42 |
43 | {
44 | "nvim-mini/mini.indentscope",
45 | event = "BufReadPost",
46 | config = function()
47 | require("mini.indentscope").setup()
48 | end,
49 | },
50 |
51 | {
52 | "nvim-mini/mini.bufremove",
53 | event = { "BufReadPost", "BufNewFile" },
54 | config = function()
55 | require("mini.bufremove").setup()
56 | end,
57 | },
58 |
59 | {
60 | -- Plugin to show a nice, minimal and easy-to-use startup screen
61 | "nvim-mini/mini.starter",
62 | event = "VimEnter",
63 | opts = function()
64 | local header = "Hello World!"
65 | return {
66 | items = {
67 | { name = "Open Old Files", action = "Telescope oldfiles", section = "File Explorer" },
68 | { name = "Open File Explorer", action = "Neotree toggle", section = "File Explorer" },
69 | { action = require("mini.starter").sections.recent_files(8, true, true), section = "Recent Files" },
70 | { name = "Fuzzy Search for Files/Folders", action = "Telescope find_files", section = "File Explorer" },
71 | },
72 | header = header,
73 | footer = 'Press "alt + j/k" to navigate up/down.',
74 | }
75 | end,
76 | config = function(_, opts)
77 | require("mini.starter").setup(opts)
78 | end,
79 | },
80 |
81 | {
82 | "nvim-mini/mini.splitjoin",
83 | event = "BufReadPost",
84 | config = function()
85 | require("mini.splitjoin").setup()
86 | end,
87 | },
88 |
89 | {
90 | "nvim-mini/mini.move",
91 | event = "BufReadPost",
92 | config = function()
93 | require("mini.move").setup()
94 | end,
95 | },
96 | }
97 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/init.lua:
--------------------------------------------------------------------------------
1 | -- Path to install "lazy.nvim" at
2 | local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
3 |
4 | if not (vim.uv or vim.loop).fs_stat(lazypath) then
5 | local lazyrepo = "https://github.com/folke/lazy.nvim.git"
6 | local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
7 | if vim.v.shell_error ~= 0 then
8 | vim.api.nvim_echo({
9 | { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
10 | { out, "WarningMsg" },
11 | { "\nPress any key to exit..." },
12 | }, true, {})
13 | vim.fn.getchar()
14 | os.exit(1)
15 | end
16 | end
17 |
18 | -- Update the Neovim runtimepath for "lazy.nvim" to source the plugins.
19 | vim.opt.rtp:prepend(lazypath)
20 |
21 | -- Map the key to .
22 | vim.g.mapleader = " "
23 |
24 | -- Disable some in-built features which are unnecessary (and probably affects performance?)
25 | vim.g.loaded_python3_provider = 0
26 | vim.g.loaded_ruby_provider = 0
27 | vim.g.loaded_perl_provider = 0
28 | vim.g.loaded_node_provider = 0
29 |
30 | -- Install the necessary plugins through "lazy.nvim"
31 | require("lazy").setup("plugins", {
32 | defaults = { lazy = true }, -- Make all plugins to be lazy-loaded.
33 | ui = {
34 | border = "rounded", -- Enable rounded borders for the "lazy.nvim" UI.
35 | },
36 | performance = {
37 | rtp = {
38 | disabled_plugins = { -- Disable certain in-built plugins which are useful af.
39 | "gzip",
40 | "matchit",
41 | "matchparen",
42 | "tarPlugin",
43 | "tohtml",
44 | "tutor",
45 | "zipPlugin",
46 | "rplugin",
47 | "man",
48 | "spellfile",
49 | },
50 | },
51 | },
52 | rocks = {
53 | enabled = false,
54 | },
55 | })
56 |
57 | -- Safely load the necessary user-defined Lua modules meant to customise Neovim.
58 | for _, module in ipairs({ "options", "autocmds", "keymaps" }) do
59 | local ok, error = pcall(require, module)
60 |
61 | if not ok then
62 | print("Error loading module: " .. error)
63 | end
64 | end
65 |
66 | -- My WIP personalised colour scheme
67 | -- vim.cmd.colorscheme("tansai")
68 |
69 | vim.cmd.colorscheme("evergarden")
70 |
71 | -- INFO: Enable an experimental fast module loader. See the PR for more information:
72 | -- https://github.com/neovim/neovim/pull/22668
73 | vim.loader.enable()
74 |
75 | -- Additional features to look into later on:
76 | -- https://github.com/rafcamlet/nvim-luapad
77 |
78 | -- INFO: Good book to learn Vim from;
79 | -- https://learnvim.irian.to/
80 |
81 | -- FIXME: Figure a way out to handle semantic highlights better with the following article as a source of reference:
82 | -- https://gist.github.com/swarn/fb37d9eefe1bc616c2a7e476c0bc0316
83 |
84 | -- TODO: Figure a way out to manage the plugin using lazy.nvim
85 | require("statusline").setup()
86 |
87 | -- Enable the required LSP servers
88 | vim.lsp.enable({ "lua_ls" })
89 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/colors/shinkai.vim:
--------------------------------------------------------------------------------
1 | hi clear
2 | syntax reset
3 | let g:colors_name = "shinkai"
4 | set background=light
5 | set t_Co=256
6 | hi Normal guifg=#000000 ctermbg=NONE guibg=#ffffff gui=NONE
7 |
8 | hi DiffText guifg=#06448b guibg=NONE
9 | hi ErrorMsg guifg=#06448b guibg=NONE
10 | hi WarningMsg guifg=#06448b guibg=NONE
11 | hi PreProc guifg=#06448b guibg=NONE
12 | hi Exception guifg=#06448b guibg=NONE
13 | hi Error guifg=#06448b guibg=NONE
14 | hi DiffDelete guifg=#06448b guibg=NONE
15 | hi GitGutterDelete guifg=#06448b guibg=NONE
16 | hi GitGutterChangeDelete guifg=#06448b guibg=NONE
17 | hi cssIdentifier guifg=#06448b guibg=NONE
18 | hi cssImportant guifg=#06448b guibg=NONE
19 | hi Type guifg=#06448b guibg=NONE
20 | hi Identifier guifg=#06448b guibg=NONE
21 | hi PMenuSel guifg=#045835 guibg=NONE
22 | hi Constant guifg=#045835 guibg=NONE
23 | hi Repeat guifg=#045835 guibg=NONE
24 | hi DiffAdd guifg=#045835 guibg=NONE
25 | hi GitGutterAdd guifg=#045835 guibg=NONE
26 | hi cssIncludeKeyword guifg=#045835 guibg=NONE
27 | hi Keyword guifg=#045835 guibg=NONE
28 | hi IncSearch guifg=#60720b guibg=NONE
29 | hi Title guifg=#60720b guibg=NONE
30 | hi PreCondit guifg=#60720b guibg=NONE
31 | hi Debug guifg=#60720b guibg=NONE
32 | hi SpecialChar guifg=#60720b guibg=NONE
33 | hi Conditional guifg=#60720b guibg=NONE
34 | hi Todo guifg=#60720b guibg=NONE
35 | hi Special guifg=#60720b guibg=NONE
36 | hi Label guifg=#60720b guibg=NONE
37 | hi Delimiter guifg=#60720b guibg=NONE
38 | hi Number guifg=#60720b guibg=NONE
39 | hi CursorLineNR guifg=#60720b guibg=NONE
40 | hi Define guifg=#60720b guibg=NONE
41 | hi MoreMsg guifg=#60720b guibg=NONE
42 | hi Tag guifg=#60720b guibg=NONE
43 | hi String guifg=#60720b guibg=NONE
44 | hi MatchParen guifg=#60720b guibg=NONE
45 | hi Macro guifg=#60720b guibg=NONE
46 | hi DiffChange guifg=#60720b guibg=NONE
47 | hi GitGutterChange guifg=#60720b guibg=NONE
48 | hi cssColor guifg=#60720b guibg=NONE
49 | hi Function guifg=#1368f3 guibg=NONE
50 | hi Directory guifg=#620eb1 guibg=NONE
51 | hi markdownLinkText guifg=#620eb1 guibg=NONE
52 | hi javaScriptBoolean guifg=#620eb1 guibg=NONE
53 | hi Include guifg=#620eb1 guibg=NONE
54 | hi Storage guifg=#620eb1 guibg=NONE
55 | hi cssClassName guifg=#620eb1 guibg=NONE
56 | hi cssClassNameDot guifg=#620eb1 guibg=NONE
57 | hi Statement guifg=#0ecaf1 guibg=NONE
58 | hi Operator guifg=#0ecaf1 guibg=NONE
59 | hi cssAttr guifg=#0ecaf1 guibg=NONE
60 |
61 |
62 | hi Pmenu guifg=#000000 guibg=#454545
63 | hi SignColumn guibg=#ffffff
64 | hi Title guifg=#000000
65 | hi LineNr guifg=#666666 guibg=#ffffff
66 | hi NonText guifg=#c481ff guibg=#ffffff
67 | hi Comment guifg=#c481ff gui=italic
68 | hi SpecialComment guifg=#c481ff gui=italic guibg=NONE
69 | hi CursorLine guibg=#454545
70 | hi TabLineFill gui=NONE guibg=#454545
71 | hi TabLine guifg=#666666 guibg=#454545 gui=NONE
72 | hi StatusLine gui=bold guibg=#454545 guifg=#000000
73 | hi StatusLineNC gui=NONE guibg=#ffffff guifg=#000000
74 | hi Search guibg=#c481ff guifg=#ffffff
75 | hi VertSplit gui=NONE guifg=#454545 guibg=NONE
76 | hi Visual gui=NONE guibg=#454545
77 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lsp/gopls.lua:
--------------------------------------------------------------------------------
1 | ---@brief
2 | ---
3 | --- https://github.com/golang/tools/tree/master/gopls
4 | ---
5 | --- Google's lsp server for golang.
6 |
7 | --- @class go_dir_custom_args
8 | ---
9 | --- @field envvar_id string
10 | ---
11 | --- @field custom_subdir string?
12 |
13 | local mod_cache = nil
14 | local std_lib = nil
15 |
16 | ---@param custom_args go_dir_custom_args
17 | ---@param on_complete fun(dir: string | nil)
18 | local function identify_go_dir(custom_args, on_complete)
19 | local cmd = { "go", "env", custom_args.envvar_id }
20 | vim.system(cmd, { text = true }, function(output)
21 | local res = vim.trim(output.stdout or "")
22 | if output.code == 0 and res ~= "" then
23 | if custom_args.custom_subdir and custom_args.custom_subdir ~= "" then
24 | res = res .. custom_args.custom_subdir
25 | end
26 | on_complete(res)
27 | else
28 | vim.schedule(function()
29 | vim.notify(
30 | ("[gopls] identify " .. custom_args.envvar_id .. " dir cmd failed with code %d: %s\n%s"):format(
31 | output.code,
32 | vim.inspect(cmd),
33 | output.stderr
34 | )
35 | )
36 | end)
37 | on_complete(nil)
38 | end
39 | end)
40 | end
41 |
42 | ---@return string?
43 | local function get_std_lib_dir()
44 | if std_lib and std_lib ~= "" then
45 | return std_lib
46 | end
47 |
48 | identify_go_dir({ envvar_id = "GOROOT", custom_subdir = "/src" }, function(dir)
49 | if dir then
50 | std_lib = dir
51 | end
52 | end)
53 | return std_lib
54 | end
55 |
56 | ---@return string?
57 | local function get_mod_cache_dir()
58 | if mod_cache and mod_cache ~= "" then
59 | return mod_cache
60 | end
61 |
62 | identify_go_dir({ envvar_id = "GOMODCACHE" }, function(dir)
63 | if dir then
64 | mod_cache = dir
65 | end
66 | end)
67 | return mod_cache
68 | end
69 |
70 | ---@param fname string
71 | ---@return string?
72 | local function get_root_dir(fname)
73 | if mod_cache and fname:sub(1, #mod_cache) == mod_cache then
74 | local clients = vim.lsp.get_clients({ name = "gopls" })
75 | if #clients > 0 then
76 | return clients[#clients].config.root_dir
77 | end
78 | end
79 | if std_lib and fname:sub(1, #std_lib) == std_lib then
80 | local clients = vim.lsp.get_clients({ name = "gopls" })
81 | if #clients > 0 then
82 | return clients[#clients].config.root_dir
83 | end
84 | end
85 | return vim.fs.root(fname, "go.work") or vim.fs.root(fname, "go.mod") or vim.fs.root(fname, ".git")
86 | end
87 |
88 | return {
89 | cmd = { "gopls" },
90 | filetypes = { "go", "gomod", "gowork", "gotmpl" },
91 | root_dir = function(bufnr, on_dir)
92 | local fname = vim.api.nvim_buf_get_name(bufnr)
93 | get_mod_cache_dir()
94 | get_std_lib_dir()
95 | -- see: https://github.com/neovim/nvim-lspconfig/issues/804
96 | on_dir(get_root_dir(fname))
97 | end,
98 | settings = {
99 | templateExtension = { "tmpl" },
100 | gofumpt = true,
101 | },
102 | }
103 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Jarmos's Dotfiles
2 |
3 | [](https://github.com/Jarmos-san/dotfiles/actions/workflows/qa-checks.yml)
4 | 
5 | 
6 | 
7 |
8 | This repository contains various "_dotfiles_" for my personal development needs.
9 | The said dotfiles are mostly configurations for the tools I use to write code on
10 | a daily basis.
11 |
12 | ## How to Use This Project
13 |
14 | The contents of this repository are **VERY** personalised & might not suit
15 | **YOUR** particular needs as-is. Hence, I strongly recommend to use the contents
16 | of this repository as a source of reference only.
17 |
18 | **DISCLAIMER**: Do not fork this repository & run the [scripts](./setup)
19 | provided here to setup your system. I'll not be held responsible for any
20 | potential data loss or system corruption in case something goes south when using
21 | the contents of this repository. Running the automation script below to setup
22 | everything:
23 |
24 | ```console
25 | curl -fsSL "https://tinyurl.com/setup-dotfile" | bash -c
26 | ```
27 |
28 |
29 | See screenshots of what the tools look like!
30 | Neovim:
31 |
32 | Wezterm:
33 |
34 | Starship:
35 |
36 |
37 |
38 |
39 | ## Acknowledgements
40 |
41 | The configurations I used are heavily inspired from other giants of the
42 | community. Following are some of the repositories I keep an eye out for
43 | inspiration.
44 |
45 | - Salomon Popp's [disrupted/dotfiles](https://github.com/disrupted/dotfiles)
46 | - Mathias Bynen's
47 | [mathiasbynens/dotfiles](https://github.com/mathiasbynens/dotfiles)
48 | - [codeinthehouse's gist](https://gist.githubusercontent.com/codeinthehole/26b37efa67041e1307db/raw/67c06401c3cdb7f7f96aa9054e95cbe0e473b7f0/osx_bootstrap.sh)
49 | - Dries Vints's [driesvints/dotfiles](https://github.com/driesvints/dotfiles)
50 | - Tom Payne's [twpayne/dotfiles](https://github.com/twpayne/dotfiles)
51 | - Maria José Solano's
52 | [MariaSolOs/dotfiles](https://github.com/MariaSolOs/dotfiles)
53 | - TJ Devrie's [kickstart.nvim](https://github.com/nvim-lua/kickstart.nvim)
54 |
55 | More will be added as & when I come across any.
56 |
57 | ## Terms & Conditions of Usage
58 |
59 | Everything in this repository is licensed under the T&Cs of a FOSS license. More
60 | specifically, the project is licensed under the T&Cs of the MIT License, so for
61 | more info on it, refer to the [LICENSE](./LICENSE). So feel free to copy &
62 | distribute any of the configurations I shared in this repository.
63 |
--------------------------------------------------------------------------------
/dotfiles/.config/git/config:
--------------------------------------------------------------------------------
1 | [init]
2 | defaultBranch = main
3 |
4 | [include]
5 | path = ~/.config/git/credentials
6 |
7 | [merge]
8 | tool = nvim
9 |
10 | [mergetool]
11 | keepBackup = false
12 | prompt = false
13 | keepTemporaries = false
14 |
15 | [mergetool "nvim"]
16 | ; INFO: More information about the following suggestions can be found at:
17 | ; https://smittie.de/posts/git-mergetool
18 | ; cmd = nvim -d $LOCAL $REMOTE $MERGED -c '$wincmd w' -c '$wincmd J'
19 | ; cmd = "nvim -d -c \"wincmd l\" -c \"normal ]c\" \"$LOCAL\" \"$MERGED\" \"$REMOTE\""
20 |
21 | ; NOTE: This is still experimental!!!
22 | ; cmd = "nvim -d '$LOCAL' '$MERGED' '$REMOTE' -c 'wincmd l' -c 'wincmd J'"
23 | ; Use the following repository to run some experiments
24 | ; https://github.com/redguardtoo/test-git-mergetool
25 |
26 | [push]
27 | default = current
28 |
29 | [core]
30 | editor = nvim
31 | pager = bat
32 | whitespace = fix
33 | excludesfile = '~/.config/git/ignore'
34 |
35 | [color "branch"]
36 | current = white magenta bold
37 | local = green bold
38 | remote = blue bold
39 | upstream = magenta bold
40 | plain = white bold
41 |
42 | [color "diff"]
43 | meta = yellow bold
44 | frag = magenta bold
45 | old = red bold
46 | new = green bold
47 | whitespace = red reverse
48 |
49 | [color "status"]
50 | added = green bold
51 | updated = yellow bold
52 | changed = red bold
53 | untracked = cyan black bold
54 | localBranch = cyan bold
55 | remoteBranch = red bold
56 |
57 | [commit]
58 | ; gpgSign = true
59 | ; TODO: Uncomment the following line after reconfigurng Git
60 | gpgSign = false
61 |
62 | [status]
63 | showStash = true
64 | relativepaths = false
65 |
66 | [tag]
67 | forceSignAnnotated = true
68 | gpgSign = false
69 |
70 | [url "git@github.com:"]
71 | insteadof = "gh:"
72 |
73 | [url "git@gist.github.com/"]
74 | insteadof = "gist:"
75 |
76 | [url "git@github.com:Jarmos-san/"]
77 | insteadof = "jarmos:"
78 |
79 | [url "git@github.com:"]
80 | insteadof = "https://github.com"
81 |
82 | [help]
83 | autocorrect = 1
84 |
85 | [color "status"]
86 | added = green bold
87 | updated = yellow bold
88 | changed = red bold
89 | untracked = cyan black bold
90 | localBranch = cyan bold
91 | remoteBranch = red bold
92 |
93 | [color "diff"]
94 | meta = yellow bold
95 | frag = magenta bold
96 | old = red bold
97 | new = green bold
98 | whitespace = red reverse
99 |
100 | [color "branch"]
101 | current = black magenta bold
102 | local = green bold
103 | remote = blue bold
104 | upstream = magenta bold
105 | plain = white bold
106 |
107 | [submodule]
108 | recurse = true
109 |
110 | [alias]
111 | st = status --short --branch --untracked-files=all
112 | ci = commit -m
113 | ca = commit -am
114 | cb = checkout -b
115 | pl = pull --rebase
116 | pu = push
117 | cl = clone
118 | vb = branch -vv
119 | rv = remote -v
120 | ra = remote add origin
121 | tar = archive --format=tar
122 | zip = archive --format=zip
123 | logs = log --pretty=oneline --max-count=20
124 |
--------------------------------------------------------------------------------
/dotfiles/.config/tmux/tmux.conf:
--------------------------------------------------------------------------------
1 | # Source the configuration file for the statusline
2 | source-file ~/.config/tmux/statusline/statusline.conf
3 |
4 | ### General Options ###
5 | # Use Vi style keybindings in copy mode (hjkl for navigation, v/y for selection)
6 | set-option -gw mode-keys vi
7 |
8 | # Default terminal type advertised to programs running inside Tmux
9 | set-option -g default-terminal "tmux-256color"
10 |
11 | # Start the window and pane numbering at 0 (instead of the default 0)
12 | set-option -g base-index 1
13 | set-option -g pane-base-index 1
14 |
15 | # Enable true colour (RGB) support for xterm-compatible terminals
16 | set-option -a terminal-features 'xterm-256color:RGB'
17 |
18 | # Allow applications inside Tmux to receive focus events (helps Neovim
19 | # auto-refresh LSP, adjust cursor shape and so on)
20 | set-option -g focus-events on
21 |
22 | ### Window / Pane Navigation ###
23 | # Move between windows with Ctrl+p / Ctrl + n (previous / next)
24 | bind-key C-p previous-window
25 | bind-key C-n next-window
26 |
27 | # Vim style pane navigation (prefix + hjkl)
28 | bind-key h select-pane -L # Left
29 | bind-key j select-pane -D # Down
30 | bind-key k select-pane -U # Up
31 | bind-key l select-pane -R # Right
32 |
33 | ### Copy Mode ###
34 | # Visual selection in copy mode (like Vim's v/V)
35 | bind-key -T copy-mode-vi v send -X begin-selection
36 | bind-key -T copy-mode-vi V send -X select-line
37 |
38 | if-shell "uname -r | grep -qEi 'microsoft|wsl'" {
39 | bind -T copy-mode-vi y send -X copy-pipe-and-cancel "clip.exe"
40 | } {
41 | if-shell "command -v wl-copy" {
42 | bind -T copy-mode-vi y send -X copy-pipe-and-cancel "wl-copy"
43 | } {
44 | bind -T copy-mode-vi y send -X copy-selection-and-cancel
45 | }
46 | }
47 |
48 | ### General QoL Improvements ###
49 | # Unbind the default prefix key and set Space as the custom prefix key instead
50 | unbind C-b
51 | set-option -g prefix C-Space
52 |
53 | # Reload the Tmux config file with prefix + R
54 | bind-key R source-file "~/.config/tmux/tmux.conf"\; display-message 'Reloaded Tmux configurations'
55 |
56 | # Kill the pane without confirmation
57 | bind-key X kill-pane
58 |
59 | # Kill the current session safely after transmitting an user prompt
60 | bind-key K confirm-before -p "Kill Session #S? (y/N)" kill-session
61 |
62 | # Set the status bar position to the top of the client
63 | set-option -g status-position top
64 |
65 | # Create panes in the same working directory
66 | bind-key '"' split-window -c "#{pane_current_path}" # Horizontal split
67 | bind-key % split-window -hc "#{pane_current_path}" # Vertical split
68 |
69 | # Create a new window (and immediately rename it) with the current directory
70 | bind-key c new-window -c "#{pane_current_path}" \; command-prompt "rename-window '%%'"
71 |
72 | # Set the value of EDITOR to 'nvim' (Neovim)
73 | set-environment -g EDITOR nvim
74 |
75 | # Set the colours for the Tmux command prompt
76 | set-option -g message-style "bg=#030007,fg=#cae2e6"
77 |
78 | # Set the colour of the clock on Tmux
79 | set-option -g clock-mode-colour "#c2e7d9"
80 |
81 | ### Configurations for the panes ###
82 | # Configure the display panes to be displayed on screen for 1.5s before disappearing
83 | set-option -g display-panes-time 1500
84 |
85 | # Add a high-contrast orange colour to the displayed pane
86 | set-option -g display-panes-color "orange"
87 |
88 | # Add a high contrast red colour to the currently active pane
89 | set-option -g display-panes-active-colour "green"
90 |
91 | # Set a thick border for the panes
92 | set-option -g pane-border-lines "heavy"
93 |
94 | # vim:ft=tmux
95 |
--------------------------------------------------------------------------------
/dotfiles/.config/starship/starship.toml:
--------------------------------------------------------------------------------
1 | "$schema" = 'https://starship.rs/config-schema.json'
2 |
3 | # Global/prompt-wide configurations
4 | command_timeout = 20000 # Increase the default timeout duration for long-running applications
5 |
6 | # palette = "catppuccin_macchiato"
7 |
8 | # Replace the "❯" symbol in the prompt with "➜"
9 | [character] # The name of the module we are configuring is "character"
10 | success_symbol = "[->](bold green)" # The "success_symbol" segment is being set to "➜" with the color "bold green"
11 | error_symbol = "[->](bold red)" # Similar to the "sucess_symbol" but in bright red
12 | vicmd_symbol = "[❮](green)"
13 |
14 | # Prompt customizations for Docker projects
15 | [docker_context]
16 | symbol = " " # Replaces the default emoji "🐳 "
17 |
18 | # Prompt customizations for projects which are packages
19 | # For more info on this module refer to the documentations at:
20 | # https://starship.rs/config/#package-version
21 | [package]
22 | symbol = " " # Replaces the default emoji "📦 "
23 |
24 | # Prompt customizations for Python projects
25 | [python]
26 | symbol = " " # Replaces the defailt emoji "🐍 "
27 |
28 | # Prompt customization for Version Control info with Git
29 | [git_branch]
30 | symbol = " " # Replaces the default emoji " "
31 |
32 | [directory]
33 | truncation_length = 4
34 | # Catppuccin 'lavender'
35 | style = "bold lavender"
36 |
37 | # palette tables should be last in the config ⚓️
38 | [palettes.catppuccin_macchiato]
39 | rosewater = "#f4dbd6"
40 | flamingo = "#f0c6c6"
41 | pink = "#f5bde6"
42 | mauve = "#c6a0f6"
43 | red = "#ed8796"
44 | maroon = "#ee99a0"
45 | peach = "#f5a97f"
46 | yellow = "#eed49f"
47 | green = "#a6da95"
48 | teal = "#8bd5ca"
49 | sky = "#91d7e3"
50 | sapphire = "#7dc4e4"
51 | blue = "#8aadf4"
52 | lavender = "#b7bdf8"
53 | text = "#cad3f5"
54 | subtext1 = "#b8c0e0"
55 | subtext0 = "#a5adcb"
56 | overlay2 = "#939ab7"
57 | overlay1 = "#8087a2"
58 | overlay0 = "#6e738d"
59 | surface2 = "#5b6078"
60 | surface1 = "#494d64"
61 | surface0 = "#363a4f"
62 | base = "#24273a"
63 | mantle = "#1e2030"
64 | crust = "#181926"
65 |
66 | [palettes.catppuccin_frappe]
67 | rosewater = "#f2d5cf"
68 | flamingo = "#eebebe"
69 | pink = "#f4b8e4"
70 | mauve = "#ca9ee6"
71 | red = "#e78284"
72 | maroon = "#ea999c"
73 | peach = "#ef9f76"
74 | yellow = "#e5c890"
75 | green = "#a6d189"
76 | teal = "#81c8be"
77 | sky = "#99d1db"
78 | sapphire = "#85c1dc"
79 | blue = "#8caaee"
80 | lavender = "#babbf1"
81 | text = "#c6d0f5"
82 | subtext1 = "#b5bfe2"
83 | subtext0 = "#a5adce"
84 | overlay2 = "#949cbb"
85 | overlay1 = "#838ba7"
86 | overlay0 = "#737994"
87 | surface2 = "#626880"
88 | surface1 = "#51576d"
89 | surface0 = "#414559"
90 | base = "#303446"
91 | mantle = "#292c3c"
92 | crust = "#232634"
93 |
94 | [palettes.catppuccin_latte]
95 | rosewater = "#dc8a78"
96 | flamingo = "#dd7878"
97 | pink = "#ea76cb"
98 | mauve = "#8839ef"
99 | red = "#d20f39"
100 | maroon = "#e64553"
101 | peach = "#fe640b"
102 | yellow = "#df8e1d"
103 | green = "#40a02b"
104 | teal = "#179299"
105 | sky = "#04a5e5"
106 | sapphire = "#209fb5"
107 | blue = "#1e66f5"
108 | lavender = "#7287fd"
109 | text = "#4c4f69"
110 | subtext1 = "#5c5f77"
111 | subtext0 = "#6c6f85"
112 | overlay2 = "#7c7f93"
113 | overlay1 = "#8c8fa1"
114 | overlay0 = "#9ca0b0"
115 | surface2 = "#acb0be"
116 | surface1 = "#bcc0cc"
117 | surface0 = "#ccd0da"
118 | base = "#eff1f5"
119 | mantle = "#e6e9ef"
120 | crust = "#dce0e8"
121 |
122 | [palettes.catppuccin_mocha]
123 | rosewater = "#f5e0dc"
124 | flamingo = "#f2cdcd"
125 | pink = "#f5c2e7"
126 | mauve = "#cba6f7"
127 | red = "#f38ba8"
128 | maroon = "#eba0ac"
129 | peach = "#fab387"
130 | yellow = "#f9e2af"
131 | green = "#a6e3a1"
132 | teal = "#94e2d5"
133 | sky = "#89dceb"
134 | sapphire = "#74c7ec"
135 | blue = "#89b4fa"
136 | lavender = "#b4befe"
137 | text = "#cdd6f4"
138 | subtext1 = "#bac2de"
139 | subtext0 = "#a6adc8"
140 | overlay2 = "#9399b2"
141 | overlay1 = "#7f849c"
142 | overlay0 = "#6c7086"
143 | surface2 = "#585b70"
144 | surface1 = "#45475a"
145 | surface0 = "#313244"
146 | base = "#1e1e2e"
147 | mantle = "#181825"
148 | crust = "#11111b"
149 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/options.lua:
--------------------------------------------------------------------------------
1 | local opt = vim.opt
2 |
3 | -- Sync the system clipboard with Neovim
4 | opt.clipboard = "unnamedplus"
5 |
6 | -- Enable the global status line
7 | opt.laststatus = 2
8 |
9 | -- Make the autocompletion window more accessible
10 | opt.completeopt = "menu,menuone,noselect"
11 |
12 | -- Hide the * markups for bold & italics
13 | opt.conceallevel = 3
14 |
15 | -- Case-insensitive searching UNLESS \C or one or more capital letters in the search term
16 | opt.ignorecase = true
17 | opt.smartcase = true
18 |
19 | -- Preview substitutions as its typed
20 | opt.inccommand = "split"
21 |
22 | -- The language to use when spelling checking
23 | opt.spelllang = { "en" }
24 |
25 | -- Configure how new splits should be opened
26 | opt.splitbelow = true
27 | opt.splitright = true
28 |
29 | -- Decrease mapped sequence wait time to display which-key popup sooner
30 | opt.timeoutlen = 300
31 |
32 | -- Save undo history
33 | opt.undofile = true
34 | opt.undolevels = 10000
35 |
36 | -- Save swap file & trigger CursorHold
37 | opt.updatetime = 200
38 |
39 | -- Command-line completion mode
40 | opt.wildmode = "longest:full,full"
41 |
42 | -- Maximum window width
43 | opt.winminwidth = 5
44 |
45 | --Disable swapfile creation since it gets annoying after a while
46 | opt.swapfile = false
47 |
48 | -- Configure Neovim to highlight the current location of the cursor
49 | opt.cursorline = true
50 |
51 | -- True color support for various plugins
52 | opt.termguicolors = true
53 |
54 | -- Make the completion popup window a bit transparent
55 | opt.pumblend = 10
56 |
57 | -- Display only 10 rows for the completion menu
58 | opt.pumheight = 10
59 |
60 | -- Disable showing the current mode since its already visible on the statusline
61 | opt.showmode = false
62 |
63 | -- Disable prompting the invoked command back to the user
64 | opt.showcmd = false
65 |
66 | -- Disable showing the current location of the cursor since the Lualine plugin takes care of it
67 | opt.ruler = false
68 |
69 | -- Configure Neovim to not wrap the contents of the buffer
70 | opt.wrap = false
71 |
72 | -- Add a slight padding to wrapped lines to distinguish them from the rest of the lines
73 | opt.showbreak = "...."
74 |
75 | -- Save the contents of the buffer after exiting Insert mode
76 | opt.autowrite = true
77 |
78 | -- Prompt to save the contents of the buffer before exiting
79 | opt.confirm = true
80 |
81 | -- Enable horinzontal scrolling when word wrap is disabled
82 | opt.sidescroll = 8
83 |
84 | -- FIXME: The following option might only be useful in certain filetypes like JSX, Markdown and such
85 | -- Make Neovim recognise dash-seperated words as a single word
86 | opt.iskeyword:append("-")
87 |
88 | -- Maintain a buffer of rows between the current row & the either ends of the window
89 | opt.scrolloff = 6
90 |
91 | -- Enable the current line number to be shown
92 | opt.number = true
93 | opt.relativenumber = true
94 |
95 | -- Allow the sign column to show else it'll keep shifting later on
96 | opt.signcolumn = "yes"
97 |
98 | -- Explicitly tell Neovim to use ZSH for terminal commands instead of relying on $SHELL
99 | opt.shell = "zsh"
100 |
101 | -- Enable break indent
102 | vim.opt.breakindent = true
103 |
104 | -- Sets how neovim will display certain whitespace characters in the editor.
105 | vim.opt.list = true
106 | vim.opt.listchars = { tab = "» ", trail = "·", nbsp = "␣" }
107 |
108 | -- These conditional lines of code are necessary when using Neovim from within WSL2. See ":h clipboard-wsl" for info
109 | if vim.fn.has("wsl") == 1 then
110 | vim.g.clipboard = {
111 | name = "WslClipboard",
112 | copy = {
113 | ["+"] = "clip.exe",
114 | ["*"] = "clip.exe",
115 | },
116 | paste = {
117 | ["+"] = [[powershell.exe -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))]],
118 | ["*"] = [[powershell.exe -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))]],
119 | },
120 | cache_enabled = 0,
121 | }
122 | end
123 |
124 | -- Disable the "~" lines on the left side column shown only the end of buffer is reached
125 | vim.opt.fillchars = "eob: "
126 |
127 | -- Remove the command line section completely!
128 | vim.opt.cmdheight = 1
129 |
130 | -- Add borders for all floating windows
131 | vim.opt.winborder = "rounded"
132 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/keymaps.lua:
--------------------------------------------------------------------------------
1 | -- Module of keymaps & bindings which makes using Neovim a pleasure
2 |
3 | local telescope = require("telescope.builtin")
4 | local utils = require("utils")
5 | local map = require("utils").map
6 | local terminal = require("terminal").setup
7 |
8 | -- Open the starter dashboard if the buffer list is empty
9 | local open_starter_if_empty_buffer = function()
10 | local buf_id = vim.api.nvim_get_current_buf()
11 | local is_empty = vim.api.nvim_buf_get_name(buf_id) == "" and vim.bo[buf_id].filetype == ""
12 | if not is_empty then
13 | return
14 | end
15 |
16 | require("mini.starter").open()
17 | vim.cmd(buf_id .. "bwipeout")
18 | end
19 |
20 | -- Delete all buffers and open the starter dashboard
21 | local bdelete = function()
22 | require("mini.bufremove").delete()
23 | open_starter_if_empty_buffer()
24 | end
25 |
26 | -- Use the ":Telescope git_files" command if the current directory is version controlled with Git
27 | local git_files = function()
28 | if utils.is_git_repo() or utils.has_git_dir() then
29 | telescope.git_files()
30 | end
31 | end
32 |
33 | -- Change to Normal mode by pressing "jk" in quick succession
34 | map("i", "jk", "", { desc = "Change to Normal mode" })
35 |
36 | -- Easier navigation to the beginning or the start of the line
37 | map("n", "H", "", { desc = "Move to the beginning of the line" })
38 | map("n", "L", "", { desc = "Move to the end of the line" })
39 |
40 | -- Resize windows using
41 | map("n", "", "resize +2", { desc = "Increase window height" })
42 | map("n", "", "resize -2", { desc = "Decrease window height" })
43 | map("n", "", "vertical resize +2", { desc = "Increase window width" })
44 | map("n", "", "vertical resize -2", { desc = "Increase window width" })
45 |
46 | -- Better & easier indenting
47 | map("v", "<", "", ">gv")
49 |
50 | -- Disable the redundant (and sometimes annoying "Ex mode")
51 | -- INFO: See the docs at ":h gQ" for more info on what its supposed to do
52 | map("n", "gQ", "")
53 |
54 | -- Easier navigation in Insert mode without the arrow keys!
55 | map("i", "", "", { desc = "Move left in Insert mode" })
56 | map("i", "", "", { desc = "Move down in Insert mode" })
57 | map("i", "", "", { desc = "Move up in Insert mode" })
58 | map("i", "", "", { desc = "Move right in Insert mode" })
59 |
60 | -- List all available files (and directories) using Telescope
61 | map("n", "ff", telescope.find_files, { desc = "List all available files/directories" })
62 | map("n", "gf", git_files, { desc = "List all files and folders tracked inside the Git repository" })
63 | map("n", "of", telescope.oldfiles, { desc = "Open recently opened files" })
64 |
65 | -- Delete the buffer contents from the Neovim session
66 | map("n", "bd", bdelete, { desc = "Delete the buffer contents from the Neovim session" })
67 |
68 | -- List all currently loaded buffers
69 | map("n", "b", telescope.buffers, { desc = "List all currently in-memory loaded buffers" })
70 |
71 | -- Navigate easier around buffers while using the "leader" key
72 | map("n", "bn", "bnext", { desc = "Change to the next buffer" })
73 | map("n", "bp", "bprevious", { desc = "Change to the previous buffer" })
74 |
75 | -- Visually list in Telescope all the currently registered marks on the current buffer
76 | map("n", "m", telescope.marks, { desc = "List all Vim marks registered on the current buffer" })
77 |
78 | -- List all the registers available on the buffer
79 | map("n", "r", telescope.registers, { desc = "Show the contents of the registers" })
80 |
81 | -- Open Telescope to fuzzy search through the help docs
82 | map("n", "h", telescope.help_tags, { desc = "Open the help tags menu" })
83 |
84 | -- Grep through the contents of the current directory for a particular string pattern
85 | map("n", "lg", telescope.live_grep, { desc = "Perform a grep on the file contents of the current directory" })
86 |
87 | -- Open a Terminal inside Neovim itself
88 | map("n", "t", terminal.float, { desc = "Open the terminal prompt in a horizontal split" })
89 | map("n", "tv", terminal.vertical, { desc = "Open the terminal prompt in vertical split" })
90 | map({ "n", "i" }, "", terminal.toggle, { desc = "Toggle a floating terminal open/close" })
91 |
92 | -- Exit terminal mode in builtin terminal with an easier to use shortcut
93 | map("t", "jk", "", { desc = "Exit terminal mode" })
94 |
95 | -- Open a list of keymaps which can be fuzzy-searched using the Telescope UI
96 | map("n", "k", telescope.keymaps, { desc = "Open a list of available keymaps" })
97 |
--------------------------------------------------------------------------------
/dotfiles/.config/tmux/statusline/battery-status:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | ###############################################################################
4 | #
5 | # Battery Status Check
6 | #
7 | # This script prints the battery charge percentage of the system Tmux is
8 | # running on and it is designed to:
9 | # - Detect whether Tmux is running inside a WSL2 distribution.
10 | # - Fetch the battery percentage using the relevant API available on the
11 | # system for e.g. using PowerShell in WSL2.
12 | # - Print the battery percentage with an appropriate glyph (Nerd Font
13 | # required).
14 | #
15 | # **NOTE**: The script is intended to be run when initialising a Tmux
16 | # environment. Executing the script in a standalone manner may yield unexpected
17 | # results.
18 | #
19 | # Author: Somraj Saha (contact@jarmos.dev)
20 | #
21 | # License: MIT License (https://github.com/Jarmos-san/dotfiles?tab=MIT-1-ov-file#readme)
22 | #
23 | ###############################################################################
24 |
25 | import os
26 | import platform
27 | import subprocess
28 |
29 |
30 | def battery_wsl2() -> str:
31 | """Retrieve the remaining battery percentage from the WSL2 environment.
32 |
33 | This function invokes a PowerShell command to query the `Win32_Battery` CIM
34 | instance and extract the `EstimatedChargeRemaining` property which
35 | represents the current battery charge.
36 |
37 | Returns:
38 | str: The remaining battery percentage as a string (without the "%").
39 |
40 | Raises:
41 | subprocess.ChildProcessError: If the PowerShell command fails.
42 | Exception: Any unexpected errors during command execution.
43 | """
44 | try:
45 | output = subprocess.check_output(
46 | [
47 | "powershell.exe",
48 | "-Command",
49 | "Get-CimInstance -ClassName Win32_Battery | ",
50 | "Select-Object -ExpandProperty EstimatedChargeRemaining",
51 | ],
52 | )
53 | return output.decode("utf-8").strip().replace("\r", "")
54 | except Exception:
55 | raise
56 |
57 |
58 | def is_charging() -> bool:
59 | """Retrieve the raw battery status code from Windows using PowerShell.
60 |
61 | This function executes a PowerShell command via `powershell.exe` to query the
62 | `Win32_Battery` WMI class. It returns the `BatteryStatus` value as a string.
63 |
64 | Returns:
65 | str: The battery status code returned by Windows:
66 | - "1" = Discharging
67 | - "2" = Charging (on AC power)
68 | - "3" = Fully Charged
69 | - Other codes may indicate low battery, unknown, etc.
70 |
71 | Raises:
72 | subprocess.CalledProcessError: If the PowerShell command fails.
73 | """
74 | try:
75 | command = subprocess.check_output(
76 | [
77 | "powershell.exe",
78 | "-Command",
79 | "Get-CimInstance -ClassName Win32_Battery | ",
80 | "Select-Object -ExpandProperty BatteryStatus",
81 | ]
82 | )
83 | except Exception:
84 | raise
85 |
86 | output = command.decode().strip().replace("\r", "")
87 |
88 | return output == "2"
89 |
90 |
91 | def battery_percent_printer(battery_percent: int) -> None:
92 | """Print a symbolic representation of a battery percentage.
93 |
94 | Args:
95 | battery_percent (int): The current battery charge (0-100 inclusive).
96 |
97 | Behavior:
98 | - Maps the percentage to one of ten predefined symbols, each covering
99 | a 10% range of the battery level.
100 | - Prints the symbol followed by the percentage value.
101 | - If `battery_percent` is outside the valid range, prints an error symbol.
102 | """
103 | if is_charging():
104 | symbols = ["", "", "", "", "", "", "", "", "", ""]
105 | else:
106 | symbols = ["", "", "", "", "", "", "", "", "", ""]
107 |
108 | if 0 <= battery_percent <= 100:
109 | index = min(battery_percent // 10, 9)
110 | print(f"{symbols[index]} {battery_percent}%")
111 | else:
112 | print("")
113 |
114 |
115 | def main() -> None:
116 | """Entrypoint of the script.
117 |
118 | Detects the current platform and determines whether the environment is
119 | WLS2. If so, fetches and prints the battery percentage otherwise prints a
120 | placeholder string.
121 | """
122 | system = platform.system()
123 |
124 | battery_percent = None
125 | if system == "Linux":
126 | try:
127 | with open("/proc/version") as file:
128 | if "microsoft" in file.read() and os.getenv("WSL_INTEROP"):
129 | battery_percent = int(battery_wsl2())
130 | except FileNotFoundError as err:
131 | raise err
132 |
133 | if battery_percent:
134 | battery_percent_printer(battery_percent)
135 |
136 |
137 | if __name__ == "__main__":
138 | main()
139 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/luasnippets/python.lua:
--------------------------------------------------------------------------------
1 | local luasnip = require("luasnip")
2 | local snippet = luasnip.snippet
3 | local insert_node = luasnip.insert_node
4 | local fmt = require("luasnip.extras.fmt").fmt
5 |
6 | return {
7 | -- Define the snippet for Python function definitions
8 | snippet(
9 | { trig = "def", desc = "Create a Python function definition" },
10 | fmt( -- The format of the snippet
11 | [[
12 | def {1}({2}: {3}) -> {4}:
13 | """{5}.
14 |
15 | Args:
16 | {2}: {6}.
17 |
18 | Returns:
19 | {4}: {7}
20 |
21 | Raises:
22 | {8}
23 | """
24 | {9}
25 | ]],
26 | { -- The node of the snippet to replace content with
27 | insert_node(1, "function_name"),
28 | insert_node(2, "arg"),
29 | insert_node(3, "ArgumentType"),
30 | insert_node(4, "ReturnType"),
31 | insert_node(5, "Describe the function briefly."),
32 | insert_node(6, "Explain the argument briefly."),
33 | insert_node(7, "Explain the return type briefly."),
34 | insert_node(8, "Exception"),
35 | insert_node(9, ""),
36 | },
37 | {
38 | repeat_duplicates = true, -- Ensure duplicates content are copied as-is
39 | }
40 | )
41 | ),
42 |
43 | -- Define the snippet for Python classes
44 | snippet(
45 | { trig = "class", desc = "Create a Python class implementation" },
46 | fmt(
47 | [[
48 | class {1}({2}):
49 | """{3}"""
50 |
51 | {4}
52 | ]],
53 | {
54 | insert_node(1, "ClassName"),
55 | insert_node(2, "ParentClassName"),
56 | insert_node(3, "Briefly describe the class and its characteristics."),
57 | insert_node(4, ""),
58 | }
59 | )
60 | ),
61 |
62 | -- Snippet for the "if __name__ == '__main__:' logic"
63 | snippet(
64 | { trig = "__main__", desc = "Create logic to invoke the Python script with apt shebang" },
65 | fmt(
66 | [[
67 | if __name__ == '__main__':
68 | main()
69 | ]],
70 | {}
71 | )
72 | ),
73 |
74 | -- Snippet for the "__repr__" function
75 | snippet(
76 | { trig = "__repr__", desc = "Implement a class's __repr__ method" },
77 | fmt(
78 | [[
79 | def __repr__(self) -> str:
80 | """{1}"""
81 | return f"{{{2}}}"
82 | ]],
83 | {
84 | insert_node(1, "Return a string representation of the class instance for debugging."),
85 | insert_node(2, ""),
86 | }
87 | )
88 | ),
89 |
90 | -- Snippet for if-else statements
91 | snippet(
92 | { trig = "if-else", desc = 'Create an "if-else" logic block' },
93 | fmt(
94 | [[
95 | if {1}:
96 | {2}
97 | else:
98 | {3}
99 | ]],
100 | {
101 | insert_node(1, ""),
102 | insert_node(2, ""),
103 | insert_node(3, ""),
104 | }
105 | )
106 | ),
107 |
108 | -- Snippets for match-case statements
109 | snippet(
110 | { trig = "match", desc = "Create a match statement" },
111 | fmt(
112 | [[
113 | match {1}:
114 | case {2}:
115 | {3}
116 | case _:
117 | {4}
118 | ]],
119 | {
120 | insert_node(1, ""),
121 | insert_node(2, ""),
122 | insert_node(3, ""),
123 | insert_node(4, ""),
124 | }
125 | )
126 | ),
127 |
128 | -- Snippets for creating Pyright directives
129 | snippet(
130 | { trig = "pyright", desc = "Create a Pyright directive" },
131 | fmt(
132 | [[
133 | # pyright: ignore[{1}]
134 | ]],
135 | { insert_node(1, "directive") }
136 | )
137 | ),
138 |
139 | -- Snippets for creating "noqa" directives (possibly used by tools like Ruff)
140 | snippet(
141 | { trig = "noqa", desc = "Create a directive for tools like Ruff" },
142 | fmt(
143 | [[
144 | # noqa: {1}
145 | ]],
146 | { insert_node(1, "directive") }
147 | )
148 | ),
149 |
150 | -- Snippet to generate a testcase function
151 | snippet(
152 | { trig = "testfunc", desc = "Create a testcase function" },
153 | fmt(
154 | [[
155 | def test_{1}() -> None:
156 | """{2}"""
157 | {3}
158 | assert False
159 | ]],
160 | { insert_node(1, ""), insert_node(2, "A brief test case function description."), insert_node(3, "") }
161 | )
162 | ),
163 |
164 | -- Snippet to generate a testcase class
165 | snippet(
166 | { trig = "testclass", desc = "Create a test class" },
167 | fmt(
168 | [[
169 | class Test{1}():
170 | """{2}"""
171 |
172 | def {3}(self) -> {4}:
173 | """{5}"""
174 | return {4}
175 |
176 | def test_{6}(self) -> None:
177 | """{7}"""
178 | {8}
179 | assert False
180 | ]],
181 | {
182 | insert_node(1, ""),
183 | insert_node(2, "Describe the test class"),
184 | insert_node(3, "fixture"),
185 | insert_node(4, "ReturnType"),
186 | insert_node(5, "Describe the fixture"),
187 | insert_node(6, ""),
188 | insert_node(7, "Describe the test function"),
189 | insert_node(8, ""),
190 | }
191 | )
192 | ),
193 | }
194 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/plugins/lspconfig.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring the plugin responsible for handling LSP configurations
2 |
3 | return {
4 | -- Official plugin for more ease in configuring the in-built LSP client.
5 | "neovim/nvim-lspconfig",
6 | event = "LspAttach",
7 | init = function()
8 | vim.opt.updatetime = 250 -- Make Neovim to display the diagnostic hover window as fast as possible.
9 | -- Setup the LSP plugin to log only error messages else the log file grows too large eventually!
10 | vim.lsp.set_log_level(vim.log.levels.ERROR)
11 | vim.diagnostic.config({
12 | underline = true, -- Show diagnostic errors with a squigly underline
13 | update_in_insert = true, -- Update the diagnostic message even when in Insert mode
14 | severity_sort = true, -- Configure Neovim to sort the error messages according to the severity.
15 | })
16 | end,
17 | config = function()
18 | local map = require("utils").map
19 | local telescope = require("telescope.builtin")
20 |
21 | -- Add rounded borders to the LSP flaoting windows
22 | require("lspconfig.ui.windows").default_options.border = "rounded"
23 |
24 | local on_attach = function()
25 | map("n", "gd", telescope.lsp_definitions, { desc = "Jump to the object definition" })
26 | map("n", "gD", vim.lsp.buf.declaration, { desc = "Jump to the object declaration" })
27 | map("n", "gT", telescope.lsp_type_definitions, { desc = "Get the type documentations" })
28 | map("n", "gi", vim.lsp.buf.implementation, { desc = "Jump to the implementation" })
29 | map("n", "K", vim.lsp.buf.hover, { desc = "Open the documentations of the object" })
30 | map("n", "", vim.lsp.buf.signature_help, { desc = "Get the help documentations" })
31 | map("n", "gr", vim.lsp.buf.rename, { desc = "Rename the object under the cursor" })
32 | map("n", "gR", telescope.lsp_references, { desc = "Jump to the reference of the object" })
33 | map("n", "gra", vim.lsp.buf.code_action, { desc = "Open available code actions" })
34 | map("n", "wa", vim.lsp.buf.add_workspace_folder, { desc = "Add workspace folder" })
35 | map("n", "wr", vim.lsp.buf.remove_workspace_folder, { desc = "Remove workspace folder" })
36 | map("n", "wl", vim.lsp.buf.list_workspace_folders, { desc = "List workspace folders" })
37 | end
38 |
39 | local capabilities = require("blink.cmp").get_lsp_capabilities()
40 |
41 | -- INFO: Necessary configuration for the JSON LSP server. See the following URL for more information:
42 | -- https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#jsonls
43 | capabilities.textDocument.completion.completionItem.snippetSupport = true
44 |
45 | --[[
46 | -- Configurations required for the Vue LSP server to work as expected
47 | --]]
48 | -- Path to the LSP server executable
49 | local vue_language_server_path = vim.fn.stdpath("data")
50 | .. "/mason/packages/vue-language-server/node_modules/@vue/language-server"
51 |
52 | -- Configuration to initialise the 'vtsls' LSP server with
53 | -- NOTE: The VUe LSP server does not work as expected with the official `tsserver`
54 | local vtsls_config = {
55 | filetypes = { "typescript", "javascript", "javascriptreact", "typescriptreact", "vue" },
56 | settings = {
57 | vtsls = {
58 | tsserver = {
59 | globalPlugins = {
60 | {
61 | name = "@vue/typescript-plugin",
62 | location = vue_language_server_path,
63 | languages = { "vue" },
64 | configNamespace = "typescript",
65 | },
66 | },
67 | },
68 | },
69 | },
70 | }
71 |
72 | -- Configurations the Vue LSP is supposed to be initialised with
73 | local vue_ls_config = {
74 | on_init = function(client)
75 | client.handlers["tsserver/request"] = function(_, result, context)
76 | local clients = vim.lsp.get_clients({ bufnr = context.bufnr, name = "vtsls" })
77 | if #clients == 0 then
78 | vim.notify("Could not find `vtsls` LSP client, `vue_ls` would not work without it.", vim.log.levels.ERROR)
79 | return
80 | end
81 |
82 | local ts_client = clients[1]
83 |
84 | local param = unpack(result)
85 | local id, command, payload = unpack(param)
86 | ts_client:exec_cmd({
87 | title = "vue_request_forward",
88 | command = "typescript.tsserverRequest",
89 | arguments = {
90 | command,
91 | payload,
92 | },
93 | }, {
94 | bufnr = context.bufnr,
95 | }, function(_, r)
96 | local response_data = { {
97 | id,
98 | r.body,
99 | } }
100 | client:notify("tsserver/response", response_data)
101 | end)
102 | end
103 | end,
104 | }
105 |
106 | vim.lsp.config("vtsls", vtsls_config)
107 | vim.lsp.config("vue_ls", vue_ls_config)
108 | vim.lsp.enable({ "vtsls", "vue_ls" })
109 |
110 | -- Enable the LSP for Ansible work
111 | vim.lsp.config("ansiblels", {
112 | on_attach = on_attach,
113 | capabilities = capabilities,
114 | })
115 | end,
116 | dependencies = {
117 | -- This plugin needs to be loaded as well otherwise Neovim can't find the LSP binary on $PATH.
118 | "williamboman/mason.nvim",
119 | },
120 | }
121 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/autocmds.lua:
--------------------------------------------------------------------------------
1 | -- Module for configuring some global autocommand which will always be loaded at startup
2 |
3 | local autocmd = require("utils").autocmd
4 | local augroup = require("utils").augroup
5 |
6 | autocmd("TextYankPost", {
7 | desc = "Highlight the yanked text for a specified time.",
8 | group = augroup("yank_highlight"),
9 | callback = function()
10 | vim.highlight.on_yank({ timeout = 250 }) -- Keep the highlight for 250ms after yanking.
11 | end,
12 | })
13 |
14 | autocmd("TermOpen", {
15 | desc = "Get into Insert mode when the terminal is opened",
16 | group = augroup("terminal_insert"),
17 | callback = function()
18 | vim.opt.number = false
19 | vim.opt.relativenumber = false
20 | vim.cmd("startinsert | 1")
21 | end,
22 | })
23 |
24 | autocmd("FocusLost", {
25 | desc = "Save/write all unsaved buffers when focus is lost",
26 | group = augroup("save_buffers"),
27 | pattern = "*",
28 | command = "silent! wall",
29 | })
30 |
31 | autocmd("BufReadPost", {
32 | desc = "Jump to the last known position of a file before closing it",
33 | group = augroup("buffer_checkpoint"),
34 | callback = function()
35 | local mark = vim.api.nvim_buf_get_mark(0, '"')
36 | local line_count = vim.api.nvim_buf_line_count(0)
37 |
38 | if mark[1] > 0 and mark[1] <= line_count then
39 | pcall(vim.api.nvim_win_set_cursor, 0, mark)
40 | end
41 | end,
42 | })
43 |
44 | autocmd("VimResized", {
45 | desc = "Resize the splits if the window is resized",
46 | group = augroup("resize_splits"),
47 | callback = function()
48 | vim.cmd("tabdo wincmd =")
49 | end,
50 | })
51 |
52 | autocmd("FileType", {
53 | desc = "Close some filtypes simply by pressing 'q'",
54 | group = augroup("close_with_q"),
55 | pattern = { "checkhealth", "help", "lspinfo", "man", "notify", "qf", "query" },
56 | callback = function(event)
57 | vim.bo[event.buf].buflisted = false
58 | vim.keymap.set("n", "q", "close", { buffer = event.buf, silent = true })
59 | end,
60 | })
61 |
62 | autocmd({ "CursorMoved", "CursorMovedI" }, {
63 | desc = "Redraw the cursorline when navigating around the buffer",
64 | group = augroup("cursorline_number"),
65 | callback = function()
66 | if vim.wo.cursorline then
67 | vim.cmd("redraw")
68 | end
69 | end,
70 | })
71 |
72 | autocmd("BufNewFile", {
73 | desc = "Create an EditorConfig file",
74 | group = augroup("editorconfig_template"),
75 | pattern = "**/.editorconfig",
76 | command = "0r ~/.config/nvim/skeletons/editorconfig.txt",
77 | })
78 |
79 | autocmd("BufNewFile", {
80 | desc = "Create a simple README.md file",
81 | group = augroup("readme_template"),
82 | pattern = "**/README.md",
83 | command = "0r ~/.config/nvim/skeletons/readme.md",
84 | })
85 |
86 | autocmd("BufNewFile", {
87 | desc = "Create a Dependabot configuration file",
88 | group = augroup("dependabot_template"),
89 | pattern = "**/.github/dependabot.yml",
90 | command = "0r ~/.config/nvim/skeletons/dependabot.yml",
91 | })
92 |
93 | autocmd("BufNewFile", {
94 | desc = "Create a GitHub Workflow file",
95 | group = augroup("github_workflow_template"),
96 | pattern = "**/.github/workflows/*.yml",
97 | command = "0r ~/.config/nvim/skeletons/github-workflow.yml",
98 | })
99 |
100 | autocmd("BufNewFile", {
101 | desc = "Create a template Taskfile.yml",
102 | group = augroup("taskfile_template"),
103 | pattern = "**/Taskfile.yml",
104 | command = "0r ~/.config/nvim/skeletons/taskfile.yml",
105 | })
106 |
107 | autocmd("BufNewFile", {
108 | desc = "Create an entrypoint file for Python projects",
109 | group = augroup("python_entrypoint_file"),
110 | pattern = "**/main.py",
111 | command = "0r ~/.config/nvim/skeletons/main.py",
112 | })
113 |
114 | autocmd("BufNewFile", {
115 | desc = "Create a LICENSE Plain-Text file for projects on GitHub",
116 | group = augroup("license_template"),
117 | pattern = "**/LICENSE",
118 | command = "0r ~/.config/nvim/skeletons/license.txt",
119 | })
120 |
121 | autocmd("BufNewFile", {
122 | desc = "Create a Vue SFC",
123 | group = augroup("vue_sfc_template"),
124 | pattern = "*.vue",
125 | command = "0r ~/.config/nvim/skeletons/sfc.vue",
126 | })
127 |
128 | autocmd("TermClose", {
129 | desc = "Delete the terminal buffer when the process exits",
130 | group = augroup("terminal_close"),
131 | callback = function()
132 | vim.cmd("bdelete")
133 | end,
134 | })
135 |
136 | autocmd("BufWritePre", {
137 | desc = "Trim training whitespace after writing the contents of a buffer",
138 | group = augroup("trim_trailing_whitespace"),
139 | pattern = "*",
140 | command = "%s/\\s\\+$//e",
141 | })
142 |
143 | -- Autocommand to apply the highlights while performing a search and replace action
144 | autocmd("CmdlineEnter", {
145 | desc = "Apply highlights during search and replace",
146 | group = augroup("apply_highlights"),
147 | pattern = { "/", "?" },
148 | callback = function()
149 | vim.o.hlsearch = true
150 | end,
151 | })
152 |
153 | -- Autocommand to clear the highlights after performing a search and replace action
154 | autocmd("CmdlineLeave", {
155 | desc = "Clear highlights after search and replace",
156 | group = augroup("clear_highlights"),
157 | pattern = { "/", "?" },
158 | callback = function()
159 | vim.o.hlsearch = false
160 | end,
161 | })
162 |
163 | -- Autocommand to apply custom highlights after the colorscheme is applied
164 | autocmd("ColorScheme", {
165 | desc = "Apply custom highlights after colorscheme",
166 | group = augroup("apply_custom_highlights"),
167 | callback = function()
168 | require("highlights").setup()
169 | end,
170 | })
171 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/lua/statusline.lua:
--------------------------------------------------------------------------------
1 | -- This is a WORK-IN-PROGRESS custom implementation of a statusline.
2 | -- Once complete, it'll replace the lualine plugin
3 | -- Inspirational resources are as follows:
4 | -- https://nuxsh.is-a.dev/blog/custom-nvim-statusline.html
5 | -- https://elianiva.my.id/posts/neovim-lua-statusline/
6 |
7 | ---@class Statusline
8 | ---@field render fun(): string
9 | ---@field setup fun(): nil
10 | local M = {}
11 |
12 | ---@return nil
13 | local define_highlight_groups = function()
14 | vim.api.nvim_set_hl(0, "StatuslineModeNormal", { fg = "#282c34", bg = "#98c379", bold = true })
15 | vim.api.nvim_set_hl(0, "StatuslineModeInsert", { fg = "#282c34", bg = "#61afef", bold = true })
16 | vim.api.nvim_set_hl(0, "StatuslineModeVisual", { fg = "#282c34", bg = "#c678dd", bold = true })
17 | vim.api.nvim_set_hl(0, "StatuslineModeCommand", { fg = "#282c34", bg = "#e5c07b", bold = true })
18 | vim.api.nvim_set_hl(0, "StatuslineModeReplace", { fg = "#282c34", bg = "#e06c75", bold = true })
19 | vim.api.nvim_set_hl(0, "StatuslineModeTerminal", { fg = "#282c34", bg = "#56b6c2", bold = true })
20 | end
21 |
22 | ---@type {[string]: {label: string, hl: string}}
23 | ---The various Vim modes and their respective codes as returned by the mode() function.
24 | ---See vim.api.nvim_get_mode for more information.
25 | local modes = {
26 | ["n"] = { label = "NORMAL", hl = "StatuslineModeNormal" },
27 | ["no"] = { label = "NORMAL", hl = "StatuslineModeNormal" },
28 | ["v"] = { label = "VISUAL", hl = "StatuslineModeVisual" },
29 | ["V"] = { label = "VISUAL LINE", hl = "StatuslineModeVisual" },
30 | [""] = { label = "VISUAL BLOCK", hl = "StatuslineModeVisual" },
31 | ["s"] = { label = "SELECT", hl = "StatuslineModeVisual" },
32 | ["S"] = { label = "SELECT LINE", hl = "StatuslineModeVisual" },
33 | [""] = { label = "SELECT BLOCK", hl = "StatuslineModeVisual" },
34 | ["i"] = { label = "INSERT", hl = "StatuslineModeInsert" },
35 | ["ic"] = { label = "INSERT", hl = "StatuslineModeInsert" },
36 | ["R"] = { label = "REPLACE", hl = "StatuslineModeReplace" },
37 | ["Rv"] = { label = "REPLACE (VISUAL)", hl = "StatuslineModeReplace" },
38 | ["c"] = { label = "COMMAND", hl = "StatuslineModeCommand" },
39 | ["cv"] = { label = "COMMAND (VIM EX)", hl = "StatuslineModeCommand" },
40 | ["ce"] = { label = "COMMAND (EX)", hl = "StatuslineModeCommand" },
41 | ["r"] = { label = "PROMPT", hl = "StatuslineModeCommand" },
42 | ["rm"] = { label = "MOAR", hl = "StatuslineModeCommand" },
43 | ["r?"] = { label = "CONFIRM", hl = "StatuslineModeCommand" },
44 | ["!"] = { label = "SHELL", hl = "StatuslineModeCommand" },
45 | ["t"] = { label = "TERMINAL", hl = "StatuslineModeTerminal" },
46 | ["nt"] = { label = "TERMINAL", hl = "StatuslineModeTerminal" },
47 | }
48 |
49 | ---@return string
50 | ---Return the current "mode" and return a uppercase formatted string representation.
51 | ---@see vim.api.nvim_get_mode
52 | local get_mode = function()
53 | local current_mode = vim.api.nvim_get_mode().mode
54 | local mode_info = modes[current_mode] or { label = "UNKNOWN", hl = "StatuslineModeNormal" }
55 |
56 | return string.format("%%#%s# %s ", mode_info.hl, mode_info.label)
57 | end
58 |
59 | ---@return string
60 | ---Get the total number of diagnostic entries in the current buffer and return a nicely
61 | ---formatted string with set icons to go with them.
62 | ---@see vim.diagnostic
63 | local get_diagnostics = function()
64 | ---@type {['errors']: integer, ['warnings']: number, ['info']: number, ['hints']: number}
65 | local count = {
66 | errors = 0,
67 | warnings = 0,
68 | info = 0,
69 | hints = 0,
70 | }
71 |
72 | ---@type { [string]: integer }
73 | local levels = {
74 | errors = vim.diagnostic.severity.ERROR,
75 | warnings = vim.diagnostic.severity.WARN,
76 | info = vim.diagnostic.severity.INFO,
77 | hints = vim.diagnostic.severity.HINT,
78 | }
79 |
80 | for key, level in pairs(levels) do
81 | count[key] = vim.tbl_count(vim.diagnostic.get(0, { severity = level }))
82 | end
83 |
84 | local errors = ""
85 | local warnings = ""
86 | local hints = ""
87 | local info = ""
88 |
89 | if count["errors"] ~= 0 then
90 | errors = " %#LspDiagnosticsSignError#? " .. count["errors"]
91 | end
92 |
93 | if count["warnings"] ~= 0 then
94 | warnings = " %#LspDiagnosticsSignWarning# " .. count["warnings"]
95 | end
96 |
97 | if count["hints"] ~= 0 then
98 | hints = " %#LspDiagnosticsSignHint#? " .. count["hints"]
99 | end
100 |
101 | if count["info"] ~= 0 then
102 | info = " %#LspDiagnosticsSignInformation#? " .. count["info"]
103 | end
104 |
105 | return errors .. warnings .. hints .. info .. "%#Normal#"
106 | end
107 |
108 | ---@return string
109 | ---Return the full filename path
110 | local get_filepath = function()
111 | ---@type string
112 | local fpath = vim.fn.fnamemodify(vim.fn.expand("%"), ":~:.")
113 |
114 | if fpath == "" or fpath == "." then
115 | return " "
116 | end
117 |
118 | return string.format(" %s", fpath)
119 | end
120 |
121 | ---@return string
122 | ---Return the current location of the cursor
123 | local get_cursor_location = function()
124 | ---@type integer
125 | local line = vim.fn.line(".")
126 | ---@type integer
127 | local column = vim.fn.col(".")
128 |
129 | return string.format("%s:%s", line, column)
130 | end
131 |
132 | ---@return string
133 | ---Return the filetype of the current buffer
134 | local get_filetype = function()
135 | ---@type string
136 | local ftype = vim.bo.filetype
137 |
138 | return string.format(" [%s]", ftype)
139 | end
140 |
141 | ---@return string
142 | ---Render the statusline programatically
143 | function M.render()
144 | return table.concat({
145 | get_mode(),
146 | get_diagnostics(),
147 | get_filepath(),
148 | "%=",
149 | get_cursor_location(),
150 | get_filetype(),
151 | })
152 | end
153 |
154 | ---@return nil
155 | function M.setup()
156 | define_highlight_groups()
157 | vim.o.statusline = "%!v:lua.require('statusline').render()"
158 | end
159 |
160 | return M
161 |
--------------------------------------------------------------------------------
/dotfiles/.config/nvim/luasnippets/go.lua:
--------------------------------------------------------------------------------
1 | local luasnip = require("luasnip")
2 | local snippet = luasnip.snippet
3 | local insert_node = luasnip.insert_node
4 | local fmt = require("luasnip.extras.fmt").fmt
5 |
6 | return {
7 | -- Snippet for defining a function
8 | snippet(
9 | { trig = "func", desc = "Create a function definition" },
10 | fmt(
11 | [[
12 | /**
13 | * {1} - {6}
14 | *
15 | * Parameters:
16 | * {8}
17 | *
18 | * Returns:
19 | * {7}
20 | */
21 | func {1}({2} {3}) ({4}) {{
22 | return {5}
23 | }}
24 | ]],
25 | {
26 | insert_node(1, "FunctionName"),
27 | insert_node(2, "Argument"),
28 | insert_node(3, "ArgumentType"),
29 | insert_node(4, "ReturnType"),
30 | insert_node(5, ""),
31 | insert_node(6, "Describe the function briefly."),
32 | insert_node(7, "Describe the return type briefly."),
33 | insert_node(8, "Describe the function arguments."),
34 | }
35 | )
36 | ),
37 |
38 | -- Snippet to create a Go struct
39 | snippet(
40 | { trig = "struct", desc = "Create a Go struct" },
41 | fmt(
42 | [[
43 | type {1} struct {{
44 | {2}
45 | }}
46 | ]],
47 | { insert_node(1, "StructName"), insert_node(2, "") }
48 | )
49 | ),
50 |
51 | -- Snippet to create struct method
52 | snippet(
53 | { trig = "method", desc = "Create a struct method" },
54 | fmt(
55 | [[
56 | func ({1}) {2}({3}) {4} {{
57 | return {5}
58 | }}
59 | ]],
60 | {
61 | insert_node(1, "Struct"),
62 | insert_node(2, "Method"),
63 | insert_node(3, "Args"),
64 | insert_node(4, "ReturnType"),
65 | insert_node(5, ""),
66 | }
67 | )
68 | ),
69 |
70 | -- Snippet to create an interface
71 | snippet(
72 | { trig = "interface", desc = "Create an interface" },
73 | fmt(
74 | [[
75 | type {1} interface {{
76 | {2}({3} {4}) {5}
77 | }}
78 | ]],
79 | {
80 | insert_node(1, "InterfaceName"),
81 | insert_node(2, "MethodName"),
82 | insert_node(3, "Argument"),
83 | insert_node(4, "ArgumentType"),
84 | insert_node(5, "ReturnType"),
85 | }
86 | )
87 | ),
88 |
89 | -- Snippet for error handling
90 | snippet(
91 | { trig = "err", desc = "Create an error handling block" },
92 | fmt(
93 | [[
94 | if err != nil {{
95 | return {1}
96 | }}
97 | ]],
98 | { insert_node(1, "err") }
99 | )
100 | ),
101 |
102 | -- Snippet for a basic for-loop
103 | snippet(
104 | { trig = "for", desc = "Create a basic for-loop snippet" },
105 | fmt(
106 | [[
107 | for {1} {{
108 | {2}
109 | }}
110 | ]],
111 | { insert_node(1, "i := 0; i < n; i++"), insert_node(2, "Statement") }
112 | )
113 | ),
114 |
115 | -- Snippet to generate a testcase function
116 | snippet(
117 | { trig = "test", desc = "Create a snippet to generate a test function" },
118 | fmt(
119 | [[
120 | func Test{1}(t *testing.T) {{
121 | {2}
122 | }}
123 | ]],
124 | {
125 | insert_node(1, "Name"),
126 | insert_node(2, ""),
127 | }
128 | )
129 | ),
130 |
131 | -- Snippet to create a map
132 | snippet(
133 | { trig = "map", desc = "Create a map object" },
134 | fmt(
135 | [[
136 | map[{1}]{2} {{
137 | {3}
138 | }}
139 | ]],
140 | { insert_node(1, "KeyType"), insert_node(2, "ValueType"), insert_node(3, "") }
141 | )
142 | ),
143 |
144 | -- Snippet to create a channel
145 | snippet(
146 | { trig = "chan", desc = "Create a snippet for channels" },
147 | fmt(
148 | [[
149 | make(chan {1})
150 | ]],
151 | insert_node(1, "Type")
152 | )
153 | ),
154 |
155 | -- Snippet for generating function documentations
156 | snippet(
157 | { trig = "fndoc", desc = "Create a snippet for function documentations" },
158 | fmt(
159 | [[
160 | /**
161 | * {1} - {2}
162 | *
163 | * Parameters:
164 | * {3}
165 | *
166 | * Returns:
167 | * {4}
168 | */
169 | ]],
170 | {
171 | insert_node(1, "FunctionName"),
172 | insert_node(2, "Description"),
173 | insert_node(3, "param1 Type, param2 Type"),
174 | insert_node(4, "Return description"),
175 | }
176 | )
177 | ),
178 |
179 | -- Snippet for creating documentations for structs
180 | snippet(
181 | { trig = "structdoc", desc = "Create a snippet for generating struct documentations" },
182 | fmt(
183 | [[
184 | /**
185 | * {1} - {2}
186 | *
187 | * Fields:
188 | * {3}
189 | */
190 | ]],
191 | {
192 | insert_node(1, "StructName"),
193 | insert_node(2, "Description"),
194 | insert_node(3, "Field1: Type // Field description"),
195 | }
196 | )
197 | ),
198 |
199 | -- Snippet for creating documentation for packages
200 | snippet(
201 | { trig = "pkgdoc", desc = "Create a snippet for generating package documentations" },
202 | fmt(
203 | [[
204 | /**
205 | * Package {1} - {2}
206 | */
207 | ]],
208 | { insert_node(1, "packageName"), insert_node(2, "Description of th package") }
209 | )
210 | ),
211 |
212 | -- Snippet for creating documentation for methods
213 | snippet(
214 | { trig = "methoddoc", desc = "Create a snippet for generating documentations for struct methods" },
215 | fmt(
216 | [[
217 | /**
218 | * {1} - {2} method of {3}
219 | *
220 | * Parameters:
221 | * {4}
222 | *
223 | * Returns:
224 | * {5}
225 | */
226 | ]],
227 | {
228 | insert_node(1, "MethodName"),
229 | insert_node(2, "Description"),
230 | insert_node(3, "StructName"),
231 | insert_node(4, "arg Type // Description"),
232 | insert_node(5, "ReturnType // Description"),
233 | }
234 | )
235 | ),
236 |
237 | -- Snippet for creating documentations for struct fields
238 | snippet(
239 | { trig = "fields", desc = "Create a snippet for generating documentations for struct fields" },
240 | fmt(
241 | [[
242 | // {1}: {2} - {3}
243 | ]],
244 | { insert_node(1, "FieldName"), insert_node(2, "Type"), insert_node(3, "Field Description") }
245 | )
246 | ),
247 |
248 | -- Snippet for generating the documentations for errors
249 | snippet(
250 | { trig = "errdoc", desc = "Creating a snippet for generating documentations for errors" },
251 | fmt([[ // {1}: {2} - {3}]], { insert_node(1, "ErrorName"), insert_node(2, "Type"), insert_node(3, "Description") })
252 | ),
253 |
254 | -- Snippet for generating the documentations for a function
255 | snippet(
256 | { trig = "funcdoc", desc = "Create a snippet for generating documentations for functions" },
257 | fmt(
258 | [[
259 | /**
260 | * {1}: {2}
261 | *
262 | * Parameters:
263 | * {3}
264 | *
265 | * Returns:
266 | * {4}
267 | */
268 | ]],
269 | {
270 | insert_node(1, "FunctionName"),
271 | insert_node(2, "Description"),
272 | insert_node(3, "Parameters"),
273 | insert_node(4, "Returns"),
274 | }
275 | )
276 | ),
277 | }
278 |
--------------------------------------------------------------------------------
/dotfiles/.local/bin/update:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """System maintenance and update utility.
4 |
5 | This script provides an unified interface for maintaining and updating the software
6 | across multiple environments. Depending on the Operating Systems, installed package
7 | managers and active shell, the script can perform;
8 |
9 | - Linux distribution updates using the appropriate package manager.
10 | - Homebrew package updates on MacOS or Linux systems where Homebrew is installed.
11 | - Zsh plugin updates for users running the Zsh shell with plugin repositories stored
12 | under `~/.zsh/plugins`.
13 |
14 | The script determines which update routines to run based on environment inspection
15 | rather than user input, making it suitable for automated maintenance tasks or periodic
16 | system cleanup.
17 |
18 | Errors from subprocess commands (such as package manager failures) may propagate unless
19 | caught internally, ensuring misconfigurations or unexpected system states are not
20 | silently ignored.
21 |
22 | Author: Somraj Saha
23 | License: MIT
24 | """
25 |
26 | import datetime
27 | import os
28 | import platform
29 | import subprocess
30 | import sys
31 | from argparse import ArgumentParser, Namespace
32 | from pathlib import Path
33 |
34 | # Message labels with their respective colour codes
35 | _RESET = "\x1b[0m"
36 | _BLUE = "\x1b[94m"
37 | _GREEN = "\x1b[92m"
38 | # _YELLOW = "\x1b[93m"
39 | # _WARN = f"[{_YELLOW}WARN{_RESET}]"
40 | _RED = "\x1b[31m"
41 | _INFO = f"[{_BLUE}INFO{_RESET}]"
42 | _SUCCESS = f"[{_GREEN}SUCCESS{_RESET}]"
43 | _ERROR = f"[{_RED}ERROR{_RESET}]"
44 |
45 |
46 | def parse_args() -> Namespace:
47 | """Parse and return the CLI arguments.
48 |
49 | Returns:
50 | An argparse.Namespace object containing the parsed arguments.
51 | """
52 | current_year = datetime.datetime.now(datetime.timezone.utc).year
53 | description = "intelligently update the system packages"
54 | epilog = f"© Somraj Saha 2018-{current_year} "
55 |
56 | parser = ArgumentParser(description=description, epilog=epilog)
57 |
58 | return parser.parse_args()
59 |
60 |
61 | def run_linux_updates() -> None:
62 | """Detect the Linux distribution and run system updates accordingly.
63 |
64 | Supported distributions:
65 | - Ubuntu (apt-get)
66 | - Debian (apt-get)
67 | - Fedora (dnf)
68 |
69 | This function executes the appropriate package manager commands for
70 | updating system packages and removing unused dependencies. It uses
71 | `subprocess.run(..., check=True)` to ensure errors are surfaced.
72 |
73 | If the distribution is not recognized, the function logs an error
74 | and terminates the program with a non-zero exit code.
75 | """
76 | distro = platform.freedesktop_os_release().get("NAME", "")
77 |
78 | match distro:
79 | case "Ubuntu" | "Debian":
80 | print(f"{_INFO} Updating {distro} system...")
81 | subprocess.run(["sudo", "apt-get", "update"], check=True)
82 | subprocess.run(["sudo", "apt-get", "upgrade", "--yes"], check=True)
83 | subprocess.run(
84 | ["sudo", "apt-get", "autoremove", "--purge", "--yes"], check=True
85 | )
86 | print(f"{_SUCCESS} {distro} APT packages upgrade complete!")
87 | case "Fedora":
88 | print(f"{_INFO} Updating {distro} system...")
89 | subprocess.run(["sudo", "dnf", "upgrade", "--assumeyes"], check=True)
90 | subprocess.run(["sudo", "dnf", "autoremove", "--assumeyes"], check=True)
91 | print(f"{_SUCCESS} {distro} APT packages upgrade complete!")
92 | case _:
93 | print(f"{_ERROR} Failed to identify system information...exiting!")
94 | sys.exit(1)
95 |
96 |
97 | def homebrew_installed() -> bool:
98 | """Determine whether Homebrew is installed and accessible.
99 |
100 | This function checks for the presence of the `brew` executable by attempting to run
101 | `brew --version`. No output is displayed during the check.
102 |
103 | Returns:
104 | `True`: Homebrew is installed and the `brew` command can be executed.
105 | `False`: Homebrew is not installed, not available on the system `PATH` or
106 | returned an unexpected error during its execution.
107 | """
108 | try:
109 | subprocess.run(["brew", "--version"], check=True, stdout=subprocess.DEVNULL)
110 | return True
111 | except (FileNotFoundError, subprocess.CalledProcessError):
112 | return False
113 |
114 |
115 | def run_homebrew_updates() -> None:
116 | """Run system package updates using Homebrew.
117 |
118 | This function executes the standard Homebrew maintenance sequence:
119 | - `brew update` to refresh the available package definitions.
120 | - `brew upgrade` to upgrade installed formulae and casks.
121 | - `brew autoremove` to removed unused dependency packages.
122 | - `brew cleanup` to remove outdated files and cached data.
123 |
124 | All the commands are executed with the `check=True` parameter to raise a
125 | `subprocess.CalledProcessError` to be raised if any step fails.
126 |
127 | Raises:
128 | subprocess.CalledProcessError: If any Homebrew command exits with a non-zero
129 | status.
130 | """
131 | print(f"{_INFO} Running Homebrew updates")
132 |
133 | subprocess.run(["brew", "update"], check=True)
134 | subprocess.run(["brew", "upgrade"], check=True)
135 | subprocess.run(["brew", "autoremove"], check=True)
136 | subprocess.run(["brew", "cleanup"], check=True)
137 |
138 | print(f"{_SUCCESS} Homebrew package upgrades complete!")
139 |
140 |
141 | def run_zsh_updates() -> None:
142 | """Update the local Zsh plugins by pulling the latest changes.
143 |
144 | This function assumes the Zsh plugins are cloned under:
145 | `~/.zsh/plugins/`
146 |
147 | For each plugin repository listed in the `plugins` tuple, the function:
148 | 1. Constructs the local plugin directory path.
149 | 2. Changes the working directory to that location.
150 | 3. Executes `git pull --rebase` to fetch and apply the upstream updates.
151 |
152 | All Git operations are executed with `check=True`, causing
153 | `subprocess.CalledProcessError` to be raised if any update fails.
154 |
155 | Raises:
156 | `FileNotFoundError`: If a plugin directory does not exist.
157 | `subprocess.CalledProcessError`: If a Git update operation exits with a non-zero
158 | status.
159 | """
160 | plugins = (
161 | "zsh-users/zsh-autosuggestions",
162 | "ael-code/zsh-colored-man-pages",
163 | "zsh-users/zsh-completions",
164 | "zsh-users/zsh-syntax-highlighting",
165 | )
166 |
167 | print(f"{_INFO} Running ZSH plugin updates")
168 | for plugin in plugins:
169 | print(f"{_INFO} Fetching https://github.com/{plugin}")
170 | plugin_dir = Path.home() / ".zsh" / "plugins" / plugin.split("/")[-1]
171 | os.chdir(plugin_dir)
172 | subprocess.run(
173 | ["git", "pull", "--rebase"], check=True, stdout=subprocess.DEVNULL
174 | )
175 | print(f"{_SUCCESS} ZSH update plugins complete!")
176 |
177 |
178 | def main() -> None:
179 | """Executes the full system update routine for the current environment.
180 |
181 | This function orchestrates all available update mechanisms based on the system
182 | configuration and installed tooling:
183 |
184 | 1. Parses the CLI arguments for the script.
185 | 2. Detects the active shell via the `SHELL` environment variable.
186 | 3. If running on Linux system, executes OS-level package updates.
187 | 4. If Homebrew is installed, runs Homebrew package maintenance.
188 | 5. If the active shell is Zsh, updates the Zsh plugins.
189 |
190 | The function prints progress messages and ends with a success message once all
191 | relevant update routines have completed. Errors from underlying update handlers
192 | (such as failed subprocess calls) may propagate upwards unless explicitly handled
193 | within those functions.
194 |
195 | Raises:
196 | subprocess.CalledProcessError: If any invoked update command (Linux, Homebrew
197 | or Zsh plugin updates) fails and is executed with `check=True`.
198 | """
199 | # Parse the CLI arguments of the script
200 | parse_args()
201 |
202 | # Chech which shell is enabled for the interactive environment
203 | shell = os.getenv("SHELL")
204 |
205 | # Run the package updates for a Linux distribution
206 | if platform.uname().system == "Linux":
207 | run_linux_updates()
208 |
209 | # Run the Homebrew package updates
210 | if homebrew_installed():
211 | run_homebrew_updates()
212 |
213 | # Update the zsh plugins
214 | if shell and shell.split("/")[-1] == "zsh":
215 | run_zsh_updates()
216 |
217 | print(f"{_SUCCESS} System update complete...exiting now")
218 |
219 |
220 | if __name__ == "__main__":
221 | main()
222 |
--------------------------------------------------------------------------------
/dotfiles/.local/bin/mkblog:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """
4 | Script to generate and automate the process of creating a blogpost.
5 |
6 | The script takes user input, either through STDIN or CLI flags to generate a Markdown
7 | file for my blog. The intention of using the script for the purpose is to reproducibly
8 | generate and manage each Markdown file along with some necessary metadata which can be
9 | quite cumbersome to remember every time.
10 |
11 | Author: Somraj Saha
12 | License: MIT (see the LICENSE document for more details)
13 |
14 | TODO: Provide a usage guide.
15 | """
16 |
17 | import argparse
18 | import datetime
19 | import logging
20 | import os
21 | import pathlib
22 | import re
23 | import shlex
24 | import subprocess
25 | from dataclasses import dataclass
26 |
27 | # The current timestamp during the template generation process
28 | _BLOG_DIR = pathlib.Path.home() / "projects" / "blogposts" / "blogs"
29 |
30 |
31 | def configure_logging(level: int, name: str = __name__) -> logging.Logger:
32 | """Configure and return a logger with a console handler and custom formatting.
33 |
34 | The function initialises or retrieves a logger with the given name, sets its logging
35 | level, attaches a stream handler which outputs to STDOUT and applies a simple,
36 | structured log message format.
37 |
38 | **NOTE**: The function unconditionally adds a new `StreamHandler` each time it is
39 | called. Hence, callers should ensure it is not invoked repeatedly for the same
40 | logger name unless multiple handlers are desired.
41 |
42 | Args:
43 | level: The logging level to apply (e.g., logging.INFO, logging.DEBUG).
44 | name: The name of the logger to configure. Defaults to the caller's module name.
45 |
46 | Returns:
47 | A configured `logging.Logger` instance.
48 | """
49 | # Set the name of the root logger
50 | logger = logging.getLogger(name)
51 | logger.setLevel(level)
52 | logger.propagate = False
53 |
54 | # Configure the formatting style of the log messages
55 | formatter = logging.Formatter("[{levelname}] - {message}", style="{")
56 |
57 | # Set the logger to send the messages to the console output
58 | if not logger.handlers:
59 | console_handler = logging.StreamHandler()
60 | console_handler.setLevel(level)
61 | console_handler.setFormatter(formatter)
62 | logger.addHandler(console_handler)
63 |
64 | return logger
65 |
66 |
67 | def parse_args() -> argparse.Namespace:
68 | """Parse and return the CLI arguments.
69 |
70 | Returns:
71 | An argparse.Namespace object containing the parsed arguments.
72 | """
73 | current_year = datetime.datetime.now(datetime.timezone.utc).year
74 |
75 | # Some usage guidelines and message for using the program.
76 | description = "generate blogpost Markdown files in a reproducible manner"
77 | epilog = f"© 2018-{current_year} Somraj Saha "
78 | blogs = _BLOG_DIR
79 |
80 | # Create the parser to fetch the CLI flags passed to the script.
81 | parser = argparse.ArgumentParser(description=description, epilog=epilog)
82 |
83 | # Add argument to set the title of the blogpost
84 | parser.add_argument("title", type=str, help="the title of the blog post")
85 |
86 | # Add argument to set the description of the blogpost
87 | parser.add_argument(
88 | "description", type=str, help="the description of the blog post"
89 | )
90 |
91 | # Add the option to store whether the blog is a draft
92 | parser.add_argument(
93 | "-D",
94 | "--draft",
95 | action="store_true",
96 | default=True,
97 | help='create a draft blogpost, defaults to "True"',
98 | )
99 |
100 | # Add the option to set the default path to store the blogpost to
101 | parser.add_argument(
102 | "-o",
103 | "--output",
104 | type=pathlib.Path,
105 | default=_BLOG_DIR,
106 | help=f'directory to save the generated Markdown file to, defaults to "{blogs}"',
107 | )
108 |
109 | # Add a flag to edit the blog post
110 | parser.add_argument(
111 | "-e",
112 | "--edit",
113 | action="store_true",
114 | help='edit the generated Markdown file using $EDITOR, defaults to "False"',
115 | )
116 |
117 | # Add the option to optionally force creation of the Markdown file (even if it
118 | # already exists)
119 | parser.add_argument(
120 | "-f", "--force", action="store_true", help="overwrite if file already exists"
121 | )
122 |
123 | # Add the option to provide verbose output when generating the file contents
124 | parser.add_argument(
125 | "-d", "--debug", action="store_true", help="enable verbose output"
126 | )
127 |
128 | # Parse the arguments and options
129 | return parser.parse_args()
130 |
131 |
132 | @dataclass
133 | class Blog:
134 | """Represents a blog post and provides utilities for generating and writing a
135 | Markdown file with YAML frontmatter.
136 |
137 | This class is intended to be used as a lightweight content scaffold for
138 | filesystem-based blogging workflows.
139 | """
140 |
141 | title: str
142 | draft: bool
143 | description: str
144 |
145 | def _slugify(self) -> str:
146 | """Generate a filesystem-safe slug from the blog title.
147 |
148 | The title is lowercased, spaces are replaced with hyphens and any characters
149 | other than lowercase alphanumerics and hyphens are removed.
150 |
151 | Returns:
152 | A lowercase, hyphen-separated string suitable for use as a filename.
153 |
154 | Raises:
155 | ValueError if the title cannot be slugified for some reason.
156 | """
157 | slug = re.sub(r"[^a-z0-9]+", "-", self.title.lower())
158 |
159 | if not slug:
160 | raise ValueError("Title cannot be converted into a valid filename")
161 |
162 | return slug.strip("-")
163 |
164 | def _create_template(self) -> str:
165 | """Create a Markdown template with populated YAML frontmatter.
166 |
167 | The frontmatter includes the blog title, description, publication
168 | timestamp (UTC), and publication status derived from the `draft`
169 | flag.
170 |
171 | Returns:
172 | A Markdown-formatted string containing YAML frontmatter
173 | followed by placeholder content.
174 | """
175 | timestamp = datetime.datetime.now(datetime.timezone.utc)
176 |
177 | return (
178 | "---\n"
179 | + f"title: {self.title}\n"
180 | + f"description: {self.description}\n"
181 | + f"publishedOn: {timestamp}\n"
182 | + f"status: {'draft' if self.draft else 'published'}\n"
183 | + "---\n\n"
184 | + "Add blog content here..."
185 | )
186 |
187 | def write_file(
188 | self, base_dir: pathlib.Path, force: bool, logger: logging.Logger
189 | ) -> pathlib.Path | None:
190 | """Write the blog post to a Markdown file on disk.
191 |
192 | The file is created under the user's home directory at
193 | `~/projects/blogposts/blogs`, using a slugified version of the
194 | title as the filename.
195 |
196 | If a file with the same name already exists and `force` is
197 | False, the method prints a warning and does not overwrite the
198 | file.
199 |
200 | Args:
201 | base_dir (pathlib.Path): The base directory path where the Markdown file
202 | will be generated at.
203 | force (bool): Whether to overwrite an existing file to replace it with a new
204 | file.
205 | logger (logging.Logger): An instance of `logging.Logger` to print log
206 | messages to the log handler.
207 |
208 | Returns:
209 | The path to the written Markdown file, or None if the file
210 | already exists and overwriting was not allowed.
211 | """
212 | # Check if the output directory exists, else create it before generating the
213 | # Markdown file into
214 | if not base_dir.is_dir():
215 | base_dir.mkdir(parents=True, exist_ok=True)
216 |
217 | # Sanitize and create the filepath of the Markdown file
218 | filepath = base_dir / f"{self._slugify()}.md"
219 |
220 | # Print a warning message to the user if the specified file already exists
221 | if filepath.exists() and not force:
222 | logger.warning(f"{filepath} already exists")
223 | logger.info('Use the "--force" flag to overwrite the existing file')
224 |
225 | return None
226 |
227 | # Generate the Markdown file along with its specified template content
228 | content = self._create_template()
229 | filepath.write_text(content, encoding="utf-8")
230 |
231 | return filepath
232 |
233 |
234 | def main() -> None:
235 | """Entrypoint of the script."""
236 | # Parse the CLI arguments
237 | args = parse_args()
238 |
239 | # Create an instance of "Logger" to print log messages
240 | logger = configure_logging(logging.DEBUG if args.debug else logging.INFO)
241 |
242 | # Set the editor command
243 | editor = os.getenv("EDITOR")
244 |
245 | # Create an instance of "Blog" to generate a blogpost from
246 | blog = Blog(title=args.title, draft=args.draft, description=args.description)
247 |
248 | # Write the blogpost to disk and get its filepath
249 | filepath = blog.write_file(base_dir=args.output, force=args.force, logger=logger)
250 |
251 | # Set the editor command which can be invoked directly from the script
252 | cmd = None
253 | if editor:
254 | cmd = shlex.split(editor) + [str(filepath)]
255 |
256 | # Print useful guidelines to edit the template if it was successfully generated
257 | if filepath and editor:
258 | logger.info(f"Blog template is generated at {str(filepath)}")
259 | logger.info(
260 | "Start editing it by running these commands:\n\n\t\x1b[92mcd "
261 | + f"{filepath.parent}\n\t{editor} {filepath}\x1b[0m"
262 | )
263 |
264 | # Open the file using the editor if the script is allowed to do so
265 | if args.edit and cmd:
266 | result = subprocess.run(cmd)
267 | if result.returncode != 0:
268 | logger.error(f'"{cmd}" command exited with a non-zero status')
269 |
270 |
271 | if __name__ == "__main__":
272 | main()
273 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to (My) Dotfiles
2 |
3 | :+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
4 |
5 | The following is a set of guidelines for contributing to my collection of
6 | [dotfiles](https://dotfiles.github.io/). They're meant to automate the process
7 | of setting up my personal development machines (**_both Unix &
8 | Windows-based_**).
9 |
10 | The scripts are hosted in this current repository on GitHub for backup purpose &
11 | a robust environment for packaging & distribution.
12 |
13 | The content in the current file you're reading from are mostly guidelines, not
14 | rules. Use your best judgment to use and/or propose changes to this document in
15 | a [Pull Request](./PULL_REQUEST_TEMPLATE.md).
16 |
17 | ## Table Of Contents
18 |
19 | - [Contributing to (My) Dotfiles](#contributing-to-my-dotfiles)
20 | - [Table Of Contents](#table-of-contents)
21 | - [Code of Conduct](#code-of-conduct)
22 | - [I Don't Want To Read This Whole Thing I Just Have a Question](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question)
23 | - [What should I know before I get started](#what-should-i-know-before-i-get-started)
24 | - [dotfiles](#dotfiles)
25 | - [Design Decisions](#design-decisions)
26 | - [How Can I Contribute](#how-can-i-contribute)
27 | - [Suggesting Enhancements](#suggesting-enhancements)
28 | - [Pull Requests](#pull-requests)
29 | - [Styleguides](#styleguides)
30 | - [Git Commit Messages](#git-commit-messages)
31 | - [Shell Styleguide](#shell-styleguide)
32 | - [Documentation Styleguide](#documentation-styleguide)
33 | - [Additional Notes](#additional-notes)
34 | - [Pull Request Labels](#pull-request-labels)
35 | - [PR Labels](#pr-labels)
36 |
37 | ## Code of Conduct
38 |
39 | This project and everyone participating in it are governed by the
40 | [CODE OF CONDUCT](https://github.com/Jarmos-san/.github/blob/master/CODE_OF_CONDUCT.md).
41 | By participating, you are expected to uphold this code. Please report
42 | unacceptable behaviour to [somraj.mle@gmail.com](mailto:somraj.mle@gmail.com).
43 |
44 | ### I Don't Want To Read This Whole Thing I Just Have a Question
45 |
46 | > **Note:** Please don't file an issue to ask a question. You'll get faster
47 | > results by using the resources below.
48 |
49 | The scripts hosted here in the repository works perfectly fine for me & as
50 | expected. If you've some suggestions about writing certain parts of the script
51 | in a better way, I welcome PRs for it.
52 |
53 | Besides, if you've questions regarding my dev environment, feel free to tweet to
54 | me at--[@Jarmosan](https://twitter.com/Jarmosan). Or if you want a detailed
55 | explanation, feel free to have a
56 | [discussion](https://github.com/Jarmos-san/dotfiles/discussions) over it.
57 |
58 | Or, perhaps you want to something more personal, then head over to
59 | [here](https://github.com/Jarmos-san/Jarmos-san/discussions/categories/q-a) for
60 | a public Q&A session.
61 |
62 | With that said, you might've noticed the "_Issues_" tab is disabled. I did so on
63 | purpose since the scripts work perfectly for my use case.
64 |
65 | ## What should I know before I get started
66 |
67 | ### dotfiles
68 |
69 | "_dotfiles_" refers to this repository which hosts some shell scripts for
70 | setting up automated development environments on my Unix-based & Windows-based
71 | machines.
72 |
73 | The scripts downloads & installs the following applications on my system:
74 |
75 | 1. Python
76 |
77 | 2. Docker
78 |
79 | 3. Poetry(Python package management system)
80 |
81 | 4. zsh
82 |
83 | and a few more stuff (check the
84 | [wiki](https://github.com/Jarmos-san/dotfiles/wiki) for a more detailed
85 | explanation)...
86 |
87 | It's not an application for you to download right way to use. Doing so can have
88 | unintended actions on your system. So if you do use some of the scripts or
89 | borrow a snippet or two, **know what you're doing**.
90 |
91 | I strongly recommend reading through the scripts to learn what each line are
92 | doing. When in doubt, feel free to reach out to me.
93 |
94 | ### Design Decisions
95 |
96 | The idea behind hosting all these scripts under one roof is for easier packaging
97 | & distribution besides backup availability. The fact that one can set up a
98 | full-blown dev environment on their Ubuntu machine with a call of just a `wget`
99 | invocation or even a `git` clone makes hosting dotfiles in a remote repository
100 | very favourable.
101 |
102 | ## How Can I Contribute
103 |
104 | ### Suggesting Enhancements
105 |
106 | This section guides you through submitting an enhancement suggestion for the
107 | dotfiles, including completely new features and minor improvements to existing
108 | functionality. Following these guidelines helps maintainers and the community
109 | understand your suggestion :pencil: and find related suggestions :mag_right:.
110 |
111 | Before creating enhancement suggestions, please know that I've designed the
112 | scripts as per my use case, hence there's not much changes required to it.
113 | Exceptions are when I change my development environment or plan on automating
114 | something else too. Hence, as you might've already figured, severe changes
115 | aren't really required. But if there's a good enhancement you think will benefit
116 | the greater good of all, please open a PR. Also, refer to the
117 | [Pull Requests](#pull-requests) section for instruction on opening a PR. You can
118 | fill up the [PR template](./PULL_REQUEST_TEMPLATE.md) & wait for a review.
119 |
120 | #### Pull Requests
121 |
122 | The process described here has several goals:
123 |
124 | - Maintain a quality standard for easier maintainability of the Shell scripts.
125 | - Fix problems that are important to users of the scripts.
126 | - Engage the community in working toward the best possible way to automate
127 | setting up their own dev environment.
128 | - Enable a sustainable system for the maintainer to review contributions.
129 |
130 | Please follow these steps to have your contribution considered by the
131 | maintainers:
132 |
133 | 1. Follow all instructions in [the template](./PULL_REQUEST_TEMPLATE.md)
134 | 2. Follow the [styleguides](#styleguides)
135 | 3. After you submit your pull request, verify that all
136 | [status checks](https://help.github.com/articles/about-status-checks/) are
137 | passing What if the status checks are failing?
If
138 | a status check is failing, and you believe that the failure is unrelated to
139 | your change, please leave a comment on the pull request explaining why you
140 | believe the failure is unrelated. A maintainer will re-run the status check
141 | for you. If we conclude that the failure was a false positive, then we will
142 | open an issue to track that problem with our status check suite.
143 |
144 | ## Styleguides
145 |
146 | ### Git Commit Messages
147 |
148 | - Use the present tense ("Add feature" not "Added feature")
149 | - Use the imperative mood ("Move the cursor to..." not "Moves the cursor to...")
150 | - Limit the first line to 80 characters or less
151 | - Reference issues and pull requests liberally after the first line
152 | - Consider starting the commit message with an applicable emoji:
153 |
154 | - :art: `:art:` when improving the format/structure of the code
155 | - :racehorse: `:racehorse:` when improving performance
156 | - :non-potable_water: `:non-potable_water:` when plugging memory leaks
157 | - :memo: `:memo:` when writing docs
158 | - :penguin: `:penguin:` when fixing something on Linux
159 | - :apple: `:apple:` when fixing something on macOS
160 | - :checkered_flag: `:checkered_flag:` when fixing something on Windows
161 | - :bug: `:bug:` when fixing a bug
162 | - :fire: `:fire:` when removing code or files
163 | - :green_heart: `:green_heart:` when fixing the CI build
164 | - :white_check_mark: `:white_check_mark:` when adding tests
165 | - :lock: `:lock:` when dealing with security
166 | - :arrow_up: `:arrow_up:` when upgrading dependencies
167 | - :arrow_down: `:arrow_down:` when downgrading dependencies
168 | - :shirt: `:shirt:` when removing linter warnings
169 |
170 | ...There are more available at [gitmoji](https://gitmoji.carloscuesta.me/).
171 |
172 | ### Shell Styleguide
173 |
174 | All Shell scripts must adhere to Google's
175 | [Shell Style Guide](https://google.github.io/styleguide/shellguide.html).
176 |
177 |
178 |
179 | ### Documentation Styleguide
180 |
181 | **This section needs to be updated properly, feel free to make a PR if you know
182 | how to document dotfiles.**
183 |
184 | As of now, the documentation exists on the [README.md](../README.md) but I think
185 | it would be more efficient to include external documentation as the project
186 | grows. Ideas are welcome but for now, please make sure to include enough
187 | instructions & docs on the README itself if you make some changes.
188 |
189 | ## Additional Notes
190 |
191 | ### Pull Request Labels
192 |
193 | This section lists the labels we use to help track & manage and pull requests.
194 |
195 | [GitHub search](https://help.github.com/articles/searching-issues/) makes it
196 | easy to use labels for finding groups of pull requests you're interested in. For
197 | example, you might be interested in
198 | [open pull requests in `jarmos/dotfiles` which haven't been reviewed yet](https://github.com/search?utf8=%E2%9C%93&q=is%3Aopen+is%3Apr+repo%3Ajarmos%2Fdotfiles+comments%3A0).
199 | To help you find pull requests, each label is listed with search links for
200 | finding open items with that label in `jarmos/dotfiles` only. it is recommended
201 | to read about
202 | [other search filters](https://help.github.com/articles/searching-issues/) which
203 | will help you write more focused queries.
204 |
205 | The labels are loosely grouped by their purpose, but it's not required that
206 | every PR have a label from every group or that a PR can't have more than one
207 | label from the same group.
208 |
209 |
210 |
211 | ### PR Labels
212 |
213 | | Labels | Description of the Labels |
214 | | :----------------: | ---------------------------------------------------------------------- |
215 | | `bug` | Issues reporting a bug |
216 | | `documentation` | Issues related to documentations |
217 | | `duplicate` | Issue or PR threads which already has a previous entry |
218 | | `enhancement` | Issue or PR which suggests some improvements |
219 | | `good first issue` | Issue which are easy to contribute to for beginners |
220 | | `help wanted` | Issues and/or PRs which could benefit from a helping hand |
221 | | `invalid` | Issue and/or PR threads which are invalid or useless |
222 | | `pinned` | Issue and/or PR threads which are important & needs attention |
223 | | `question` | Issue threads which should be converted to a Discussion thread instead |
224 | | `stale` | Issue and/or PRs which hasn't received any feedback & will be closed |
225 | | `wontfix` | Issue threads which won't be fixed like ever |
226 |
--------------------------------------------------------------------------------
/bootstrap.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ###############################################################################
4 | # Script to automatically setup a fresh new Linux/MacOS system (or VM).
5 | #
6 | # This script should ONLY be used after installing a fresh new OS on a new
7 | # machine or inside a VM to setup a development environment automatically. The
8 | # script will install necessary tools like code editors, package managers and
9 | # more before setting up their configuration files automatically.
10 | #
11 | # USAGE: To use the script, run the following command (its not ready for usage yet);
12 | #
13 | # curl -fsSL https://raw.githubusercontent.com///path/to/script \
14 | # | bash -s
15 | #
16 | # NOTE: The script is designed to be subjective, hence it is RECOMMENDED to NOT
17 | # invoke it without understanding the context of the contents! Please read
18 | # through the script or reach out to the author for clarification on what
19 | # certain parts of the script does.
20 | #
21 | # DISCLAIMER: The script IS NOT TESTED and there is no guranteed it works
22 | # properly!
23 | #
24 | # Author: Somraj Saha
25 | # License: MIT (see the LICENSE document for more info on this regards)
26 | ###############################################################################
27 |
28 | # Enable some options for Bash to stop executing the script if there's an error
29 | set -o errexit
30 | set -o nounset
31 | set -o pipefail
32 |
33 | # Enable debugging capabilities to the script
34 | if [[ "${TRACE-0}" == "1" ]]; then
35 | set -o xtrace
36 | fi
37 |
38 | # Logic to print out a simple help message to STDOUT
39 | if [[ "${1-}" =~ ^-*h(elp)?$ ]]; then
40 | echo 'Usage: ./script.sh arg-one arg-two
41 |
42 | This is an awesome bash script to make your life better.
43 |
44 | '
45 | exit
46 | fi
47 |
48 | # Execute the script in context to the current directory where the script is run
49 | cd "$(dirname "$0")"
50 |
51 | ###############################################################################
52 | # Print a nicely formatted informative message to STDOUT
53 | ###############################################################################
54 | info() {
55 | echo -e "\033[0;34m[INFO]\033[0m $1"
56 | }
57 |
58 | ###############################################################################
59 | # Print a nicely formatted warning message to STDOUT
60 | ###############################################################################
61 | warn() {
62 | echo -e "\033[0;33m[WARN]\033[0m $1"
63 | }
64 |
65 | ###############################################################################
66 | # Print a nicely formatted success message to STDOUT
67 | ###############################################################################
68 | success() {
69 | echo -e "\033[0;32m[SUCCESS]\033[0m $1"
70 | }
71 |
72 | ###############################################################################
73 | # Print a nicely formatted error message to STDOUT
74 | ###############################################################################
75 | error() {
76 | echo -e "\033[0;31m[ERROR]\033[0m $1"
77 | }
78 |
79 | # Check if the script is running as root
80 | if [[ "$EUID" -ne 0 ]]; then
81 | warn "Please run with root (or \"sudo\") privileges!"
82 | fi
83 |
84 | ###############################################################################
85 | # Configure the system to not require a password prompt for sudo privileges
86 | ###############################################################################
87 | sudo_nopasswd() {
88 | local user
89 | local sudoers_file
90 |
91 | user="jarmos"
92 | sudoers_file="/etc/sudoers.d/{$user}_nopasswd"
93 |
94 | echo "$user ALL=(ALL) NOPASSWD: ALL" > "$sudoers_file"
95 |
96 | chmod 0440 "$sudoers_file"
97 |
98 | success "Passwordless \"sudo\" has been enabled for user \"$user\"."
99 | }
100 |
101 | ###############################################################################
102 | # Warn user and prompt for confirmation before executing the script
103 | ###############################################################################
104 | warn_user() {
105 | warn "The script will perform an automated setup of the system and can cause\
106 | potential harm to the system!"
107 |
108 | read -rp "Do you still want to proceed? (yes/no) " yn
109 |
110 | case $yn in
111 | yes) info "This system will now be automatically setup..." ;;
112 | no)
113 | info "Aborting automated system updated..."
114 | exit 0
115 | ;;
116 | *)
117 | error "Invalid response"
118 | exit 1
119 | ;;
120 | esac
121 | }
122 |
123 | # Warn and prompt the user for confirmation to prevent accidental execution
124 | warn_user
125 |
126 | info "Please manually enter the prompts below before the automation starts"
127 |
128 | read -rp "GitHub Access Token: " github_pat
129 | read -rp "SSH key name for GitHub: " github_ssh_key_name
130 | read -rp "Enter email address for Git: " git_email
131 | read -rp "Enter username for Git: " git_name
132 |
133 | GHTOKEN="$github_pat"
134 | SSH_KEY_NAME="$github_ssh_key_name"
135 | # GPG_SIGN_NAME=$(read -rp "GPG signature name: ")
136 | # GPG_SIGN_EMAIL=$(read -rp "GPG signature email address: ")
137 | # GPG_SIGN_KEY=$(read -rp "GPG signature key: ")
138 | OS_NAME=$(grep -Po "(?<=^ID=).+" /etc/os-release | sed 's/"//g')
139 |
140 | info "Automatic setup is starting...please feel free to grab a cup of coffee!"
141 |
142 | ################################################################################
143 | # On Debian systems, update the sources to point to the "unstable" repository
144 | ################################################################################
145 | add_unstable_sources() {
146 | unstable_repo_url="deb https://deb.debian.org/debian unstable main"
147 | sources_list="/etc/apt/sources.list"
148 | echo "$unstable_repo_url" | tee "$sources_list" &> /dev/null
149 | }
150 |
151 | ###############################################################################
152 | # Update the system before starting the automated setup
153 | ###############################################################################
154 | update_system() {
155 | info "Updating the system before starting the automated setup..."
156 |
157 | case "$OS_NAME" in
158 | debian)
159 | add_unstable_sources
160 | sudo apt-get update
161 | sudo apt-get upgrade --yes
162 | ;;
163 | ubuntu)
164 | sudo apt-get update
165 | sudo apt-get upgrade --yes
166 | ;;
167 | fedora)
168 | sudo dnf upgrade --refresh --assumeyes
169 | ;;
170 | *)
171 | error "Failed to identify the OS"
172 | exit 1
173 | ;;
174 | esac
175 | }
176 |
177 | ###############################################################################
178 | # Install some necessary prerequisite tools before the setup script runs
179 | ###############################################################################
180 | install_prerequisite_tools() {
181 | # List of prerequisite tools to check for existence
182 | declare -a prerequisite_tools
183 |
184 | # List of prerequisite tools which aren't installed and will be eventually!
185 | declare -a missing_tools
186 |
187 | case "$OS_NAME" in
188 | debian | ubuntu)
189 | prerequisite_tools=(
190 | "git" "curl" "build-essential" "gnupg" "ca-certificates"
191 | )
192 | ;;
193 | *)
194 | error "Failed to identify the OS!"
195 | exit 1
196 | ;;
197 | esac
198 |
199 | # Check for missing prerequisite tools and store them for future reference
200 | for tool in "${prerequisite_tools[@]}"; do
201 | if ! command -v "${tool}" &> /dev/null; then
202 | missing_tools+=("$tool")
203 | else
204 | missing_tools=()
205 | fi
206 | done
207 |
208 | if [[ ${#missing_tools[@]} -ne 0 ]]; then
209 | warn "These tools were not found & hence will be installed!"
210 |
211 | for tool in "${missing_tools[@]}"; do
212 | echo " $tool"
213 | done
214 |
215 | sudo apt-get install --yes --no-install-recommends "${missing_tools[@]}"
216 |
217 | info "Prerequisite tools installed...proceeding with automated setup"
218 | fi
219 | }
220 |
221 | ###############################################################################
222 | # Setup necessary directories relative to the home directory on the system
223 | ###############################################################################
224 | create_necessary_dirs() {
225 | declare -a dirs
226 |
227 | dirs=(".config" ".gnupg" ".ssh" "projects" "work")
228 |
229 | info "Setting up necessary directories for proper system functioning"
230 |
231 | for dir in "${dirs[@]}"; do
232 | if [[ ! -d "$HOME/$dir" ]]; then
233 | info "$HOME/$dir not found...created"
234 | mkdir --parents "$HOME/$dir"
235 | fi
236 | done
237 | }
238 |
239 | ###############################################################################
240 | # Setup SSH for authenticating to GitHub using Git
241 | #
242 | # FIXME: Identify better ways to automate SSH setup for GitHub because it fails
243 | # and breaks right now
244 | ###############################################################################
245 | setup_github_ssh() {
246 | # Check for the "~/.ssh" directory's existence to createh the SSH keys safely
247 | if [[ ! -d "$HOME/.ssh" ]]; then
248 | error "The $HOME/.ssh directory does not exist...please create it!"
249 | exit 1
250 | fi
251 |
252 | info "Generating the SSH secret/public key pair now..."
253 |
254 | ssh-keygen -q -b 4096 -t ed25519 -N "" -f "$HOME/.ssh/id_ed25519"
255 |
256 | pubkey=$(cat "$HOME/.ssh/id_ed25519.pub")
257 |
258 | curl --silent --location \
259 | --request POST \
260 | --header "Accept: application/vnd.github+json" \
261 | --header "Authorization: Bearer $GHTOKEN" \
262 | --header "X-GitHub-Api-Version: 2022-11-28" \
263 | https://api.github.com/user/keys \
264 | --data-binary "{\"title\":\"$SSH_KEY_NAME\",\"key\":\"$pubkey\"}"
265 |
266 | info "SSH public key pushed to remote service..."
267 |
268 | chmod 600 "$HOME/.ssh/*"
269 | chmod 700 "$HOME/.ssh"
270 | chmod 644 "$HOME/.ssh/*.pub"
271 |
272 | eval "$(ssh-agent -s)" &> /dev/null
273 |
274 | ssh-add "$HOME/.ssh/id_ed25519.pub"
275 |
276 | info "Testing SSH connection to GitHub..."
277 | ssh -T git@github.com
278 | }
279 |
280 | ###############################################################################
281 | # Setup and install fonts
282 | ###############################################################################
283 | setup_fonts() {
284 | # URL for Cascadia Code assets to download from
285 | font_url="https://github.com/ryanoasis/nerd-fonts/releases/download/v3.1.1/CascadiaCode.zip"
286 |
287 | # Only download and setup the Cascadia Code fonts for systems other than WSL2
288 | if [[ ! -e "/proc/sys/fs/binfmt_misc/WSLInterop" ]]; then
289 | info "Downloading fonts from the remote source..."
290 |
291 | curl --silent --fail --show-error --remote-name "$font_url"
292 |
293 | unzip CascadiaCode.zip &> /dev/null
294 |
295 | rm CascadiaCode.zip
296 |
297 | mv ./CascadiaCode/CaskaydiaCoveNerdFontMono-Bold.ttf "$HOME/.fonts"
298 | fi
299 | }
300 |
301 | ###############################################################################
302 | # Setup and install the "lazy.nvim" package manager for Neovim on the system
303 | ###############################################################################
304 | install_lazy_nvim() {
305 | lazy_nvim_repo="https://github.com/folke/lazy.nvim"
306 | lazy_path="$HOME/.local/share/nvim/lazy/lazy.nvim"
307 |
308 | info "Preparing to setup up the LazyNvim package manager for Neovim..."
309 |
310 | # If the LazyNvim installation directory doesn't exist, create it
311 | if [[ ! -d "$lazy_path" ]]; then
312 | mkdir --parents "$lazy_path"
313 | fi
314 |
315 | # Exit script execution safely if Git isn't installed and/or accessible
316 | if ! command -v git &> /dev/null; then
317 | error "Failed to installed LazyNvim...please ensure Git is installed!"
318 | exit 1
319 | fi
320 |
321 | # Clone the LazyNvim source repository to the local machine for usage
322 | git clone --filter=blob:none $lazy_nvim_repo --branch=stable "$lazy_path" \
323 | &> /dev/null
324 |
325 | success "LazyNvim installation complete!"
326 | }
327 |
328 | ###############################################################################
329 | # Install some ZSH plugns
330 | ###############################################################################
331 | install_zsh_plugins() {
332 | declare -a plugins
333 |
334 | # Location where the ZSH plugins will be downloaded to
335 | plugins_parent_directory="$HOME/.zsh/plugins"
336 |
337 | # List of all the ZSH plugins
338 | plugins=(
339 | "https://github.com/zsh-users/zsh-autosuggestions.git"
340 | "https://github.com/zsh-users/zsh-syntax-highlighting.git"
341 | "https://github.com/zsh-users/zsh-completions.git"
342 | "https://github.com/ael-code/zsh-colored-man-pages.git"
343 | )
344 |
345 | info "Preparing to install the ZSH plugins..."
346 |
347 | # Create the parent ZSH plugins directory if it doesn't already exist
348 | if [[ ! -d $plugins_parent_directory ]]; then
349 | mkdir --parents "$plugins_parent_directory"
350 | fi
351 |
352 | # Ensure Git is installed & executable, else exit the script execution safely
353 | if [[ $(command -v git &> /dev/null) ]]; then
354 | error "Git not found...please ensure its installed and executable!"
355 | exit 1
356 | fi
357 |
358 | # Loop through the list of plugins to install
359 | for plugin_url in "${plugins[@]}"; do
360 | plugin_name=$(basename "$plugin_url" .git)
361 |
362 | target_dir="$plugins_parent_directory/$plugin_name"
363 |
364 | # If the plugins wasn't already installed, download it locally
365 | if [[ ! -d "$target_dir" ]]; then
366 | git clone "$plugin_url" "$target_dir"
367 | fi
368 | done
369 |
370 | success "ZSH plugins installation complete!"
371 |
372 | info "The plugins will be usable after a system restart..."
373 | }
374 |
375 | ###############################################################################
376 | # Setup the dotfiles and related configuration files
377 | ###############################################################################
378 | setup_dotfiles() {
379 | info "Preparing to download and setup the dotfiles..."
380 |
381 | # Check if git is installed & executable else exit safely
382 | if ! command -v git &> /dev/null; then
383 | error "Git not found...please ensure its installed and executable!"
384 | exit 1
385 | fi
386 |
387 | git clone https://github.com/Jarmos-san/dotfiles "$HOME"/.dotfiles
388 |
389 | # Create symlinks of the dotfiles
390 | for file in "$HOME"/.dotfiles/dotfiles/*; do
391 | if [[ -f "$file" || -d "$file" ]]; then
392 | ln --symbolic "$file" "$HOME"
393 | info "Created symlink for $file"
394 | fi
395 | done
396 |
397 | success "Dotfiles setup complete!"
398 | }
399 |
400 | ###############################################################################
401 | # Install Homebrew only on Linux and MacOS systems
402 | ###############################################################################
403 | install_homebrew() {
404 | installation_script=https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh
405 |
406 | if [[ $(uname -s) == "Darwin" ]] || [[ $(uname) == "Linux" ]]; then
407 | NONINTERACTIVE=1 /bin/bash -c \
408 | "$(curl --fail --silent --show-error --location ${installation_script})"
409 | fi
410 | }
411 |
412 | ###############################################################################
413 | # Install Homebrew packages on either Linux or MacOS systems
414 | ###############################################################################
415 | install_homebrew_packages() {
416 | linux_brewfile=$HOME/.dotfiles/dotfiles/linux.Brewfile
417 | macos_brewfile=$HOME/.dotfiles/dotfiles/macos.Brewfile
418 |
419 | if [[ ! $(command -v brew &> /dev/null) ]]; then
420 | error "Homebrew not found...aborting package installation!"
421 | exit 1
422 | fi
423 |
424 | if [[ $(uname -s) == "Linux" ]] && [[ -e $linux_brewfile ]] && [[ -f $linux_brewfile ]]; then
425 | brew bundle --file "$linux_brewfile"
426 | fi
427 |
428 | if [[ $(uname -s) == "Darwin" ]] && [[ -e $macos_brewfile ]] && [[ -f $macos_brewfile ]]; then
429 | brew bundle --file "$macos_brewfile"
430 | fi
431 | }
432 |
433 | ###############################################################################
434 | # Setup ZSH as the default shell
435 | ###############################################################################
436 | setup_zsh() {
437 | command -v zsh | sudo tee -a /etc/shells
438 | sudo chsh -s "$(command -v zsh)" "${USER}"
439 | }
440 |
441 | ###############################################################################
442 | # Setup Git credentials (and potentially other things like SSH access and more!)
443 | ###############################################################################
444 | setup_git() {
445 | git_config_dir="$HOME/.config/git"
446 |
447 | if [[ ! -d $git_config_dir ]]; then
448 | mkdir --parents "$git_config_dir"
449 | else
450 | echo "Failed to create the ${git_config_dir} directory!"
451 | exit 1
452 | fi
453 |
454 | cat << EOF > "${git_config_dir}"/credentials
455 | [user]
456 | email = $git_email
457 | name = $git_name
458 | EOF
459 | }
460 |
461 | ###############################################################################
462 | # The entrypoint of the script which will run the script as per the prescribed
463 | # logic
464 | ###############################################################################
465 | main() {
466 | # Perform a preliminary system update before starting the automated setup
467 | update_system
468 |
469 | # Configure the system for passwordless sudo privileges
470 | sudo_nopasswd
471 |
472 | # Ensure certain folders are present and/or created for a smooth operation
473 | create_necessary_dirs
474 |
475 | # FIXME: Identify ways to automate SSH setup
476 | # Setup SSH for Git/GitHub for cloning/managing the dotfiles itself
477 | # setup_github_ssh
478 |
479 | echo "Setting up system automatically!"
480 |
481 | # Install the fonts for systems with a Linux DE (excluding WSL2 environments)
482 | setup_fonts
483 |
484 | # Install prerequisite tools before the automated setup
485 | install_prerequisite_tools
486 |
487 | # Install and setup the "lazy.nvim" package manager for Neovim
488 | install_lazy_nvim
489 |
490 | # Install all necessary ZSH plugins
491 | install_zsh_plugins
492 |
493 | # Setup the dotfiles (like setting up the symlinks and so on)
494 | setup_dotfiles
495 |
496 | # Install the Homebrew package manager
497 | install_homebrew
498 |
499 | # Install necessary tools using the Homebrew package manager
500 | install_homebrew_packages
501 |
502 | # Make ZSH the default interactive shell environment
503 | setup_zsh
504 |
505 | # Setup Git to work well with GitHub
506 | setup_git
507 |
508 | info "System setup complete! Please restart the system before usage."
509 | }
510 |
511 | # Defer running the script till the last moment for safety reasons
512 | main "$@"
513 |
--------------------------------------------------------------------------------