feat manage script
This commit is contained in:
commit
1a3a374f3b
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
**/.DS_Store
|
||||
.dotfiles_env
|
||||
117
README.md
Normal file
117
README.md
Normal file
@ -0,0 +1,117 @@
|
||||
# dotfiles
|
||||
```shell
|
||||
git clone https://gitea.tomastm.com/tomas.mirchev/dotfiles.git ~/.dotfiles
|
||||
cd ~/.dotfiles
|
||||
./install.py
|
||||
```
|
||||
|
||||
Do not forget to change the remote from https to ssh
|
||||
```shell
|
||||
git remote set-url origin git@gitea.tomastm.com:tomas.mirchev/dotfiles.git
|
||||
git remote -v
|
||||
```
|
||||
|
||||
### Todo
|
||||
- [ ] Uninstall option
|
||||
- [ ] Fix inconsistencies with usage fn
|
||||
|
||||
---
|
||||
|
||||
# Notes for README
|
||||
- How to update dotfiles? By default, they are symlinked.
|
||||
-> Directly modify `config/shared/<config>` or `config/envs/<env>/<config>`
|
||||
-> If new config, add it to `config.json` too.
|
||||
-> And simply run `./manage.py link <env>`. If needed, do not forget to update the `config.json#install` or `homebrew dump`.
|
||||
- How to unlink?
|
||||
-> Just remove the symlink and unspecify it from `config.json` to keep it updated for the future.
|
||||
|
||||
# Files and steps
|
||||
Scripts:
|
||||
- macos-save_homebrew.sh
|
||||
- macos-install_homebrew.sh
|
||||
- macos-change_hostname --hostname
|
||||
- linux-setup_docker.sh
|
||||
- linux-change_hostname --hostname
|
||||
- setup_shh.sh -C $USER@$HOSTNAME -f internal|git|none
|
||||
|
||||
Setups:
|
||||
- macos (--hostname)
|
||||
- linux-vm (--hostname)
|
||||
- linux-dev
|
||||
|
||||
|
||||
# For MacOS
|
||||
```
|
||||
$ git clone https://gitea.tomastm.com/tomas.mirchev/dotfiles.git .dotfiles
|
||||
$ cd .dotfiles
|
||||
$ ./manage.py setup macos --hostname macbook-pro
|
||||
-> Install homebrew
|
||||
-> Install all apps from dump (also stored in ./config/envs/macos)
|
||||
-> run: ./manage.py link macos (git, zsh, nvim-vanilla, tmux, karabiner, linearmouse, ghostty)
|
||||
-> from shared: git, zsh, tmux, nvim-simple
|
||||
-> from env macos: karabiner, linearmouse, ghostty
|
||||
-> execute: ./scripts/macos-change_hostname --hostname $HOSTNAME
|
||||
-> execute: ./scripts/setup_ssh.sh -C $USER@$HOSTNAME -f internal (-f: id_ed25519_internal)
|
||||
-> execute: ./scripts/setup_ssh.sh -C $USER@$HOSTNAME -f git (-f: id_ed25519_git)
|
||||
-> echo: "internal key generated, once vms and dns are ready: ssh-copy-id tomas@ip"
|
||||
-> echo: "You ssh pub key is: <key>". do not forget to change from https to git
|
||||
-> echo: "Do not forget to change git remote from https to git after adding SSH Key"
|
||||
-> echo: "Next steps: setup UTM and DNS" (maybe store DNS settings in private repo)
|
||||
-> todo: Add WindowTagger automatically too. In the meantime, echo it and reference to the repo.
|
||||
```
|
||||
|
||||
# For LinuxVM
|
||||
## Create VM
|
||||
### MacOS host with UTM
|
||||
- Download the ISO for architecture ARM64.
|
||||
- Create the VM with UTM.
|
||||
- It is recommended to setup local DNS with `dnsmasq`.
|
||||
|
||||
### Other hosts
|
||||
- Download the ISO for architecture AMD64.
|
||||
- Setup Proxmox and create the VM.
|
||||
|
||||
## Setup VM
|
||||
```
|
||||
$ git clone https://gitea.tomastm.com/tomas.mirchev/dotfiles.git .dotfiles
|
||||
$ cd .dotfiles
|
||||
$ ./manage.py setup linux-vm --hostname <personal|university|client>-<utm|workstation>
|
||||
-> execute: ./scripts/linux-setup_sudoers.sh
|
||||
-> execute: mkdir /home/$USER/projects
|
||||
-> execute: ./scripts/linux-setup_docker.sh
|
||||
-> execute: ./scripts/linux-change_hostname.sh --hostname $HOSTNAME
|
||||
-> execute: ./scripts/setup_ssh.sh -C $USER@HOSTNAME -f "" (-f: id_ed25519)
|
||||
-> run: ./manage.py install linux-vm
|
||||
-> run: ./manage.py link linux-vm
|
||||
-> from shared: git, zsh, tmux, nvim-simple
|
||||
-> echo: "You ssh pub key is: ". do not forget to change from https to git
|
||||
-> echo: "use `dev` for bla bla"
|
||||
```
|
||||
|
||||
# For LinuxDev
|
||||
Build with multi-stage.
|
||||
|
||||
## base-debian
|
||||
### Stage 1 - Setup NeoVim
|
||||
```
|
||||
RUN apt install python3
|
||||
RUN git clone https://gitea.tomastm.com/tomas.mirchev/dotfiles.git .dotfiles \
|
||||
&& cd .dotfiles \
|
||||
&& ./manage.py setup linux-dev
|
||||
-> wget tree-sitter && move (check architecture)
|
||||
-> wget nvim.deb && install (check architecture)
|
||||
-> nvim !lazy restore plugins
|
||||
```
|
||||
### Stage 2
|
||||
- copy-from: .dotfiles & `./setup.py --env-linux-c --copy`
|
||||
- copy-from: tree-sitter
|
||||
- copy-from: `nvim.deb` & `apt install ./nvim.deb`
|
||||
- copy-from: .local/share/nvim
|
||||
- Setup locales (check debian setup)
|
||||
- Create dev user
|
||||
- Create workspace directory
|
||||
|
||||
## node
|
||||
|
||||
## python
|
||||
|
||||
75
config.json
Normal file
75
config.json
Normal file
@ -0,0 +1,75 @@
|
||||
{
|
||||
"template": {
|
||||
"htop": {
|
||||
"link": { "from": "shared/htop", "to": "~/.config/htop" }
|
||||
},
|
||||
"bin": {
|
||||
"link": { "from": "shared/bin", "to": "~/bin" }
|
||||
},
|
||||
"vim": {
|
||||
"link": { "from": "shared/vim", "to": "~/.vimrc" },
|
||||
"post-link": "curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim && vim -es -u ~/.vimrc -i NONE -c 'PlugInstall' -c 'qa'"
|
||||
},
|
||||
"nvim": {
|
||||
"link": { "from": "shared/nvim", "to": "~/.config/nvim" },
|
||||
"post-link": "nvim --headless '+Lazy! restore' +qa && echo 'alias vim=nvim' >> ~/.zshrc"
|
||||
},
|
||||
"zsh": {
|
||||
"link": { "from": "shared/zsh", "to": "~/.zshrc" },
|
||||
"install": "./scripts/linux-setup_zsh.sh"
|
||||
},
|
||||
"tmux": {
|
||||
"link": { "from": "shared/tmux", "to": "~/.tmux.conf" }
|
||||
},
|
||||
"git": {
|
||||
"link": { "from": "shared/git", "to": "~/.gitconfig" }
|
||||
},
|
||||
"wezterm": {
|
||||
"link": { "from": "shared/wezterm", "to": "~/.wezterm.lua" }
|
||||
},
|
||||
"alacritty": {
|
||||
"link": { "from": "shared/alacritty", "to": "~/.alacritty.toml" }
|
||||
},
|
||||
"ghostty": {
|
||||
"link": { "from": "shared/ghostty", "to": "~/.config/ghostty" }
|
||||
}
|
||||
},
|
||||
"environments": {
|
||||
"macos": [
|
||||
"zsh",
|
||||
"tmux",
|
||||
"nvim",
|
||||
"git",
|
||||
"ghostty",
|
||||
{
|
||||
"package": "karabiner",
|
||||
"link": { "from": "macos/karabiner", "to": "~/.config/karabiner" }
|
||||
},
|
||||
{
|
||||
"package": "linearmouse",
|
||||
"link": { "from": "macos/linearmouse", "to": "~/.config/linearmouse" }
|
||||
}
|
||||
],
|
||||
"linux-vm": [
|
||||
"zsh",
|
||||
"tmux",
|
||||
"nvim",
|
||||
"git",
|
||||
"htop",
|
||||
"bin"
|
||||
],
|
||||
"linux-dev": [
|
||||
"zsh",
|
||||
"tmux",
|
||||
{
|
||||
"package": "nvim",
|
||||
"ignore-template": true,
|
||||
"link": { "from": "linux-dev/nvim", "to": "~/.config/nvim" },
|
||||
"post-link": "nvim --headless '+Lazy! restore' +qa && echo 'alias vim=nvim' >> ~/.zshrc"
|
||||
},
|
||||
"git",
|
||||
"htop",
|
||||
"bin"
|
||||
]
|
||||
}
|
||||
}
|
||||
3
config/linux-dev/nvim/init.lua
Normal file
3
config/linux-dev/nvim/init.lua
Normal file
@ -0,0 +1,3 @@
|
||||
require('config.options') -- vim options
|
||||
require('config.keymaps') -- keymaps
|
||||
require('config.lazy') -- plugin manager and plugins
|
||||
25
config/linux-dev/nvim/lazy-lock.json
Normal file
25
config/linux-dev/nvim/lazy-lock.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"cmp-nvim-lsp": { "branch": "main", "commit": "39e2eda76828d88b773cc27a3f61d2ad782c922d" },
|
||||
"cmp-path": { "branch": "main", "commit": "91ff86cd9c29299a64f968ebb45846c485725f23" },
|
||||
"conform.nvim": { "branch": "master", "commit": "d28ccf945374edd9f1c34a82f6c22261dbd8ab98" },
|
||||
"fidget.nvim": { "branch": "main", "commit": "e2a175c2abe2d4f65357da1c98c59a5cfb2b543f" },
|
||||
"harpoon": { "branch": "harpoon2", "commit": "a84ab829eaf3678b586609888ef52f7779102263" },
|
||||
"indent-blankline.nvim": { "branch": "master", "commit": "e51b651ca26cba250ef3a1150c8d35045eee2a84" },
|
||||
"lazy.nvim": { "branch": "main", "commit": "7e6c863bc7563efbdd757a310d17ebc95166cef3" },
|
||||
"mason-lspconfig.nvim": { "branch": "main", "commit": "4d0e5b49363cac187326998b96aa6a2884e0e89b" },
|
||||
"mason.nvim": { "branch": "main", "commit": "e2f7f9044ec30067bc11800a9e266664b88cda22" },
|
||||
"neo-tree.nvim": { "branch": "main", "commit": "a77af2e764c5ed4038d27d1c463fa49cd4794e07" },
|
||||
"nui.nvim": { "branch": "main", "commit": "b58e2bfda5cea347c9d58b7f11cf3012c7b3953f" },
|
||||
"nvim-autopairs": { "branch": "master", "commit": "ee297f215e95a60b01fde33275cc3c820eddeebe" },
|
||||
"nvim-cmp": { "branch": "main", "commit": "f17d9b4394027ff4442b298398dfcaab97e40c4f" },
|
||||
"nvim-lspconfig": { "branch": "master", "commit": "bc6ada4b0892b7f10852c0b8ca7209fd39a6d754" },
|
||||
"nvim-treesitter": { "branch": "master", "commit": "7dc8aabe86db8c2f23520e8334f7584f83e84342" },
|
||||
"nvim-ts-autotag": { "branch": "main", "commit": "1cca23c9da708047922d3895a71032bc0449c52d" },
|
||||
"nvim-web-devicons": { "branch": "master", "commit": "e87554285f581047b1bf236794b0eb812b444b87" },
|
||||
"plenary.nvim": { "branch": "master", "commit": "2d9b06177a975543726ce5c73fca176cedbffe9d" },
|
||||
"rose-pine": { "branch": "main", "commit": "91548dca53b36dbb9d36c10f114385f759731be1" },
|
||||
"schemastore.nvim": { "branch": "main", "commit": "f8d6e9068861888651f68958521b1958314aac41" },
|
||||
"telescope-fzf-native.nvim": { "branch": "main", "commit": "cf48d4dfce44e0b9a2e19a008d6ec6ea6f01a83b" },
|
||||
"telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" },
|
||||
"telescope.nvim": { "branch": "0.1.x", "commit": "a0bbec21143c7bc5f8bb02e0005fa0b982edc026" }
|
||||
}
|
||||
49
config/linux-dev/nvim/lua/config/keymaps.lua
Normal file
49
config/linux-dev/nvim/lua/config/keymaps.lua
Normal file
@ -0,0 +1,49 @@
|
||||
local remap = require("utils.remap")
|
||||
|
||||
remap.nmap("<leader>q", vim.diagnostic.setloclist, { desc = "Open diagnostic [Q]uickfix list" })
|
||||
|
||||
remap.imap("jk", "<Esc>", { desc = "Exit insert mode with jk" })
|
||||
remap.nmap("<Esc>", "<cmd>nohlsearch<CR>", { desc = "Clear highlights" })
|
||||
|
||||
-- Prevent "x" from overriding the register
|
||||
remap.nmap("x", '"_x')
|
||||
|
||||
-- Window Navigation
|
||||
remap.nmap("<C-h>", "<C-w>h", { desc = "Move focus to the left window" })
|
||||
remap.nmap("<C-l>", "<C-w>l", { desc = "Move focus to the right window" })
|
||||
remap.nmap("<C-j>", "<C-w>j", { desc = "Move focus to the lower window" })
|
||||
remap.nmap("<C-k>", "<C-w>k", { desc = "Move focus to the upper window" })
|
||||
|
||||
-- Tab management
|
||||
remap.nmap("<Leader>tn", ":tabnew<CR>", { desc = "[T]ab [N]ew" })
|
||||
remap.nmap("<Leader>tc", ":tabclose<CR>", { desc = "[T]ab [C]lose" })
|
||||
remap.nmap("<Leader>to", ":tabonly<CR>", { desc = "[T]ab [O]nly" })
|
||||
remap.nmap("<Leader>tl", ":tabnext<CR>", { desc = "[T]ab Next" })
|
||||
remap.nmap("<Leader>th", ":tabprevious<CR>", { desc = "[T]ab Previous" })
|
||||
remap.nmap("<Leader>tm.", ":tabmove +1<CR>", { desc = "[T]ab [M]ove Right" })
|
||||
remap.nmap("<Leader>tm,", ":tabmove -1<CR>", { desc = "[T]ab [M]ove Left" })
|
||||
for i = 1, 9 do
|
||||
remap.nmap(string.format("<Leader>%d", i), string.format("%dgt", i), { desc = string.format("[T]ab %d", i) })
|
||||
end
|
||||
|
||||
-- Buffer Management
|
||||
remap.nmap("<Leader>bl", ":ls<CR>", { desc = "[B]uffer [L]ist" })
|
||||
remap.nmap("<Leader>bd", ":bdelete<CR>", { desc = "[B]uffer [D]elete" })
|
||||
remap.nmap("]b", ":bnext<CR>", { desc = "[B]uffer [N]ext" })
|
||||
remap.nmap("[b", ":bprevious<CR>", { desc = "[B]uffer [P]revious" })
|
||||
remap.nmap("<Leader>bb", ":b<Space>", { desc = "[B]uffer Select" })
|
||||
remap.nmap("<Leader>bo", ":bufdo bd|1bd<CR>", { desc = "[B]uffer Delete Others" })
|
||||
|
||||
-- Terminal
|
||||
remap.nmap("<Leader>tet", function()
|
||||
vim.cmd("terminal")
|
||||
vim.cmd("startinsert")
|
||||
end, { desc = "[T]erminal" })
|
||||
remap.nmap("<leader>ter", function()
|
||||
local buf_dir = vim.fn.expand("%:p:h")
|
||||
vim.cmd("edit term://" .. buf_dir .. "//zsh")
|
||||
vim.cmd("startinsert")
|
||||
end, { desc = "[T]erminal [R]elative" })
|
||||
remap.tmap("<Esc>", "<C-\\><C-n>", { desc = "Terminal Normal Mode" })
|
||||
remap.tmap("jk", "<C-\\><C-n>", { desc = "Terminal Normal Mode" })
|
||||
remap.tmap("<C-w>", "<C-\\><C-n><C-w>", { desc = "Terminal Window Command" })
|
||||
11
config/linux-dev/nvim/lua/config/lazy.lua
Normal file
11
config/linux-dev/nvim/lua/config/lazy.lua
Normal file
@ -0,0 +1,11 @@
|
||||
local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim'
|
||||
if not (vim.uv or vim.loop).fs_stat(lazypath) then
|
||||
local lazyrepo = 'https://github.com/folke/lazy.nvim.git'
|
||||
local out = vim.fn.system { 'git', 'clone', '--filter=blob:none', '--branch=stable', lazyrepo, lazypath }
|
||||
if vim.v.shell_error ~= 0 then
|
||||
error('Error cloning lazy.nvim:\n' .. out)
|
||||
end
|
||||
end ---@diagnostic disable-next-line: undefined-field
|
||||
vim.opt.rtp:prepend(lazypath)
|
||||
|
||||
require('lazy').setup('plugins')
|
||||
86
config/linux-dev/nvim/lua/config/options.lua
Normal file
86
config/linux-dev/nvim/lua/config/options.lua
Normal file
@ -0,0 +1,86 @@
|
||||
-- Map Leader
|
||||
vim.g.mapleader = " "
|
||||
vim.g.maplocalleader = " "
|
||||
|
||||
-- Use Nerd Font
|
||||
vim.g.have_nerd_font = true
|
||||
|
||||
-- Add vertical line
|
||||
-- vim.opt.colorcolumn = "100"
|
||||
|
||||
-- Enable TrueColor
|
||||
vim.opt.termguicolors = true
|
||||
|
||||
-- Disable Neovim background
|
||||
vim.api.nvim_set_hl(0, "Normal", { bg = "none" })
|
||||
vim.api.nvim_set_hl(0, "NormalFloat", { bg = "none" })
|
||||
|
||||
-- Scroll lines/columns
|
||||
vim.opt.mousescroll = "hor:1,ver:1"
|
||||
|
||||
-- Set indentation preferences
|
||||
vim.opt.expandtab = true -- Convert tabs to spaces
|
||||
vim.opt.shiftwidth = 2 -- Number of spaces for auto-indent
|
||||
vim.opt.tabstop = 2 -- Number of spaces a tab counts for
|
||||
vim.opt.softtabstop = 2 -- Number of spaces a tab counts for when editing
|
||||
vim.opt.autoindent = true -- Copy indent from current line when starting new line
|
||||
vim.opt.smartindent = true -- Do smart autoindenting when starting a new line
|
||||
|
||||
-- Disable line wrapping
|
||||
vim.opt.wrap = false
|
||||
|
||||
-- Enable break indent
|
||||
vim.opt.breakindent = true
|
||||
|
||||
-- Make line numbers default
|
||||
vim.opt.number = true
|
||||
vim.opt.relativenumber = true
|
||||
|
||||
-- Enable mouse mode, can be useful for resizing splits for example
|
||||
vim.opt.mouse = "a"
|
||||
|
||||
-- Full path on status line
|
||||
vim.opt.statusline = "%F%m%r%h%w%=%l,%c %P"
|
||||
|
||||
-- Sync clipboard between OS and Neovim
|
||||
vim.schedule(function()
|
||||
vim.opt.clipboard = "unnamedplus"
|
||||
end)
|
||||
|
||||
-- Save undo history
|
||||
vim.opt.undofile = true
|
||||
|
||||
-- Case-insensitive searching UNLESS \C or one or more capital letters in the search term
|
||||
vim.opt.ignorecase = true
|
||||
vim.opt.smartcase = true
|
||||
|
||||
-- Decrease update time
|
||||
vim.opt.updatetime = 250
|
||||
|
||||
-- Decrease mapped sequence wait time
|
||||
-- Displays which-key popup sooner
|
||||
vim.opt.timeoutlen = 300
|
||||
|
||||
-- Configure how new splits should be opened
|
||||
vim.opt.splitright = true
|
||||
vim.opt.splitbelow = true
|
||||
|
||||
-- Sets how neovim will display certain whitespace characters in the editor.
|
||||
vim.opt.list = true
|
||||
vim.opt.listchars = { tab = "» ", trail = "·", nbsp = "␣" }
|
||||
|
||||
-- Preview substitutions live, as you type
|
||||
vim.opt.inccommand = "split"
|
||||
|
||||
-- Show which line your cursor is on
|
||||
vim.opt.cursorline = true
|
||||
|
||||
-- Minimal number of screen lines to keep above and below the cursor
|
||||
vim.opt.scrolloff = 10
|
||||
|
||||
-- Highlight when yanking (copying) text
|
||||
vim.api.nvim_create_autocmd("TextYankPost", {
|
||||
callback = function()
|
||||
vim.highlight.on_yank()
|
||||
end,
|
||||
})
|
||||
40
config/linux-dev/nvim/lua/plugins/autoformat.lua
Normal file
40
config/linux-dev/nvim/lua/plugins/autoformat.lua
Normal file
@ -0,0 +1,40 @@
|
||||
return { -- Autoformat
|
||||
"stevearc/conform.nvim",
|
||||
event = { "BufWritePre" },
|
||||
cmd = { "ConformInfo" },
|
||||
keys = {
|
||||
{
|
||||
"<leader>f",
|
||||
function()
|
||||
require("conform").format({ async = true, lsp_format = "fallback" })
|
||||
end,
|
||||
mode = "",
|
||||
desc = "[F]ormat buffer",
|
||||
},
|
||||
},
|
||||
opts = {
|
||||
notify_on_error = false,
|
||||
format_on_save = function(bufnr)
|
||||
local disable_filetypes = { c = true, cpp = true }
|
||||
local lsp_format_opt
|
||||
if disable_filetypes[vim.bo[bufnr].filetype] then
|
||||
lsp_format_opt = "never"
|
||||
else
|
||||
lsp_format_opt = "fallback"
|
||||
end
|
||||
return {
|
||||
timeout_ms = 500,
|
||||
lsp_format = lsp_format_opt,
|
||||
}
|
||||
end,
|
||||
formatters_by_ft = {
|
||||
lua = { "stylua" },
|
||||
swift = { "swift_format" },
|
||||
python = { "isort", "black", stop_after_first = true },
|
||||
javascript = { "prettierd", "prettier", stop_after_first = true },
|
||||
javascriptreact = { "prettierd", "prettier", stop_after_first = true },
|
||||
typescript = { "prettierd", "prettier", stop_after_first = true },
|
||||
typescriptreact = { "prettierd", "prettier", stop_after_first = true },
|
||||
},
|
||||
},
|
||||
}
|
||||
13
config/linux-dev/nvim/lua/plugins/autopairs.lua
Normal file
13
config/linux-dev/nvim/lua/plugins/autopairs.lua
Normal file
@ -0,0 +1,13 @@
|
||||
return {
|
||||
'windwp/nvim-autopairs',
|
||||
event = 'InsertEnter',
|
||||
-- Optional dependency
|
||||
dependencies = { 'hrsh7th/nvim-cmp' },
|
||||
config = function()
|
||||
require('nvim-autopairs').setup {}
|
||||
-- If you want to automatically add `(` after selecting a function or method
|
||||
local cmp_autopairs = require 'nvim-autopairs.completion.cmp'
|
||||
local cmp = require 'cmp'
|
||||
cmp.event:on('confirm_done', cmp_autopairs.on_confirm_done())
|
||||
end,
|
||||
}
|
||||
11
config/linux-dev/nvim/lua/plugins/autotag.lua
Normal file
11
config/linux-dev/nvim/lua/plugins/autotag.lua
Normal file
@ -0,0 +1,11 @@
|
||||
return {
|
||||
"windwp/nvim-ts-autotag",
|
||||
config = {
|
||||
autotag = {
|
||||
enable = true,
|
||||
enable_close = true,
|
||||
enable_rename = true,
|
||||
enable_close_on_slash = true,
|
||||
},
|
||||
},
|
||||
}
|
||||
11
config/linux-dev/nvim/lua/plugins/colorscheme.lua
Normal file
11
config/linux-dev/nvim/lua/plugins/colorscheme.lua
Normal file
@ -0,0 +1,11 @@
|
||||
return {
|
||||
"rose-pine/neovim",
|
||||
name = "rose-pine",
|
||||
config = function()
|
||||
require("rose-pine").setup({
|
||||
disable_background = true,
|
||||
disable_float_background = true,
|
||||
})
|
||||
vim.cmd("colorscheme rose-pine")
|
||||
end,
|
||||
}
|
||||
60
config/linux-dev/nvim/lua/plugins/completion.lua
Normal file
60
config/linux-dev/nvim/lua/plugins/completion.lua
Normal file
@ -0,0 +1,60 @@
|
||||
return {
|
||||
"hrsh7th/nvim-cmp",
|
||||
event = "InsertEnter",
|
||||
dependencies = {
|
||||
"hrsh7th/cmp-nvim-lsp",
|
||||
"hrsh7th/cmp-path",
|
||||
},
|
||||
config = function()
|
||||
local cmp = require("cmp")
|
||||
cmp.setup({
|
||||
window = {
|
||||
completion = {
|
||||
border = "single",
|
||||
-- or border = true for default border
|
||||
},
|
||||
documentation = {
|
||||
border = "single",
|
||||
},
|
||||
},
|
||||
completion = { completeopt = "menu,menuone,noselect" }, -- This ensures nothing is auto-selected
|
||||
sources = cmp.config.sources({
|
||||
{ name = "nvim_lsp" }, -- from language server
|
||||
{ name = "buffer" }, -- from current buffer
|
||||
{ name = "path" }, -- for file paths
|
||||
}),
|
||||
mapping = cmp.mapping.preset.insert({
|
||||
["<Tab>"] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
cmp.select_next_item({ behavior = cmp.SelectBehavior.Insert })
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end),
|
||||
["<S-Tab>"] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
cmp.select_prev_item({ behavior = cmp.SelectBehavior.Insert })
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end),
|
||||
["<C-e>"] = cmp.mapping.abort(), -- This closes the completion menu
|
||||
|
||||
["<C-u>"] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() and cmp.get_selected_entry() then
|
||||
cmp.scroll_docs(-4)
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end),
|
||||
["<C-d>"] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() and cmp.get_selected_entry() then
|
||||
cmp.scroll_docs(4)
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end),
|
||||
}),
|
||||
})
|
||||
end,
|
||||
}
|
||||
42
config/linux-dev/nvim/lua/plugins/harpoon2.lua
Normal file
42
config/linux-dev/nvim/lua/plugins/harpoon2.lua
Normal file
@ -0,0 +1,42 @@
|
||||
return {
|
||||
"ThePrimeagen/harpoon",
|
||||
branch = "harpoon2",
|
||||
opts = {
|
||||
menu = {
|
||||
width = vim.api.nvim_win_get_width(0) - 4,
|
||||
},
|
||||
settings = {
|
||||
save_on_toggle = true,
|
||||
},
|
||||
},
|
||||
keys = function()
|
||||
local keys = {
|
||||
{
|
||||
"<leader>H",
|
||||
function()
|
||||
require("harpoon"):list():add()
|
||||
end,
|
||||
desc = "Harpoon File",
|
||||
},
|
||||
{
|
||||
"<leader>h",
|
||||
function()
|
||||
local harpoon = require("harpoon")
|
||||
harpoon.ui:toggle_quick_menu(harpoon:list())
|
||||
end,
|
||||
desc = "Harpoon Quick Menu",
|
||||
},
|
||||
}
|
||||
|
||||
for i = 1, 5 do
|
||||
table.insert(keys, {
|
||||
"<C-" .. i .. ">",
|
||||
function()
|
||||
require("harpoon"):list():select(i)
|
||||
end,
|
||||
desc = "Harpoon to File " .. i,
|
||||
})
|
||||
end
|
||||
return keys
|
||||
end,
|
||||
}
|
||||
9
config/linux-dev/nvim/lua/plugins/indent_line.lua
Normal file
9
config/linux-dev/nvim/lua/plugins/indent_line.lua
Normal file
@ -0,0 +1,9 @@
|
||||
return {
|
||||
{ -- Add indentation guides even on blank lines
|
||||
'lukas-reineke/indent-blankline.nvim',
|
||||
-- Enable `lukas-reineke/indent-blankline.nvim`
|
||||
-- See `:help ibl`
|
||||
main = 'ibl',
|
||||
opts = {},
|
||||
},
|
||||
}
|
||||
98
config/linux-dev/nvim/lua/plugins/lsp.lua
Normal file
98
config/linux-dev/nvim/lua/plugins/lsp.lua
Normal file
@ -0,0 +1,98 @@
|
||||
local remap = require("utils.remap")
|
||||
|
||||
vim.diagnostic.config({
|
||||
update_in_insert = false,
|
||||
virtual_text = {
|
||||
source = true,
|
||||
},
|
||||
float = {
|
||||
border = "rounded",
|
||||
},
|
||||
})
|
||||
|
||||
vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, {
|
||||
border = "rounded",
|
||||
})
|
||||
vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, {
|
||||
border = "rounded",
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
"neovim/nvim-lspconfig",
|
||||
dependencies = {
|
||||
{ "williamboman/mason.nvim", config = true },
|
||||
"williamboman/mason-lspconfig.nvim",
|
||||
{ "j-hui/fidget.nvim", opts = {} }, -- side fidget showing status
|
||||
"hrsh7th/cmp-nvim-lsp", -- completion
|
||||
"b0o/schemastore.nvim",
|
||||
},
|
||||
config = function()
|
||||
require("mason").setup()
|
||||
require("mason-lspconfig").setup()
|
||||
|
||||
local lspconfig = require("lspconfig")
|
||||
local capabilities = require("cmp_nvim_lsp").default_capabilities()
|
||||
|
||||
require("lspconfig.ui.windows").default_options = {
|
||||
border = "rounded",
|
||||
}
|
||||
|
||||
lspconfig.ts_ls.setup({
|
||||
capabilities = capabilities,
|
||||
init_options = {
|
||||
preferences = {
|
||||
includeCompletionsWithSnippetText = true,
|
||||
jsxAttributeCompletionStyle = "auto",
|
||||
},
|
||||
},
|
||||
on_attach = function(client, bufnr)
|
||||
-- Mappings
|
||||
local opts = { buffer = bufnr }
|
||||
remap.nmap("gd", vim.lsp.buf.definition, opts)
|
||||
remap.nmap("gr", vim.lsp.buf.references, opts)
|
||||
|
||||
remap.nmap("K", vim.lsp.buf.hover, opts)
|
||||
|
||||
remap.nmap("<leader>rn", vim.lsp.buf.rename, opts)
|
||||
remap.nmap("<leader>ca", vim.lsp.buf.code_action, opts)
|
||||
remap.nmap("<leader>ri", function()
|
||||
local diagnostics = vim.diagnostic.get(0)
|
||||
|
||||
-- Filter for TypeScript's unused import diagnostics (code 6133)
|
||||
local unused_imports_diagnostics = {}
|
||||
for _, diagnostic in ipairs(diagnostics) do
|
||||
if diagnostic.code == 6133 and diagnostic.source == "typescript" then
|
||||
table.insert(unused_imports_diagnostics, diagnostic)
|
||||
end
|
||||
end
|
||||
|
||||
vim.lsp.buf.code_action({
|
||||
context = {
|
||||
diagnostics = unused_imports_diagnostics,
|
||||
only = { "source.removeUnusedImports" },
|
||||
},
|
||||
})
|
||||
end, { desc = "Remove unused imports" })
|
||||
|
||||
remap.nmap("[d", vim.diagnostic.goto_prev, opts)
|
||||
remap.nmap("]d", vim.diagnostic.goto_next, opts)
|
||||
remap.nmap("<leader>d", vim.diagnostic.open_float, opts)
|
||||
end,
|
||||
})
|
||||
|
||||
lspconfig.eslint.setup({})
|
||||
lspconfig.html.setup({})
|
||||
lspconfig.cssls.setup({})
|
||||
lspconfig.jsonls.setup({
|
||||
capabilities = capabilities,
|
||||
settings = {
|
||||
json = {
|
||||
schemas = require("schemastore").json.schemas(),
|
||||
validate = { enable = true },
|
||||
allowComments = true,
|
||||
},
|
||||
},
|
||||
})
|
||||
end,
|
||||
}
|
||||
33
config/linux-dev/nvim/lua/plugins/neo-tree.lua
Normal file
33
config/linux-dev/nvim/lua/plugins/neo-tree.lua
Normal file
@ -0,0 +1,33 @@
|
||||
return {
|
||||
"nvim-neo-tree/neo-tree.nvim",
|
||||
version = "*",
|
||||
dependencies = {
|
||||
"nvim-lua/plenary.nvim",
|
||||
"nvim-tree/nvim-web-devicons",
|
||||
"MunifTanjim/nui.nvim",
|
||||
},
|
||||
cmd = "Neotree",
|
||||
keys = {
|
||||
{ "<Leader>et", ":Neotree position=left toggle<CR>", desc = "Explorer Toggle", silent = true },
|
||||
{ "<Leader>E", ":Neotree focus<CR>", desc = "Explorer Focus", silent = true },
|
||||
{ "<Leader>ef", ":Neotree float<CR>", desc = "Explorer Float", silent = true },
|
||||
{ "<Leader>eb", ":Neotree buffers<CR>", desc = "Explorer Buffers", silent = true },
|
||||
{ "<Leader>eg", ":Neotree git_status<CR>", desc = "Explorer Git", silent = true },
|
||||
},
|
||||
opts = {
|
||||
filesystem = {
|
||||
follow_current_file = {
|
||||
enabled = true, -- Enable this feature
|
||||
leave_dirs_open = true, -- Leave directories open when following
|
||||
},
|
||||
filtered_items = {
|
||||
visible = true,
|
||||
},
|
||||
window = {
|
||||
mappings = {
|
||||
["<Leader>e"] = "close_window",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
91
config/linux-dev/nvim/lua/plugins/telescope.lua
Normal file
91
config/linux-dev/nvim/lua/plugins/telescope.lua
Normal file
@ -0,0 +1,91 @@
|
||||
local remap = require("utils.remap")
|
||||
|
||||
return { -- Fuzzy Finder (files, lsp, etc)
|
||||
"nvim-telescope/telescope.nvim",
|
||||
event = "VimEnter",
|
||||
branch = "0.1.x",
|
||||
dependencies = {
|
||||
"nvim-lua/plenary.nvim",
|
||||
{ -- If encountering errors, see telescope-fzf-native README for installation instructions
|
||||
"nvim-telescope/telescope-fzf-native.nvim",
|
||||
|
||||
-- `build` is used to run some command when the plugin is installed/updated.
|
||||
-- This is only run then, not every time Neovim starts up.
|
||||
build = "make",
|
||||
|
||||
-- `cond` is a condition used to determine whether this plugin should be
|
||||
-- installed and loaded.
|
||||
cond = function()
|
||||
return vim.fn.executable("make") == 1
|
||||
end,
|
||||
},
|
||||
{ "nvim-telescope/telescope-ui-select.nvim" },
|
||||
|
||||
-- Useful for getting pretty icons, but requires a Nerd Font.
|
||||
{ "nvim-tree/nvim-web-devicons", enabled = vim.g.have_nerd_font },
|
||||
},
|
||||
config = function()
|
||||
-- Telescope is a fuzzy finder that comes with a lot of different things that
|
||||
-- it can fuzzy find! It's more than just a "file finder", it can search
|
||||
-- many different aspects of Neovim, your workspace, LSP, and more!
|
||||
--
|
||||
-- The easiest way to use Telescope, is to start by doing something like:
|
||||
-- :Telescope help_tags
|
||||
--
|
||||
-- After running this command, a window will open up and you're able to
|
||||
-- type in the prompt window. You'll see a list of `help_tags` options and
|
||||
-- a corresponding preview of the help.
|
||||
--
|
||||
-- Two important keymaps to use while in Telescope are:
|
||||
-- - Insert mode: <c-/>
|
||||
-- - Normal mode: ?
|
||||
--
|
||||
-- This opens a window that shows you all of the keymaps for the current
|
||||
-- Telescope picker. This is really useful to discover what Telescope can
|
||||
-- do as well as how to actually do it!
|
||||
|
||||
-- [[ Configure Telescope ]]
|
||||
-- See `:help telescope` and `:help telescope.setup()`
|
||||
require("telescope").setup({
|
||||
-- You can put your default mappings / updates / etc. in here
|
||||
-- All the info you're looking for is in `:help telescope.setup()`
|
||||
--
|
||||
-- defaults = {
|
||||
-- mappings = {
|
||||
-- i = { ['<c-enter>'] = 'to_fuzzy_refine' },
|
||||
-- },
|
||||
-- },
|
||||
-- pickers = {}
|
||||
defaults = {
|
||||
layout_strategy = "vertical",
|
||||
layout_config = {
|
||||
-- vertical = { width = 0.5 }
|
||||
-- horizontal = {
|
||||
-- width = 0.9,
|
||||
-- preview_width = 0.5,
|
||||
-- },
|
||||
},
|
||||
mappings = {
|
||||
n = {
|
||||
["d"] = "delete_buffer",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
-- Enable Telescope extensions if they are installed
|
||||
pcall(require("telescope").load_extension, "fzf")
|
||||
pcall(require("telescope").load_extension, "ui-select")
|
||||
|
||||
local builtin = require("telescope.builtin")
|
||||
remap.nmap("<leader>sk", builtin.keymaps, { desc = "[S]earch [K]eymaps" })
|
||||
remap.nmap("<leader>sf", builtin.find_files, { desc = "[S]earch [F]iles" })
|
||||
remap.nmap("<leader>sw", builtin.grep_string, { desc = "[S]earch current [W]ord" })
|
||||
remap.nmap("<leader>sg", builtin.live_grep, { desc = "[S]earch by [G]rep" })
|
||||
remap.nmap("<leader>sd", builtin.diagnostics, { desc = "[S]earch [D]iagnostics" })
|
||||
remap.nmap("<leader>sr", builtin.lsp_references, { desc = "[S]earch [R]references" })
|
||||
remap.nmap("<leader>s.", builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' })
|
||||
remap.nmap("<leader>ss", builtin.git_status, { desc = "[S]earch Git [S]tatus" })
|
||||
remap.nmap("<leader><leader>", builtin.buffers, { desc = "Find existing [B]uffers" })
|
||||
end,
|
||||
}
|
||||
21
config/linux-dev/nvim/lua/plugins/treesitter.lua
Normal file
21
config/linux-dev/nvim/lua/plugins/treesitter.lua
Normal file
@ -0,0 +1,21 @@
|
||||
return {
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
build = 'TSUpdate',
|
||||
main = 'nvim-treesitter.configs',
|
||||
opts = {
|
||||
ensure_installed = {
|
||||
'diff',
|
||||
'lua',
|
||||
'html',
|
||||
'css',
|
||||
'javascript',
|
||||
'typescript'
|
||||
},
|
||||
auto_install = true,
|
||||
highlight = {
|
||||
enable = true,
|
||||
},
|
||||
indent = { enable = true }
|
||||
}
|
||||
}
|
||||
|
||||
35
config/linux-dev/nvim/lua/utils/remap.lua
Normal file
35
config/linux-dev/nvim/lua/utils/remap.lua
Normal file
@ -0,0 +1,35 @@
|
||||
local M = {}
|
||||
|
||||
function M.map(mode, lhs, rhs, opts)
|
||||
local options = { silent = true, noremap = true }
|
||||
|
||||
if opts then
|
||||
options = vim.tbl_extend("force", options, opts)
|
||||
end
|
||||
|
||||
if type(mode) == "table" then
|
||||
for _, m in ipairs(mode) do
|
||||
vim.keymap.set(m, lhs, rhs, options)
|
||||
end
|
||||
else
|
||||
vim.keymap.set(mode, lhs, rhs, options)
|
||||
end
|
||||
end
|
||||
|
||||
function M.nmap(lhs, rhs, opts)
|
||||
M.map("n", lhs, rhs, opts)
|
||||
end
|
||||
|
||||
function M.imap(lhs, rhs, opts)
|
||||
M.map("i", lhs, rhs, opts)
|
||||
end
|
||||
|
||||
function M.vmap(lhs, rhs, opts)
|
||||
M.map("v", lhs, rhs, opts)
|
||||
end
|
||||
|
||||
function M.tmap(lhs, rhs, opts)
|
||||
M.map("t", lhs, rhs, opts)
|
||||
end
|
||||
|
||||
return M
|
||||
105
config/linux-dev/nvim/neovim-actions.md
Normal file
105
config/linux-dev/nvim/neovim-actions.md
Normal file
@ -0,0 +1,105 @@
|
||||
-- Window Creation/Closing
|
||||
Ctrl-w s - Split window horizontally
|
||||
Ctrl-w v - Split window vertically
|
||||
Ctrl-w n - Create new window horizontally with empty buffer
|
||||
Ctrl-w c - Close current window
|
||||
Ctrl-w o - Close all windows except current one
|
||||
|
||||
-- Window Navigation
|
||||
Ctrl-w h - Move to window on the left
|
||||
Ctrl-w j - Move to window below
|
||||
Ctrl-w k - Move to window above
|
||||
Ctrl-w l - Move to window on the right
|
||||
|
||||
-- Window Moving/Rearranging
|
||||
Ctrl-w H - Move current window to far left
|
||||
Ctrl-w J - Move current window to bottom
|
||||
Ctrl-w K - Move current window to top
|
||||
Ctrl-w L - Move current window to far right
|
||||
Ctrl-w r - Rotate windows downward/rightward
|
||||
Ctrl-w R - Rotate windows upward/leftward
|
||||
Ctrl-w x - Exchange current window with next one
|
||||
|
||||
-- Window Resizing
|
||||
Ctrl-w = - Make all windows equal size
|
||||
Ctrl-w _ - Maximize height of current window
|
||||
Ctrl-w | - Maximize width of current window
|
||||
Ctrl-w > - Increase width by 1 column
|
||||
Ctrl-w < - Decrease width by 1 column
|
||||
Ctrl-w + - Increase height by 1 row
|
||||
Ctrl-w - - Decrease height by 1 row
|
||||
|
||||
-- Window Special Commands
|
||||
Ctrl-w T - Move current window to new tab
|
||||
Ctrl-w } - Preview definition in new window
|
||||
Ctrl-w z - Close preview window
|
||||
Ctrl-w ] - Split window and jump to definition
|
||||
Ctrl-w f - Split window and edit file under cursor
|
||||
Ctrl-w i - Split window and show declaration
|
||||
Ctrl-w ^ - Split window and edit alternate file
|
||||
|
||||
-- Tab
|
||||
gt :tabnext - Go to next tab
|
||||
gT :tabprevious - Go to previous tab
|
||||
{n}gt :tabnext {n} - Go to tab number {n}
|
||||
<Leader>tn :tabnew - Create a new tab - Suggested
|
||||
<Leader>tc :tabclose - Close current tab - Suggested
|
||||
<Leader>to :tabonly - Close all other tabs - Suggested
|
||||
<Leader>t{n} {n}gt - Go to tab {n} - Suggested
|
||||
<Leader>tm. :tabmove +1 - Move tab right - Suggested
|
||||
<Leader>tm, :tabmove -1 - Move tab left - Suggested
|
||||
|
||||
-- Buffer
|
||||
<Leader>bl :ls - List all buffers - Suggested
|
||||
<Leader>bd :bdelete - Delete current buffer - Suggested
|
||||
<Leader>bn :bnext - Go to next buffer - Suggested
|
||||
<Leader>bp :bprevious - Go to previous buffer - Suggested
|
||||
<Leader>b{n} :buffer {n} - Go to buffer {n} - Suggested
|
||||
<Leader>bb :b<Space> - Start buffer selection - Suggested
|
||||
<Leader>bo :bufdo bd|1bd - Delete all other buffers - Suggested
|
||||
|
||||
-- Telescope
|
||||
<Leader>sf telescope.find_files - Search Files
|
||||
<Leader>sg telescope.live_grep - Search by Grep
|
||||
<Leader>sb telescope.buffers - Search Buffers
|
||||
<Leader>sh telescope.help_tags - Search Help
|
||||
<Leader>sp telescope.projects - Search Projects
|
||||
<Leader>sm telescope.marks - Search Marks
|
||||
<Leader>sc telescope.commands - Search Commands
|
||||
<Leader>sk telescope.keymaps - Search Keymaps
|
||||
<Leader>ss telescope.git_status - Search Git Status
|
||||
<Leader>sw telescope.grep_string - Search current Word
|
||||
<Leader>sd telescope.diagnostics - Search Diagnostics
|
||||
<Leader>sr telescope.lsp_references - Search References
|
||||
|
||||
-- Neo-tree
|
||||
<Leader>e :Neotree toggle - Explorer Toggle
|
||||
<Leader>E :Neotree focus - Explorer Focus
|
||||
<Leader>ef :Neotree float - Explorer Float
|
||||
<Leader>eb :Neotree buffers - Explorer Buffers
|
||||
<Leader>eg :Neotree git_status - Explorer Git
|
||||
|
||||
-- Harpoon
|
||||
<Leader>h harpoon_ui.toggle_menu - Harpoon Menu
|
||||
<Leader>m harpoon_mark.add_file - Mark File
|
||||
<Leader>1 harpoon_ui.nav_file(1) - Harpoon File 1
|
||||
<Leader>2 harpoon_ui.nav_file(2) - Harpoon File 2
|
||||
<Leader>3 harpoon_ui.nav_file(3) - Harpoon File 3
|
||||
<Leader>4 harpoon_ui.nav_file(4) - Harpoon File 4
|
||||
<Leader>hn harpoon_ui.nav_next - Harpoon Next
|
||||
<Leader>hp harpoon_ui.nav_prev - Harpoon Previous
|
||||
|
||||
-- Terminal
|
||||
<Leader>tet :terminal cd %:h - Terminal in This dir
|
||||
<Leader>ter :terminal - Terminal Regular
|
||||
<Leader>tec :!cd %:h && - Terminal Command
|
||||
<Esc> <C-\><C-n> - Terminal Normal Mode
|
||||
<C-w> <C-\><C-n><C-w> - Terminal Window Command
|
||||
|
||||
-- LSP
|
||||
gd vim.lsp.buf.definition - Goto Definition
|
||||
gr vim.lsp.buf.references - Goto References
|
||||
K vim.lsp.buf.hover - Hover Documentation
|
||||
<Leader>rn vim.lsp.buf.rename - Rename
|
||||
<Leader>ca vim.lsp.buf.code_action - Code Action
|
||||
<Leader>f vim.lsp.buf.format - Format
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"global": { "show_in_menu_bar": false },
|
||||
"profiles": [
|
||||
{
|
||||
"devices": [
|
||||
{
|
||||
"identifiers": { "is_keyboard": true },
|
||||
"simple_modifications": [
|
||||
{
|
||||
"from": { "key_code": "non_us_backslash" },
|
||||
"to": [{ "key_code": "grave_accent_and_tilde" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"name": "Default profile",
|
||||
"selected": true
|
||||
}
|
||||
]
|
||||
}
|
||||
44
config/macos/karabiner/karabiner.json
Normal file
44
config/macos/karabiner/karabiner.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"global": { "show_in_menu_bar": false },
|
||||
"profiles": [
|
||||
{
|
||||
"devices": [
|
||||
{
|
||||
"identifiers": { "is_keyboard": true },
|
||||
"simple_modifications": [
|
||||
{
|
||||
"from": { "key_code": "non_us_backslash" },
|
||||
"to": [{ "key_code": "grave_accent_and_tilde" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifiers": {
|
||||
"is_keyboard": true,
|
||||
"product_id": 49164,
|
||||
"vendor_id": 7276
|
||||
},
|
||||
"simple_modifications": [
|
||||
{
|
||||
"from": { "key_code": "left_command" },
|
||||
"to": [{ "key_code": "left_option" }]
|
||||
},
|
||||
{
|
||||
"from": { "key_code": "left_option" },
|
||||
"to": [{ "key_code": "left_command" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"name": "Default profile",
|
||||
"selected": true,
|
||||
"simple_modifications": [
|
||||
{
|
||||
"from": { "key_code": "caps_lock" },
|
||||
"to": [{ "key_code": "left_control" }]
|
||||
}
|
||||
],
|
||||
"virtual_hid_keyboard": { "keyboard_type_v2": "ansi" }
|
||||
}
|
||||
]
|
||||
}
|
||||
44
config/macos/linearmouse/linearmouse.json
Normal file
44
config/macos/linearmouse/linearmouse.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"$schema": "https:\/\/schema.linearmouse.app\/0.10.0",
|
||||
"schemes": [
|
||||
{
|
||||
"if" : {
|
||||
"device" : {
|
||||
"vendorID" : "0x46d",
|
||||
"productID" : "0xc52b",
|
||||
"productName" : "USB Receiver",
|
||||
"category" : "mouse"
|
||||
}
|
||||
},
|
||||
"scrolling": {
|
||||
"reverse": {
|
||||
"vertical": true
|
||||
},
|
||||
"speed": {
|
||||
"vertical": 0
|
||||
},
|
||||
"acceleration": {
|
||||
"vertical": 1
|
||||
},
|
||||
"distance": {
|
||||
"vertical": "100px"
|
||||
},
|
||||
"modifiers": {
|
||||
"vertical": {
|
||||
"command": {
|
||||
"type": "preventDefault"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"universalBackForward": true
|
||||
},
|
||||
"pointer": {
|
||||
"acceleration": 0.3,
|
||||
"speed": 0.2,
|
||||
"disableAcceleration": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
40
config/shared/alacritty
Normal file
40
config/shared/alacritty
Normal file
@ -0,0 +1,40 @@
|
||||
live_config_reload = true
|
||||
|
||||
[env]
|
||||
TERM = "xterm-256color"
|
||||
|
||||
[font]
|
||||
normal = { family = "SF Mono", style = "Regular" }
|
||||
size = 12
|
||||
offset = { x = 0, y = 0 }
|
||||
|
||||
[window]
|
||||
decorations_theme_variant = "Dark"
|
||||
padding = { x = 4, y = 0 }
|
||||
dynamic_padding = false
|
||||
resize_increments = true
|
||||
|
||||
[keyboard]
|
||||
bindings = [
|
||||
# Create new window
|
||||
{ action = "SpawnNewInstance", key = "N", mods = "Command" },
|
||||
# Jump back one word
|
||||
{ key = "Left", mods = "Alt", chars = "\u001bb" },
|
||||
# Jump forward one word
|
||||
{ key = "Right", mods = "Alt", chars = "\u001bf" },
|
||||
# Move to start of line
|
||||
{ key = "Left", mods = "Command", chars = "\u0001" },
|
||||
# Move to end of line
|
||||
{ key = "Right", mods = "Command", chars = "\u0005" },
|
||||
|
||||
# Delete backwards
|
||||
{ key = "Back", mods = "Alt", chars = "\u001B\u007F" }, # word
|
||||
{ key = "Back", mods = "Command", chars = "\u0015" }, # line
|
||||
|
||||
# Delete forwards
|
||||
{ key = "Delete", mods = "Alt", chars = "\u001Bd" }, # word
|
||||
{ key = "Delete", mods = "Command", chars = "\u000B" } # line
|
||||
]
|
||||
|
||||
[scrolling]
|
||||
multiplier = 1
|
||||
97
config/shared/bin/colortest
Executable file
97
config/shared/bin/colortest
Executable file
@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Test black and white
|
||||
echo "=== Black and White ==="
|
||||
printf "Normal text\n"
|
||||
printf "\e[1mBold text\e[0m\n"
|
||||
printf "\e[7mReverse text\e[0m\n\n"
|
||||
|
||||
# Test 4-bit ANSI (16 colors)
|
||||
echo "=== 4-bit ANSI Colors (16 colors) ==="
|
||||
echo "Foreground colors:"
|
||||
for i in {30..37}; do
|
||||
printf "\e[${i}m\\e[${i}m\e[0m "
|
||||
done
|
||||
echo -e "\n"
|
||||
|
||||
echo "Background colors:"
|
||||
for i in {40..47}; do
|
||||
printf "\e[${i}m\\e[${i}m\e[0m "
|
||||
done
|
||||
echo -e "\n"
|
||||
|
||||
echo "Bright foreground colors:"
|
||||
for i in {90..97}; do
|
||||
printf "\e[${i}m\\e[${i}m\e[0m "
|
||||
done
|
||||
echo -e "\n"
|
||||
|
||||
echo "Bright background colors:"
|
||||
for i in {100..107}; do
|
||||
printf "\e[${i}m\\e[${i}m\e[0m "
|
||||
done
|
||||
echo -e "\n\n"
|
||||
|
||||
# Test 8-bit ANSI (256 colors)
|
||||
echo "=== 8-bit ANSI Colors (256 colors) ==="
|
||||
echo "16 System Colors:"
|
||||
for i in {0..15}; do
|
||||
printf "\e[48;5;${i}m \e[0m"
|
||||
if [ $((($i + 1) % 8)) == 0 ]; then
|
||||
echo
|
||||
fi
|
||||
done
|
||||
echo
|
||||
|
||||
echo "216 RGB Colors:"
|
||||
for i in {16..231}; do
|
||||
printf "\e[48;5;${i}m \e[0m"
|
||||
if [ $((($i - 15) % 36)) == 0 ]; then
|
||||
echo
|
||||
fi
|
||||
done
|
||||
echo
|
||||
|
||||
echo "24 Grayscale Colors:"
|
||||
for i in {232..255}; do
|
||||
printf "\e[48;5;${i}m \e[0m"
|
||||
if [ $((($i - 231) % 12)) == 0 ]; then
|
||||
echo
|
||||
fi
|
||||
done
|
||||
echo -e "\n"
|
||||
|
||||
# Test 24-bit true color
|
||||
echo "=== 24-bit True Color (16.7 million colors) ==="
|
||||
echo "RGB Color Gradient:"
|
||||
awk 'BEGIN{
|
||||
s="/\\";
|
||||
for (colnum = 0; colnum<77; colnum++) {
|
||||
r = 255-(colnum*255/76);
|
||||
g = (colnum*510/76);
|
||||
b = (colnum*255/76);
|
||||
if (g>255) g = 510-g;
|
||||
printf "\033[48;2;%d;%d;%dm", r,g,b;
|
||||
printf "\033[38;2;%d;%d;%dm", 255-r,255-g,255-b;
|
||||
printf "%s\033[0m", substr(s,colnum%2+1,1);
|
||||
}
|
||||
printf "\n";
|
||||
}'
|
||||
|
||||
echo "RGB Color Bars:"
|
||||
for r in 0 127 255; do
|
||||
for g in 0 127 255; do
|
||||
for b in 0 127 255; do
|
||||
printf "\e[48;2;${r};${g};${b}m \e[0m"
|
||||
done
|
||||
printf " "
|
||||
done
|
||||
echo
|
||||
done
|
||||
echo
|
||||
|
||||
# Print terminal information
|
||||
echo "=== Terminal Information ==="
|
||||
echo "TERM: $TERM"
|
||||
echo "COLORTERM: $COLORTERM"
|
||||
echo "Reported colors (tput colors): $(tput colors)"
|
||||
18
config/shared/bin/detect_keys
Executable file
18
config/shared/bin/detect_keys
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/zsh
|
||||
|
||||
echo "Press any key combination. Press Ctrl+C to exit."
|
||||
while true; do
|
||||
result=""
|
||||
escape_sequence=""
|
||||
read -sk 1 key
|
||||
if [[ $key == $'\x1b' ]]; then
|
||||
escape_sequence+="^["
|
||||
while read -sk 1 -t 0.01 next_key; do
|
||||
escape_sequence+="$next_key"
|
||||
done
|
||||
result="$escape_sequence"
|
||||
else
|
||||
result="$key"
|
||||
fi
|
||||
echo -E "Key: $result"
|
||||
done
|
||||
41
config/shared/bin/dev
Executable file
41
config/shared/bin/dev
Executable file
@ -0,0 +1,41 @@
|
||||
# --rm: automatically remove the container when it exits
|
||||
|
||||
# Check if a container name was provided
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: $0 <container_name>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IMAGE="web-stack"
|
||||
NAME="${IMAGE}-$1"
|
||||
|
||||
# Function to exec into the container
|
||||
exec_into_container() {
|
||||
docker exec --detach-keys "ctrl-q,ctrl-p" -it $NAME /bin/zsh
|
||||
}
|
||||
|
||||
# Check if the container exists
|
||||
if [ "$(docker ps -a -q -f name=$NAME)" ]; then
|
||||
# Container exists, start it if it's not running
|
||||
if [ ! "$(docker ps -q -f name=$NAME)" ]; then
|
||||
echo "Container $NAME exists but is not running. Starting it..."
|
||||
docker start $NAME
|
||||
else
|
||||
echo "Container $NAME is already running."
|
||||
fi
|
||||
else
|
||||
echo "Container $NAME does not exist. Creating and running it in detached mode..."
|
||||
docker run -d \
|
||||
--detach-keys "ctrl-q,ctrl-p" \
|
||||
--network host \
|
||||
-v $HOME/.ssh:/home/dev/.ssh \
|
||||
-v $PWD:/workspace \
|
||||
--name $NAME \
|
||||
--init \
|
||||
$IMAGE \
|
||||
tail -f /dev/null
|
||||
fi
|
||||
|
||||
# Exec into the container
|
||||
echo "Executing into container $NAME..."
|
||||
exec_into_container
|
||||
29
config/shared/bin/ssh-forward
Executable file
29
config/shared/bin/ssh-forward
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Function to display usage information
|
||||
usage() {
|
||||
echo "Usage: $0 <user@host> <port1> [port2] [port3] ..."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Ensure at least two arguments are provided: host and one port
|
||||
if [ "$#" -lt 2 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
# Extract the host from the first argument
|
||||
HOST="$1"
|
||||
shift # Shift the arguments so that $@ contains the remaining ports
|
||||
|
||||
# Initialize the PORTS variable
|
||||
PORTS=""
|
||||
|
||||
# Iterate over the remaining arguments, which are the ports
|
||||
for port in "$@"; do
|
||||
PORTS="$PORTS -L ${port}:localhost:${port}"
|
||||
done
|
||||
|
||||
# Construct and run the SSH command
|
||||
SSH_CMD="ssh -N -T -o ExitOnForwardFailure=yes $HOST $PORTS"
|
||||
echo "Running: $SSH_CMD"
|
||||
$SSH_CMD
|
||||
48
config/shared/ghostty/config
Normal file
48
config/shared/ghostty/config
Normal file
@ -0,0 +1,48 @@
|
||||
# Terminal
|
||||
term = "xterm-256color"
|
||||
|
||||
# Fonts
|
||||
font-family = "SF Mono"
|
||||
font-family = "SF Mono"
|
||||
font-size = 12
|
||||
font-thicken = true
|
||||
|
||||
# Cell width (affects letter spacing)
|
||||
adjust-cell-width = -1
|
||||
adjust-cell-height = -1
|
||||
adjust-font-baseline = -1
|
||||
|
||||
# Cursor
|
||||
cursor-style-blink = false
|
||||
cursor-style = block
|
||||
shell-integration-features = no-cursor
|
||||
|
||||
# Icon
|
||||
# macos-icon = custom-style
|
||||
# macos-icon-frame = plastic
|
||||
# macos-icon-ghost-color = cba6f7
|
||||
# macos-icon-screen-color = 181825
|
||||
|
||||
# Window
|
||||
#background = #181818
|
||||
background = #000000
|
||||
window-theme = dark
|
||||
window-width = 100
|
||||
window-height = 26
|
||||
window-padding-x = 4
|
||||
window-padding-y = 2
|
||||
window-colorspace = display-p3
|
||||
window-decoration = true
|
||||
macos-titlebar-style = native
|
||||
|
||||
|
||||
# Resize by row
|
||||
#window-step-resize = true
|
||||
#window-padding-balance = true
|
||||
|
||||
# Background
|
||||
background-opacity = 1
|
||||
background-blur-radius = 0
|
||||
|
||||
|
||||
|
||||
7
config/shared/git
Normal file
7
config/shared/git
Normal file
@ -0,0 +1,7 @@
|
||||
[init]
|
||||
defaultBranch = main
|
||||
[user]
|
||||
name = Tomas Mirchev
|
||||
email = contact@tomastm.com
|
||||
[pull]
|
||||
rebase = true
|
||||
63
config/shared/htop/htoprc
Normal file
63
config/shared/htop/htoprc
Normal file
@ -0,0 +1,63 @@
|
||||
# Beware! This file is rewritten by htop when settings are changed in the interface.
|
||||
# The parser is also very primitive, and not human-friendly.
|
||||
htop_version=3.2.2
|
||||
config_reader_min_version=3
|
||||
fields=0 48 17 18 38 39 40 2 46 47 49 1
|
||||
hide_kernel_threads=1
|
||||
hide_userland_threads=1
|
||||
hide_running_in_container=0
|
||||
shadow_other_users=0
|
||||
show_thread_names=0
|
||||
show_program_path=1
|
||||
highlight_base_name=0
|
||||
highlight_deleted_exe=1
|
||||
shadow_distribution_path_prefix=0
|
||||
highlight_megabytes=1
|
||||
highlight_threads=1
|
||||
highlight_changes=0
|
||||
highlight_changes_delay_secs=5
|
||||
find_comm_in_cmdline=1
|
||||
strip_exe_from_cmdline=1
|
||||
show_merged_command=0
|
||||
header_margin=1
|
||||
screen_tabs=1
|
||||
detailed_cpu_time=0
|
||||
cpu_count_from_one=0
|
||||
show_cpu_usage=1
|
||||
show_cpu_frequency=0
|
||||
show_cpu_temperature=0
|
||||
degree_fahrenheit=0
|
||||
update_process_names=0
|
||||
account_guest_in_cpu_meter=0
|
||||
color_scheme=0
|
||||
enable_mouse=1
|
||||
delay=15
|
||||
hide_function_bar=0
|
||||
header_layout=two_50_50
|
||||
column_meters_0=AllCPUs Memory Swap
|
||||
column_meter_modes_0=1 1 1
|
||||
column_meters_1=Tasks LoadAverage Uptime
|
||||
column_meter_modes_1=2 2 2
|
||||
tree_view=0
|
||||
sort_key=47
|
||||
tree_sort_key=0
|
||||
sort_direction=-1
|
||||
tree_sort_direction=1
|
||||
tree_view_always_by_pid=0
|
||||
all_branches_collapsed=0
|
||||
screen:Main=PID USER PRIORITY NICE M_VIRT M_RESIDENT M_SHARE STATE PERCENT_CPU PERCENT_MEM TIME Command
|
||||
.sort_key=PERCENT_MEM
|
||||
.tree_sort_key=PID
|
||||
.tree_view=0
|
||||
.tree_view_always_by_pid=0
|
||||
.sort_direction=-1
|
||||
.tree_sort_direction=1
|
||||
.all_branches_collapsed=0
|
||||
screen:I/O=PID USER IO_PRIORITY IO_RATE IO_READ_RATE IO_WRITE_RATE PERCENT_SWAP_DELAY PERCENT_IO_DELAY Command
|
||||
.sort_key=IO_RATE
|
||||
.tree_sort_key=PID
|
||||
.tree_view=0
|
||||
.tree_view_always_by_pid=0
|
||||
.sort_direction=-1
|
||||
.tree_sort_direction=1
|
||||
.all_branches_collapsed=0
|
||||
121
config/shared/nvim
Normal file
121
config/shared/nvim
Normal file
@ -0,0 +1,121 @@
|
||||
-- [[ Basic Keymaps ]]
|
||||
-- See `:help vim.keymap.set()`
|
||||
|
||||
-- Map 'jk' to escape in insert mode
|
||||
vim.keymap.set('i', 'jk', '<Esc>', { desc = 'Exit insert mode with jk' })
|
||||
|
||||
-- Clear highlights on search when pressing <Esc> in normal mode
|
||||
-- See `:help hlsearch`
|
||||
vim.keymap.set('n', '<Esc>', '<cmd>nohlsearch<CR>')
|
||||
|
||||
-- Diagnostic keymaps
|
||||
vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' })
|
||||
|
||||
-- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier
|
||||
-- for people to discover. Otherwise, you normally need to press <C-\><C-n>, which
|
||||
-- is not what someone will guess without a bit more experience.
|
||||
vim.keymap.set('t', '<Esc><Esc>', '<C-\\><C-n>', { desc = 'Exit terminal mode' })
|
||||
|
||||
-- Keybinds to make split navigation easier.
|
||||
-- Use CTRL+<hjkl> to switch between windows
|
||||
--
|
||||
-- See `:help wincmd` for a list of all window commands
|
||||
vim.keymap.set('n', '<C-h>', '<C-w><C-h>', { desc = 'Move focus to the left window' })
|
||||
vim.keymap.set('n', '<C-l>', '<C-w><C-l>', { desc = 'Move focus to the right window' })
|
||||
vim.keymap.set('n', '<C-j>', '<C-w><C-j>', { desc = 'Move focus to the lower window' })
|
||||
vim.keymap.set('n', '<C-k>', '<C-w><C-k>', { desc = 'Move focus to the upper window' })
|
||||
|
||||
-- [[ Basic Autocommands ]]
|
||||
-- See `:help lua-guide-autocommands`
|
||||
|
||||
-- Highlight when yanking (copying) text
|
||||
-- Try it with `yap` in normal mode
|
||||
-- See `:help vim.highlight.on_yank()`
|
||||
vim.api.nvim_create_autocmd('TextYankPost', {
|
||||
desc = 'Highlight when yanking (copying) text',
|
||||
group = vim.api.nvim_create_augroup('kickstart-highlight-yank', { clear = true }),
|
||||
callback = function()
|
||||
vim.highlight.on_yank()
|
||||
end,
|
||||
})
|
||||
|
||||
-- ---------------------------------------------------
|
||||
-- ---------------------------------------------------
|
||||
|
||||
-- Set <space> as the leader key
|
||||
-- See `:help mapleader`
|
||||
-- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used)
|
||||
vim.g.mapleader = " "
|
||||
vim.g.maplocalleader = " "
|
||||
|
||||
-- [[ Setting options ]]
|
||||
-- See `:help vim.opt`
|
||||
-- NOTE: You can change these options as you wish!
|
||||
-- For more options, you can see `:help option-list`
|
||||
|
||||
-- Disable Neovim background
|
||||
vim.api.nvim_set_hl(0, "Normal", { bg = "none" })
|
||||
vim.api.nvim_set_hl(0, "NormalFloat", { bg = "none" })
|
||||
|
||||
-- Scroll lines/columns
|
||||
vim.opt.mousescroll = "hor:1,ver:1"
|
||||
|
||||
-- Set indentation preferences
|
||||
vim.opt.expandtab = true -- Convert tabs to spaces
|
||||
vim.opt.shiftwidth = 2 -- Number of spaces for auto-indent
|
||||
vim.opt.tabstop = 2 -- Number of spaces a tab counts for
|
||||
vim.opt.softtabstop = 2 -- Number of spaces a tab counts for when editing
|
||||
vim.opt.autoindent = true -- Copy indent from current line when starting new line
|
||||
vim.opt.smartindent = true -- Do smart autoindenting when starting a new line
|
||||
|
||||
-- Disable line wrapping
|
||||
vim.opt.wrap = false
|
||||
|
||||
-- Make line numbers default
|
||||
vim.opt.number = true
|
||||
vim.opt.relativenumber = true
|
||||
|
||||
-- Enable mouse mode, can be useful for resizing splits for example!
|
||||
vim.opt.mouse = "a"
|
||||
|
||||
-- Don't show the mode, since it's already in the status line
|
||||
vim.opt.showmode = true
|
||||
vim.opt.statusline = "%F%m%r%h%w%=%l,%c %P"
|
||||
|
||||
-- Sync clipboard between OS and Neovim.
|
||||
-- Schedule the setting after `UiEnter` because it can increase startup-time.
|
||||
-- Remove this option if you want your OS clipboard to remain independent.
|
||||
-- See `:help 'clipboard'`
|
||||
vim.schedule(function()
|
||||
vim.opt.clipboard = "unnamedplus"
|
||||
end)
|
||||
|
||||
-- Enable break indent
|
||||
vim.opt.breakindent = true
|
||||
|
||||
-- Save undo history
|
||||
vim.opt.undofile = true
|
||||
|
||||
-- Case-insensitive searching UNLESS \C or one or more capital letters in the search term
|
||||
vim.opt.ignorecase = true
|
||||
vim.opt.smartcase = true
|
||||
|
||||
-- Decrease update time
|
||||
vim.opt.updatetime = 250
|
||||
|
||||
-- Decrease mapped sequence wait time
|
||||
-- Displays which-key popup sooner
|
||||
vim.opt.timeoutlen = 300
|
||||
|
||||
-- Configure how new splits should be opened
|
||||
vim.opt.splitright = true
|
||||
vim.opt.splitbelow = true
|
||||
|
||||
-- Preview substitutions live, as you type!
|
||||
vim.opt.inccommand = "split"
|
||||
|
||||
-- Show which line your cursor is on
|
||||
vim.opt.cursorline = true
|
||||
|
||||
-- Minimal number of screen lines to keep above and below the cursor.
|
||||
vim.opt.scrolloff = 10
|
||||
62
config/shared/tmux
Normal file
62
config/shared/tmux
Normal file
@ -0,0 +1,62 @@
|
||||
# Change the prefix from 'C-b' to 'C-Space'
|
||||
unbind C-b
|
||||
set-option -g prefix C-Space
|
||||
bind-key C-Space send-prefix
|
||||
|
||||
#set -g default-terminal "tmux-256color"
|
||||
#set -as terminal-features ",*:RGB"
|
||||
|
||||
set-option -sg escape-time 10
|
||||
set-option -g focus-events on
|
||||
|
||||
# Set the base index for windows and panes to 1 instead of 0
|
||||
set -g base-index 1
|
||||
setw -g pane-base-index 1
|
||||
|
||||
# Increase scrollback buffer size
|
||||
set -g history-limit 10000
|
||||
|
||||
# Customize the status bar
|
||||
set -g status-style bg=default,fg=white
|
||||
set -g status-left '#[fg=cyan,bold][#S] '
|
||||
set -g status-left-length 50
|
||||
set -g status-right ''
|
||||
|
||||
# Window status format
|
||||
setw -g window-status-format '#[fg=white,dim]#I#[fg=grey]:#[fg=white]#W#[fg=grey]#F'
|
||||
setw -g window-status-current-format '#[fg=cyan,bold]#I#[fg=blue]:#[fg=cyan]#W#[fg=grey]#F'
|
||||
|
||||
# Pane border
|
||||
set -g pane-border-style fg=colour240
|
||||
set -g pane-active-border-style fg=cyan
|
||||
|
||||
# Message text
|
||||
set -g message-style bg=default,fg=cyan
|
||||
|
||||
# Enable mouse support
|
||||
setw -g mouse on
|
||||
|
||||
# Fix scroll. Use N3 instead of N1 to make it quicker
|
||||
bind-key -T copy-mode-vi WheelUpPane send -N1 -X scroll-up
|
||||
bind-key -T copy-mode-vi WheelDownPane send -N1 -X scroll-down
|
||||
|
||||
# Update terminal titles
|
||||
set-option -g set-titles on
|
||||
|
||||
# Use vim keybindings in copy mode
|
||||
setw -g mode-keys vi
|
||||
|
||||
# Setup 'v' to begin selection as in Vim
|
||||
bind -T copy-mode-vi v send-keys -X begin-selection
|
||||
|
||||
# Pane navigation using vim-like keys
|
||||
bind -r k select-pane -U
|
||||
bind -r j select-pane -D
|
||||
bind -r h select-pane -L
|
||||
bind -r l select-pane -R
|
||||
|
||||
# Automatically renumber windows when one is closed
|
||||
set -g renumber-windows on
|
||||
|
||||
# Reload tmux config
|
||||
bind r source-file ~/.tmux.conf \; display "Reloaded!"
|
||||
26
config/shared/vim
Normal file
26
config/shared/vim
Normal file
@ -0,0 +1,26 @@
|
||||
set nocompatible
|
||||
set nobackup
|
||||
set encoding=utf-8
|
||||
set clipboard=unnamed
|
||||
filetype plugin indent on
|
||||
|
||||
let mapleader=" "
|
||||
inoremap jk <esc>
|
||||
set number
|
||||
set relativenumber
|
||||
set ruler
|
||||
set cursorline
|
||||
set scrolloff=10
|
||||
set nowrap
|
||||
set showcmd
|
||||
set wildmenu
|
||||
set title
|
||||
set mouse=a
|
||||
|
||||
set shiftwidth=2
|
||||
set tabstop=2
|
||||
set expandtab
|
||||
set autoindent
|
||||
set smartindent
|
||||
|
||||
syntax on
|
||||
70
config/shared/wezterm
Normal file
70
config/shared/wezterm
Normal file
@ -0,0 +1,70 @@
|
||||
local wezterm = require('wezterm')
|
||||
|
||||
local config = wezterm.config_builder()
|
||||
|
||||
config.term="xterm-256color"
|
||||
config.color_scheme = "Catppuccin Frappe"
|
||||
config.font = wezterm.font('FiraCode Nerd Font')
|
||||
-- config.window_decorations = "INTEGRATED_BUTTONS | RESIZE"
|
||||
config.font_size = 14.0
|
||||
config.use_resize_increments = true
|
||||
config.window_padding = {
|
||||
left = 4,
|
||||
right = 4,
|
||||
top = 4,
|
||||
bottom = 0,
|
||||
}
|
||||
config.mouse_bindings = {
|
||||
{
|
||||
event = { Drag = { streak = 1, button = 'Left' } },
|
||||
mods = 'CMD',
|
||||
action = wezterm.action.StartWindowDrag,
|
||||
},
|
||||
{
|
||||
event = { Drag = { streak = 1, button = 'Left' } },
|
||||
mods = 'CTRL|SHIFT',
|
||||
action = wezterm.action.StartWindowDrag,
|
||||
},
|
||||
}
|
||||
local act = wezterm.action
|
||||
config.keys = {
|
||||
{
|
||||
key = 'w',
|
||||
mods = 'CMD',
|
||||
action = wezterm.action.CloseCurrentTab { confirm = false }
|
||||
},
|
||||
{
|
||||
key = 'LeftArrow',
|
||||
mods = 'CMD',
|
||||
action = wezterm.action { SendString = '\x1b0H' }
|
||||
},
|
||||
{
|
||||
key = 'RightArrow',
|
||||
mods = 'CMD',
|
||||
action = wezterm.action { SendString = '\x1b0F' }
|
||||
},
|
||||
{
|
||||
key = 'LeftArrow',
|
||||
mods = 'OPT',
|
||||
action = act.SendKey { key = 'b', mods = 'ALT' }
|
||||
},
|
||||
{
|
||||
key = 'RightArrow',
|
||||
mods = 'OPT',
|
||||
action = act.SendKey { key = 'f', mods = 'ALT' }
|
||||
}
|
||||
---- Make Option-Left equivalent to Alt-b which many line editors interpret as backward-word
|
||||
--{
|
||||
-- key="LeftArrow",
|
||||
-- mods="OPT",
|
||||
-- action=wezterm.action{SendString="\x1bb"}
|
||||
--},
|
||||
---- Make Option-Right equivalent to Alt-f; forward-word
|
||||
--{
|
||||
-- key="RightArrow",
|
||||
-- mods="OPT",
|
||||
-- action=wezterm.action{SendString="\x1bf"}
|
||||
--}
|
||||
}
|
||||
|
||||
return config
|
||||
71
config/shared/zsh
Normal file
71
config/shared/zsh
Normal file
@ -0,0 +1,71 @@
|
||||
# Add /bin to path
|
||||
export PATH="$PATH:$HOME/bin"
|
||||
|
||||
# Set locales
|
||||
export LANGUAGE="en_US:en"
|
||||
export LANG=en_US.UTF-8
|
||||
export LC_ALL=en_US.UTF-8
|
||||
|
||||
autoload -Uz compinit && compinit # Autocomplete
|
||||
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' # Case Insensitive
|
||||
|
||||
setopt autocd # cd without it
|
||||
setopt share_history
|
||||
|
||||
# Git prompt function
|
||||
git_prompt_info() {
|
||||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
local branch=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD)
|
||||
echo " %F{green}($branch)%f"
|
||||
fi
|
||||
}
|
||||
|
||||
# Set up the prompt
|
||||
setopt PROMPT_SUBST # Dyna
|
||||
PROMPT='%n@%m%f %F{blue}%~%f$(git_prompt_info) $ '
|
||||
|
||||
# Disable the log builtin, so we don't conflict with /usr/bin/log
|
||||
disable log
|
||||
|
||||
# Save command history
|
||||
HISTFILE=${ZDOTDIR:-$HOME}/.zsh_history
|
||||
HISTSIZE=2000
|
||||
SAVEHIST=1000
|
||||
setopt HIST_IGNORE_ALL_DUPS
|
||||
|
||||
# Load functions
|
||||
autoload -U up-line-or-beginning-search
|
||||
autoload -U down-line-or-beginning-search
|
||||
zle -N up-line-or-beginning-search
|
||||
zle -N down-line-or-beginning-search
|
||||
|
||||
# Bind both common escape sequences
|
||||
bindkey '^[[A' up-line-or-beginning-search # normal mode
|
||||
bindkey '^[OA' up-line-or-beginning-search # application mode
|
||||
bindkey '^[[B' down-line-or-beginning-search # normal mode
|
||||
bindkey '^[OB' down-line-or-beginning-search # application mode
|
||||
|
||||
# Aliases for ls
|
||||
alias ls='ls --color=auto'
|
||||
alias ll='ls -lF'
|
||||
alias lla='ll -a'
|
||||
alias ld='ls -ld */' # List only directories
|
||||
|
||||
# Aliases for git
|
||||
alias g='git'
|
||||
alias ga='git add'
|
||||
alias gaa='git add --all'
|
||||
alias gb='git branch'
|
||||
alias gcm='git commit -m'
|
||||
alias gam='git commit -am'
|
||||
alias gco='git checkout'
|
||||
alias gd='git diff'
|
||||
alias gf='git fetch'
|
||||
alias gl='git pull'
|
||||
alias gp='git push'
|
||||
alias gst='git status'
|
||||
alias glg='git log --graph --oneline --decorate --all'
|
||||
alias gm='git merge'
|
||||
alias grb='git rebase'
|
||||
alias grs='git reset'
|
||||
alias grv='git remote -v'
|
||||
196
manage.py
Normal file
196
manage.py
Normal file
@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import subprocess
|
||||
import json
|
||||
from pathlib import Path
|
||||
import shlex
|
||||
import shutil
|
||||
|
||||
DOTFILES_DIR = Path(__file__).parent
|
||||
SETUPS_DIR = DOTFILES_DIR / "setups"
|
||||
CONFIG_DIR = DOTFILES_DIR / "config"
|
||||
CONFIG_PATH = DOTFILES_DIR / "config.json"
|
||||
|
||||
def load_config():
|
||||
if not CONFIG_PATH.exists():
|
||||
raise FileNotFoundError(f"Configuration file not found: {CONFIG_PATH}")
|
||||
|
||||
with open(CONFIG_PATH, "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not isinstance(data, dict):
|
||||
raise ValueError("JSON must be an object")
|
||||
|
||||
if "environments" not in data:
|
||||
raise ValueError("Missing required field: 'environments'")
|
||||
|
||||
if not isinstance(data["environments"], dict):
|
||||
raise ValueError("'environments' must be an object")
|
||||
|
||||
if "template" in data and not isinstance(data["template"], dict):
|
||||
raise ValueError("'template' must be an object if present")
|
||||
|
||||
return data
|
||||
|
||||
def get_environment_packages(config, env, search_package=None):
|
||||
env_entries = config["environments"].get(env, [])
|
||||
if not env_entries:
|
||||
raise TypeError(f"Environment {env} was not found or it is empty")
|
||||
|
||||
template_config = config.get("template", {})
|
||||
packages = []
|
||||
for entry in env_entries:
|
||||
if isinstance(entry, str):
|
||||
entry = { "package": entry }
|
||||
|
||||
package_name = entry.pop("package", None)
|
||||
if package_name is None:
|
||||
raise TypeError(f"The following entry is missing `package` field: {entry}")
|
||||
|
||||
package = { "name": package_name }
|
||||
if package_name in template_config and not entry.get("ignore-template", False):
|
||||
template_entry = template_config[package_name]
|
||||
package = { **package, **template_entry, **entry }
|
||||
else:
|
||||
package.update(entry)
|
||||
|
||||
package.pop("ignore-template", None)
|
||||
|
||||
if "link" in package:
|
||||
link_from = package["link"].get("from")
|
||||
link_to = package["link"].get("to")
|
||||
if not isinstance(link_from, str) or not isinstance(link_to, str):
|
||||
raise ValueError("`link` should follow the structure: `{ from: str, to: str }`")
|
||||
|
||||
if len(link_from.split("/")) != 2:
|
||||
raise ValueError("`link.from` should be '<env>/<package>'")
|
||||
|
||||
package["link"] = {
|
||||
"from": Path(CONFIG_DIR / link_from).expanduser(),
|
||||
"to": Path(link_to).expanduser()
|
||||
}
|
||||
|
||||
if search_package == None:
|
||||
packages.append(package)
|
||||
else:
|
||||
if package["name"] == search_package:
|
||||
packages.append(package)
|
||||
break
|
||||
|
||||
return packages
|
||||
|
||||
def force_delete(path):
|
||||
if path.is_file() or path.is_symlink():
|
||||
path.unlink()
|
||||
elif path.is_dir():
|
||||
shutil.rmtree(path)
|
||||
|
||||
def link_environment(config, env, **kwargs):
|
||||
options = {
|
||||
"package": kwargs.get("package"),
|
||||
"copy": kwargs.get("copy", False),
|
||||
"force": kwargs.get("force", False)
|
||||
}
|
||||
|
||||
packages = get_environment_packages(config, env, search_package=options["package"])
|
||||
for package in packages:
|
||||
print(f"[{package['name']}]")
|
||||
|
||||
if "link" not in package:
|
||||
print("\t> Skipped: No link entry")
|
||||
continue
|
||||
|
||||
src = package["link"]["from"]
|
||||
dest = package["link"]["to"]
|
||||
|
||||
if dest.exists():
|
||||
if options["force"]:
|
||||
force_delete(dest)
|
||||
print(f"\t> Deleted: {dest}")
|
||||
else:
|
||||
print(f"\t> Skipped: Already exists {dest}")
|
||||
continue
|
||||
|
||||
if options["copy"]:
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy(src, dest)
|
||||
print(f"\t> Copied: {src} -> {dest}")
|
||||
else:
|
||||
dest.symlink_to(src)
|
||||
print(f"\t> Symlinked: {src} -> {dest}")
|
||||
|
||||
if "post-link" in package:
|
||||
command = package["post-link"]
|
||||
subprocess.run(shlex.split(command), check=True)
|
||||
print(f"\t> Post-link executed: `{command}`")
|
||||
|
||||
def install_environment(config, env, **kwargs):
|
||||
options = {
|
||||
"package": kwargs.get("package"),
|
||||
}
|
||||
|
||||
packages = get_environment_packages(config, env, search_package=options["package"])
|
||||
for package in packages:
|
||||
print(f"[{package['name']}]")
|
||||
|
||||
if "install" not in package:
|
||||
print("\t> Skipped: No install entry")
|
||||
continue
|
||||
|
||||
install_command = package.get("install")
|
||||
if install_command:
|
||||
subprocess.run(shlex.split(install_command), check=True)
|
||||
print(f"\t> Installed: `{install_command}`")
|
||||
|
||||
if "post-install" in package:
|
||||
postinstall_command = package["post-install"]
|
||||
subprocess.run(shlex.split(postinstall_command), check=True)
|
||||
print(f"\t> Post-install executed: `{postinstall_command}`")
|
||||
|
||||
def setup_environment(config, env, **kwargs):
|
||||
print(f"[{env}]")
|
||||
options = {
|
||||
"extra_args": kwargs.get("extra"),
|
||||
}
|
||||
|
||||
setup_script = SETUPS_DIR / f"{env}.sh"
|
||||
if setup_script.exists():
|
||||
cmd = ["bash", str(setup_script)]
|
||||
if options["extra_args"]:
|
||||
cmd.extend(shlex.split(options["extra_args"])) # Split extra args safely
|
||||
subprocess.run(cmd, check=True)
|
||||
print(f"\t> Setup script executed: {setup_script} {options['extra_args'] or ''}")
|
||||
else:
|
||||
print(f"\t> No setup script found for {env}")
|
||||
|
||||
def main():
|
||||
config = load_config()
|
||||
|
||||
config_envs = list(config["environments"].keys())
|
||||
setup_envs = [script.stem for script in SETUPS_DIR.glob("*.sh")]
|
||||
|
||||
parser = argparse.ArgumentParser(description="Dotfile & System Setup Manager")
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
subparser = subparsers.add_parser("link", help="Link configs")
|
||||
subparser.add_argument("env", choices=config_envs)
|
||||
subparser.add_argument("-p", "--package")
|
||||
subparser.add_argument("-f", "--force", action="store_true")
|
||||
subparser.add_argument("--copy", action="store_true")
|
||||
|
||||
subparser = subparsers.add_parser("install", help="Install packages")
|
||||
subparser.add_argument("env", choices=config_envs)
|
||||
subparser.add_argument("-p", "--package")
|
||||
|
||||
setup_parser = subparsers.add_parser("setup", help="Run setup script")
|
||||
setup_parser.add_argument("env", choices=setup_envs)
|
||||
setup_parser.add_argument("--extra")
|
||||
|
||||
args = parser.parse_args()
|
||||
command_actions = {"link": link_environment, "install": install_environment, "setup": setup_environment}
|
||||
command_actions[args.command](config, **vars(args))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
20
scripts/linux-change_hostname.sh
Executable file
20
scripts/linux-change_hostname.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run this script as root using sudo."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 <new-hostname>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NEW_HOSTNAME=$1
|
||||
OLD_HOSTNAME=$(hostname)
|
||||
|
||||
hostnamectl set-hostname "$NEW_HOSTNAME"
|
||||
|
||||
sed -i "s/$OLD_HOSTNAME/$NEW_HOSTNAME/g" /etc/hosts
|
||||
|
||||
echo "Hostname has been changed to: $(hostname)"
|
||||
63
scripts/linux-setup_docker.sh
Executable file
63
scripts/linux-setup_docker.sh
Executable file
@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run this script as root: sudo $0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Removing old Docker versions..."
|
||||
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do
|
||||
apt-get remove -y $pkg || true
|
||||
done
|
||||
|
||||
# Detect OS
|
||||
if [ -f /etc/debian_version ]; then
|
||||
DOCKER_OS="debian"
|
||||
elif [ -f /etc/lsb-release ]; then
|
||||
DOCKER_OS="ubuntu"
|
||||
else
|
||||
echo "Error: Unsupported OS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating package list and installing dependencies..."
|
||||
apt-get update
|
||||
apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release
|
||||
|
||||
echo "Setting up Docker repository..."
|
||||
# Add Docker's official GPG key
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/${DOCKER_OS}/gpg -o /etc/apt/keyrings/docker.asc
|
||||
chmod a+r /etc/apt/keyrings/docker.asc
|
||||
|
||||
# Add the repository to Apt sources
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/${DOCKER_OS} \
|
||||
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||||
tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
echo "Installing Docker..."
|
||||
apt-get update
|
||||
apt-get install -y \
|
||||
docker-ce \
|
||||
docker-ce-cli \
|
||||
containerd.io \
|
||||
docker-buildx-plugin \
|
||||
docker-compose-plugin
|
||||
|
||||
# Verify installation
|
||||
echo "Verifying Docker installation..."
|
||||
docker --version
|
||||
containerd --version
|
||||
|
||||
echo "Configuring Docker permissions..."
|
||||
groupadd docker 2>/dev/null || true
|
||||
usermod -aG docker ${SUDO_USER:-$USER}
|
||||
|
||||
echo "Enabling and starting Docker services..."
|
||||
systemctl enable --now docker.service
|
||||
systemctl enable --now containerd.service
|
||||
|
||||
echo "Docker setup completed. Please log out and log back in for group changes to take effect."
|
||||
30
scripts/linux-setup_zsh.sh
Executable file
30
scripts/linux-setup_zsh.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "Please run this script as root: sudo $0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if Zsh is already installed
|
||||
if command -v zsh &> /dev/null; then
|
||||
echo "Zsh is already installed. Skipping installation."
|
||||
else
|
||||
echo "Updating package list..."
|
||||
apt-get update
|
||||
|
||||
echo "Installing Zsh..."
|
||||
apt-get install -y zsh
|
||||
|
||||
if ! command -v zsh &> /dev/null; then
|
||||
echo "Error: Zsh installation failed."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Changing default shell to Zsh for user ${SUDO_USER:-$USER}..."
|
||||
zsh_path=$(command -v zsh)
|
||||
chsh -s "$zsh_path" "${SUDO_USER:-$USER}"
|
||||
|
||||
echo "Zsh installation and setup complete. Please log out and log back in for changes to take effect."
|
||||
10
scripts/macos-brew_backup.sh
Executable file
10
scripts/macos-brew_backup.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
BACKUP_FILE="$HOME/.dotfiles/config/envs/macos/homebrew/Brewfile"
|
||||
|
||||
echo "Backing up Homebrew installations..."
|
||||
mkdir -p "$(dirname "$BACKUP_FILE")"
|
||||
|
||||
brew bundle dump --file="$BACKUP_FILE" --force
|
||||
|
||||
echo "Backup saved to $BACKUP_FILE"
|
||||
13
scripts/macos-brew_restore.sh
Executable file
13
scripts/macos-brew_restore.sh
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
BACKUP_FILE="$HOME/.dotfiles/config/envs/macos/homebrew/Brewfile"
|
||||
|
||||
if [[ ! -f "$BACKUP_FILE" ]]; then
|
||||
echo "Backup file not found: $BACKUP_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Restoring Homebrew installations..."
|
||||
brew bundle --file="$BACKUP_FILE"
|
||||
|
||||
echo "Homebrew restoration complete."
|
||||
22
scripts/macos-change_hostname.sh
Executable file
22
scripts/macos-change_hostname.sh
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run this script as root using sudo."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 <new-hostname>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NEW_HOSTNAME=$1
|
||||
|
||||
scutil --set HostName "$NEW_HOSTNAME"
|
||||
scutil --set ComputerName "$NEW_HOSTNAME"
|
||||
scutil --set LocalHostName "$NEW_HOSTNAME"
|
||||
|
||||
echo "Hostname has been changed to:"
|
||||
echo "HostName: $(scutil --get HostName)"
|
||||
echo "ComputerName: $(scutil --get ComputerName)"
|
||||
echo "LocalHostName: $(scutil --get LocalHostName)"
|
||||
57
scripts/setup_ssh_keys.sh
Executable file
57
scripts/setup_ssh_keys.sh
Executable file
@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 --comment <comment> [--filename <filename>]"
|
||||
echo " --comment <comment> The comment for the SSH key."
|
||||
echo " --filename <filename> (optional) The filename suffix for the SSH key. Defaults to 'id_ed25519'."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Default values
|
||||
COMMENT=""
|
||||
FILENAME="id_ed25519"
|
||||
|
||||
# Parse named arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--comment)
|
||||
COMMENT="$2"
|
||||
shift 2
|
||||
;;
|
||||
--filename)
|
||||
FILENAME="id_ed25519_$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate required arguments
|
||||
if [ -z "$COMMENT" ]; then
|
||||
echo "Error: --comment is required."
|
||||
usage
|
||||
fi
|
||||
|
||||
SSH_DIR="$HOME/.ssh"
|
||||
KEY_PATH="$SSH_DIR/$FILENAME"
|
||||
|
||||
# Ensure SSH directory exists
|
||||
mkdir -p "$SSH_DIR"
|
||||
chmod 700 "$SSH_DIR"
|
||||
|
||||
# Generate SSH key
|
||||
if [ -f "$KEY_PATH" ]; then
|
||||
echo "Error: Key file $KEY_PATH already exists."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ssh-keygen -t ed25519 -C "$COMMENT" -f "$KEY_PATH" -N ""
|
||||
|
||||
echo "SSH key created: $KEY_PATH"
|
||||
echo "Public key:"
|
||||
cat "$KEY_PATH.pub"
|
||||
Loading…
Reference in New Issue
Block a user