Compare commits

36 Commits

Author SHA1 Message Date
ec4785be12 remove orb ask sudo 2026-01-23 13:07:23 +01:00
5972c3c5df feat(flow): more cases for sync check 2025-11-07 19:06:56 +02:00
2fdf72d746 refactor: clean up 2025-11-06 13:17:28 +01:00
f8390f006d feat(macos): add defaults script 2025-11-06 13:16:54 +01:00
0c2b2875ed feat(nvim): update 2025-11-06 14:11:48 +02:00
0ab2aa869c feat(macos): update homebrew 2025-11-06 12:51:48 +01:00
42b634c19b feat(rectangle): add plist 2025-11-06 11:14:53 +01:00
ad2e33db35 bump karabiner 2025-11-06 11:14:53 +01:00
35a9e08a7e feat(flow): add dotfiles 2025-11-04 05:30:35 +02:00
4d895b2c52 feat(macos): enable karabiner again 2025-11-04 04:29:32 +01:00
9db467735f feat(flow): add git sync command 2025-11-03 07:58:01 +02:00
7b72fa6796 fix(flow): regex 2025-11-03 06:28:47 +01:00
13ddf830c9 bump: barg-parser 2025-11-03 07:27:47 +02:00
f4ce2ef3c3 refactor(flow): set HOME var 2025-11-03 05:58:44 +01:00
27ec787416 refactor: adapt barg and flow 2025-11-03 06:51:37 +02:00
f1b0fd94fb feat: add barg-parser 2025-11-03 06:47:34 +02:00
866a25a66d feat(macos): add kitty 2025-11-03 05:31:44 +01:00
34b6439521 refactor: clean up and rename binaries 2025-11-03 06:26:26 +02:00
60834ccae1 feat/devflow 2025-11-03 06:08:42 +02:00
78ea031fd6 macos update 2025-11-02 20:40:39 +01:00
ed51e48bb4 remove macos specific bins 2025-10-20 20:01:50 +02:00
799b186e9f add nvim as submodule 2025-10-20 20:57:15 +03:00
3b4e2621da remove nvim 2025-10-20 20:56:55 +03:00
c8a4741d94 feat: git 2025-10-20 19:44:31 +02:00
0d394dd577 add new bins 2025-10-20 20:21:42 +03:00
13530beaaf add new bins 2025-10-20 19:19:22 +02:00
458847c4af add new bins 2025-10-20 19:17:11 +02:00
7aaf25ce85 improve zsh 2025-10-20 20:10:25 +03:00
fe553b1c3f adapt macos profile 2025-10-20 18:07:19 +02:00
aa8ce447c1 remove wezterm 2025-10-20 18:54:13 +03:00
14585bca9e remove individual bin dirs 2025-10-20 18:41:41 +03:00
05bdb4abdc reorganize packages 2025-10-20 18:29:59 +03:00
ec50d3f12f nvim add json formatter jq 2025-10-20 17:23:20 +03:00
c958a0ab9d rename config to manifest 2025-10-20 17:14:48 +03:00
d08998a0ca colors to zsh 2025-10-20 17:08:52 +03:00
f1b3dbb9c3 nvim-upgrade (#4)
Reviewed-on: #4
Co-authored-by: Tomas Mirchev <contact@tomastm.com>
Co-committed-by: Tomas Mirchev <contact@tomastm.com>
2025-10-20 13:57:13 +00:00
82 changed files with 1625 additions and 2717 deletions

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "config/shared/nvim"]
path = config/shared/nvim
url = git@gitea.tomastm.com:tomas.mirchev/nvim-config.git
[submodule "config/shared/barg-parser"]
path = config/shared/barg-parser
url = git@gitea.tomastm.com:tomas.mirchev/barg-parser.git

View File

@@ -1,153 +0,0 @@
{
"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/init.lua"
},
"post-link": "(grep -q 'alias vim=nvim' ~/.zshrc || echo 'alias vim=nvim' >> ~/.zshrc) || true"
},
"zsh": {
"link": {
"from": "shared/zsh",
"to": "~/.zshrc"
}
},
"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",
{
"package": "bin",
"link": {
"from": "macos/bin",
"to": "~/bin"
}
},
"tmux",
"nvim",
"git",
"ghostty",
"alacritty",
{
"package": "karabiner",
"link": {
"from": "macos/karabiner",
"to": "~/.config/karabiner"
}
},
{
"package": "linearmouse",
"link": {
"from": "macos/linearmouse",
"to": "~/.config/linearmouse"
}
},
{
"package": "rectangle",
"link-comment": "Needs manual import from config/macos/linearmouse"
}
],
"linux-vm": [
{
"package": "zsh",
"install": "sudo apt install -y zsh",
"post-link": "./scripts/linux-setup_zsh.sh"
},
{
"package": "tmux",
"link": {
"from": "linux-vm/tmux",
"to": "~/.tmux.conf"
},
"install": "sudo apt install -y tmux"
},
{
"package": "nvim",
"install": "bash -c 'wget -O nvim.deb https://gitea.tomastm.com/tomas.mirchev/neovim/releases/download/v0.10.0/nvim-linux-$(dpkg --print-architecture).deb && sudo dpkg -i nvim.deb && rm nvim.deb'"
},
{
"package": "git",
"install": "sudo apt install -y git"
},
{
"package": "htop",
"install": "sudo apt install -y htop"
},
"bin"
],
"linux-dev": [
{
"package": "zsh",
"install": "sudo apt install -y zsh",
"post-link": "./scripts/linux-setup_zsh.sh"
},
{
"package": "nvim",
"ignore-template": true,
"link": {
"from": "linux-dev/nvim",
"to": "~/.config/nvim"
},
"post-link": "nvim --headless '+Lazy! restore' +qa"
},
{
"package": "git",
"install": "sudo apt install -y git"
},
{
"package": "htop",
"install": "sudo apt install -y htop"
}
]
}
}

View File

@@ -1 +0,0 @@
require("themes.invero").load()

View File

@@ -1,22 +0,0 @@
--[[
Neovim Lua config: ways to set things
- vim.opt : preferred modern API for options (handles lists, cleaner syntax)
- vim.g : global variables (leader key, plugin settings, disable builtins, etc.)
- vim.o : global-only option (rarely needed directly)
- vim.wo : window-local option (applies to current window only, use in autocmds)
- vim.bo : buffer-local option (applies to current buffer only, use in autocmds)
- vim.env : set environment variables (like PATH, LANG)
- vim.fn : call Vimscript functions (e.g. vim.fn.getcwd())
- vim.cmd : run raw Vimscript/Ex commands (e.g. vim.cmd("colorscheme desert"))
- vim.api : low-level Neovim API (create autocmds, keymaps, buffer/window ops, etc.)
TL;DR -> use vim.opt + vim.g in options.lua for defaults.
Use vim.wo/vim.bo only in context-specific tweaks (autocmds).
Use vim.env, vim.fn, vim.cmd, vim.api as needed for scripting.
]]
require("config.options")
require("config.keymaps")
require("config.lazy")
require("config.autocmds")

View File

@@ -1,22 +0,0 @@
{
"cmp-nvim-lsp": { "branch": "main", "commit": "bd5a7d6db125d4654b50eeae9f5217f24bb22fd3" },
"cmp-path": { "branch": "main", "commit": "c642487086dbd9a93160e1679a1327be111cbc25" },
"conform.nvim": { "branch": "master", "commit": "b4aab989db276993ea5dcb78872be494ce546521" },
"fidget.nvim": { "branch": "main", "commit": "4d5858bd4c471c895060e1b9f3575f1551184dc5" },
"harpoon": { "branch": "harpoon2", "commit": "ed1f853847ffd04b2b61c314865665e1dadf22c7" },
"lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" },
"mason-lspconfig.nvim": { "branch": "main", "commit": "25c11854aa25558ee6c03432edfa0df0217324be" },
"mason.nvim": { "branch": "main", "commit": "d66c60e17dd6fd8165194b1d14d21f7eb2c1697a" },
"nvim-autopairs": { "branch": "master", "commit": "23320e75953ac82e559c610bec5a90d9c6dfa743" },
"nvim-cmp": { "branch": "main", "commit": "b5311ab3ed9c846b585c0c15b7559be131ec4be9" },
"nvim-lspconfig": { "branch": "master", "commit": "d9879110d0422a566fa01d732556f4d5515e1738" },
"nvim-tree.lua": { "branch": "master", "commit": "321bc61580fd066b76861c32de3319c3a6d089e7" },
"nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" },
"nvim-ts-autotag": { "branch": "main", "commit": "c4ca798ab95b316a768d51eaaaee48f64a4a46bc" },
"nvim-web-devicons": { "branch": "master", "commit": "6e51ca170563330e063720449c21f43e27ca0bc1" },
"plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
"schemastore.nvim": { "branch": "main", "commit": "0fccf9234acfd981867cbd42c4101829e6808790" },
"telescope-fzf-native.nvim": { "branch": "main", "commit": "1f08ed60cafc8f6168b72b80be2b2ea149813e55" },
"telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" },
"telescope.nvim": { "branch": "0.1.x", "commit": "a0bbec21143c7bc5f8bb02e0005fa0b982edc026" }
}

View File

@@ -1,128 +0,0 @@
-- Highlight when yanking (copying) text
vim.api.nvim_create_autocmd("TextYankPost", {
callback = function()
vim.highlight.on_yank()
end,
})
----------------------------------------------
-- Reload ColorScheme by clearing cached modules
vim.api.nvim_create_user_command("ReloadColorscheme", function()
local current = vim.g.colors_name
if not current then
vim.notify("No colorscheme is currently set", vim.log.levels.WARN)
return
end
-- clear only the cached modules for this theme
for k in pairs(package.loaded) do
if k:match("^themes%." .. current) then
package.loaded[k] = nil
end
end
-- reload it
vim.cmd("colorscheme " .. current)
vim.notify("Reloaded " .. current .. " colorscheme", vim.log.levels.INFO)
end, { desc = "Reload the current colorscheme" })
----------------------------------------------
--[[
Command :TSHighlightRoots (works but uncomment only when used)
Description:
Collects all Tree-sitter highlight groups, resolves their links,
and outputs the unique root groups actually used (for theming/debugging).
Usage:
:TSHighlightRoots -> prints roots in the command line
:TSHighlightRoots <filename> -> writes roots into <filename> (overwrites)
(filename supports ~ and tab-completion)
]]
-- local function resolve_link(name)
-- local seen = {}
-- while name and not seen[name] do
-- seen[name] = true
-- local hl = vim.api.nvim_get_hl(0, { name = name })
-- if hl.link then
-- name = hl.link
-- else
-- return name
-- end
-- end
-- end
--
-- vim.api.nvim_create_autocmd("VimEnter", {
-- callback = function()
-- vim.api.nvim_create_user_command("TSHighlightRoots", function(opts)
-- local roots = {}
-- for _, group in ipairs(vim.fn.getcompletion("@", "highlight")) do
-- local root = resolve_link(group)
-- if root then
-- roots[root] = true
-- end
-- end
--
-- local output = { "Unique root highlight groups used by Tree-sitter:" }
-- for root in pairs(roots) do
-- table.insert(output, " " .. root)
-- end
--
-- if opts.args ~= "" then
-- -- write to file
-- local filename = vim.fn.expand(opts.args)
-- local fd = assert(io.open(filename, "w"))
-- fd:write(table.concat(output, "\n"))
-- fd:close()
-- print("Wrote roots to " .. filename)
-- else
-- -- default: print to command line
-- for _, line in ipairs(output) do
-- print(line)
-- end
-- end
-- end, {
-- nargs = "?", -- allow 0 or 1 argument
-- complete = "file", -- tab-complete filenames
-- })
-- end,
-- })
----------------------------------------------
-- Useful tricks that do not fully work
----------------------------------------------
-- -- Show cursorline only in the active window
--
-- vim.api.nvim_create_autocmd({ "WinEnter", "BufEnter" }, {
-- callback = function()
-- local ft = vim.bo.filetype
-- vim.notify("enter: " .. ft .. " - " .. vim.bo.buftype)
-- -- if not ft:match("^Telescope") and ft ~= "NvimTree" then
-- -- vim.wo.cursorline = true
-- -- end
-- end,
-- })
-- vim.api.nvim_create_autocmd({ "WinLeave", "BufLeave" }, {
-- callback = function()
-- local ft = vim.bo.filetype
-- vim.notify("exit: " .. ft .. " - " .. vim.bo.buftype)
-- -- if not ft:match("^Telescope") and ft ~= "NvimTree" then
-- -- vim.wo.cursorline = false
-- -- end
-- end,
-- })
----------------------------------------------
-- -- Associate filetype
--
-- vim.api.nvim_create_autocmd("FileType", {
-- pattern = "text",
-- callback = function()
-- vim.bo.filetype = "markdown"
-- end,
-- })

View File

@@ -1,50 +0,0 @@
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.cmap("jk", "<C-c>", { desc = "Exit command/search 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" })

View File

@@ -1,18 +0,0 @@
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({
spec = { { import = "plugins" } },
ui = {
backdrop = 100,
border = "rounded"
},
})

View File

@@ -1,95 +0,0 @@
-- Map Leader
vim.g.mapleader = " "
vim.g.maplocalleader = " "
-- Use Nerd Font
vim.g.have_nerd_font = false
if vim.env.CONTAINER == "true" then
vim.g.clipboard = {
name = "osc52",
copy = {
["+"] = require("vim.ui.clipboard.osc52").copy("+"),
["*"] = require("vim.ui.clipboard.osc52").copy("*"),
},
paste = {
["+"] = require("vim.ui.clipboard.osc52").paste("+"),
["*"] = require("vim.ui.clipboard.osc52").paste("*"),
},
}
end
-- Sync clipboard between OS and Neovim
vim.schedule(function()
vim.opt.clipboard = "unnamedplus"
end)
-- Add vertical line
vim.opt.colorcolumn = "100"
-- vim.opt.laststatus = 3
vim.opt.signcolumn = "no"
-- Enable TrueColor
vim.opt.termguicolors = false
-- Scroll lines/columns
vim.opt.mousescroll = "hor:1,ver:1"
-- Set indentation preferences
vim.opt.expandtab = true -- Convert tabs to spaces
vim.opt.shiftwidth = 4 -- Number of spaces for auto-indent
vim.opt.tabstop = 4 -- Number of spaces a tab counts for
vim.opt.softtabstop = 4 -- 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 "
-- vim.opt.statusline = "%= %F%m%r%h%w ─ (%l,%c %P) %="
-- vim.opt.fillchars:append({ stl = "─", stlnc = "─" })
-- 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
vim.opt.guicursor = "n-v-i-c:block"
-- Minimal number of screen lines to keep above and below the cursor
vim.opt.scrolloff = 10
-- Load the colorscheme
vim.cmd.colorscheme("invero")

View File

@@ -1,46 +0,0 @@
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" },
sh = { "shfmt" },
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 },
},
formatters = {
shfmt = {
prepend_args = { "-i", "4", "-ci" }, -- 4 spaces, indent cases
},
},
},
}

View File

@@ -1,13 +0,0 @@
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,
}

View File

@@ -1,11 +0,0 @@
return {
"windwp/nvim-ts-autotag",
opts = {
autotag = {
enable = true,
enable_close = true,
enable_rename = true,
enable_close_on_slash = true,
},
},
}

View File

@@ -1,60 +0,0 @@
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,
}

View File

@@ -1,42 +0,0 @@
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,
}

View File

@@ -1,104 +0,0 @@
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", version = "1.8.0", config = true },
{ "williamboman/mason-lspconfig.nvim", version = "1.31.0"},
{ "j-hui/fidget.nvim", opts = {} }, -- side fidget showing status
"hrsh7th/cmp-nvim-lsp", -- completion
"b0o/schemastore.nvim",
},
config = function()
require("mason").setup({
ui = {
border = "rounded",
backdrop = 0
},
})
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,
}

View File

@@ -1,212 +0,0 @@
return {
"nvim-tree/nvim-tree.lua",
version = "*",
lazy = false,
keys = {
{ "<Leader>et", ":NvimTreeToggle<CR>", desc = "Explorer Toggle", silent = true },
{
"<Leader>ei",
function()
require("nvim-tree.api").node.show_info_popup()
end,
desc = "NvimTree: Info",
mode = "n",
},
},
config = function()
local function my_on_attach(bufnr)
local api = require("nvim-tree.api")
local function opts(desc)
return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true }
end
api.config.mappings.default_on_attach(bufnr)
vim.keymap.set("n", "<Leader>et", api.tree.toggle, opts("Open or close the tree"))
vim.keymap.set("n", "<Leader>ei", api.node.show_info_popup, opts("Show info popup"))
vim.keymap.set("n", "?", api.tree.toggle_help, opts("Help"))
vim.keymap.del("n", "<C-k>", { buffer = bufnr })
end
require("nvim-tree").setup({
on_attach = my_on_attach,
hijack_cursor = true,
disable_netrw = true,
hijack_netrw = true,
hijack_unnamed_buffer_when_opening = true,
root_dirs = { ".git", "package.json" },
prefer_startup_root = true,
sync_root_with_cwd = true,
reload_on_bufenter = true,
respect_buf_cwd = true,
view = {
centralize_selection = false,
cursorline = true,
cursorlineopt = "both",
debounce_delay = 15,
side = "left",
preserve_window_proportions = false,
number = false,
relativenumber = false,
signcolumn = "no",
width = 30,
},
renderer = {
add_trailing = false,
group_empty = false,
full_name = false,
root_folder_label = false,
-- special_files = { "Cargo.toml", "Makefile", "README.md", "readme.md" },
special_files = {}, -- keep to overwrite defaults
symlink_destination = true,
icons = {
padding = "",
glyphs = {
folder = {
arrow_closed = "+",
arrow_open = "-",
},
},
show = {
file = false,
folder = false,
folder_arrow = true,
git = false,
modified = false,
hidden = false,
diagnostics = false,
bookmarks = false,
},
},
},
hijack_directories = {
enable = true,
auto_open = true,
},
update_focused_file = {
enable = true,
update_root = {
enable = true,
ignore_list = {},
},
exclude = false,
},
filters = {
enable = true,
git_ignored = true,
dotfiles = false,
git_clean = false,
no_buffer = false,
no_bookmark = false,
custom = {},
exclude = {},
},
live_filter = {
prefix = "[FILTER]: ",
always_show_folders = true,
},
filesystem_watchers = {
enable = true,
debounce_delay = 50,
ignore_dirs = {
-- C / C++
"/.ccls-cache",
"/build",
"/out",
"/cmake-build-*",
-- Node.js / Web
"/node_modules",
"/dist",
"/.next",
"/.nuxt",
"/coverage",
"/storybook-static",
-- Rust
"/target",
-- Java / JVM
"/target", -- (Maven)
"/build", -- (Gradle)
"/out", -- (IDEA / javac)
-- Python
"/.venv",
"/venv",
"/__pycache__",
"/.mypy_cache",
"/.pytest_cache",
-- Go
"/bin",
"/pkg",
-- General
"/tmp",
"/.cache",
"/.idea",
"/.vscode",
"/logs",
},
},
trash = {
cmd = "gio trash",
},
})
end,
}
-- 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 = {
-- event_handlers = {
-- {
-- event = require("neo-tree.ui.events").NEO_TREE_WINDOW_AFTER_OPEN,
-- handler = function(args)
-- if args and args.winid and vim.api.nvim_win_is_valid(args.winid) then
-- vim.api.nvim_win_set_option(args.winid, "colorcolumn", "")
-- vim.api.nvim_win_set_option(args.winid, "signcolumn", "no")
-- end
-- end,
-- },
-- },
-- popup_border_style = "single",
-- window = {
-- mappings = {
-- ["<Leader>e"] = "close_window",
-- },
-- },
-- default_component_configs = {
-- icon = { enabled = false },
-- git_status = { symbols = {}, align = "none" },
-- name = { trailing_slash = true }
-- },
-- enable_git_status = false,
-- enable_diagnostics = false,
-- filesystem = {
-- follow_current_file = {
-- enabled = true, -- Enable this feature
-- leave_dirs_open = true, -- Leave directories open when following
-- },
-- filtered_items = {
-- visible = true,
-- }
-- },
-- },
-- }

View File

@@ -1,52 +0,0 @@
local remap = require("utils.remap")
return {
"nvim-telescope/telescope.nvim",
event = "VimEnter",
branch = "0.1.x",
dependencies = {
"nvim-lua/plenary.nvim",
{
"nvim-telescope/telescope-fzf-native.nvim",
build = "make",
cond = function()
return vim.fn.executable("make") == 1
end,
},
{ "nvim-telescope/telescope-ui-select.nvim" },
-- { "nvim-tree/nvim-web-devicons", enabled = vim.g.have_nerd_font },
},
config = function()
require("telescope").setup({
defaults = {
layout_strategy = "vertical",
layout_config = {
width = { 0.95, max = 100 },
height = 0.95,
preview_cutoff = 1,
preview_height = 0.7,
},
mappings = {
n = {
["d"] = "delete_buffer",
},
},
},
})
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>ss", builtin.current_buffer_fuzzy_find, { desc = "[S]earch [C]urrent file" })
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,
}

View File

@@ -1,32 +0,0 @@
return {
"nvim-treesitter/nvim-treesitter",
build = "TSUpdate",
main = "nvim-treesitter.configs",
opts = {
ensure_installed = {
"diff",
"lua",
"html",
"css",
"javascript",
"typescript",
"tsx",
"markdown",
"markdown_inline",
},
auto_install = true,
highlight = {
enable = true,
},
indent = { enable = true },
},
config = function(_, opts)
require("nvim-treesitter.configs").setup(opts)
-- Add MDX filetype detection
vim.filetype.add({
extension = {
mdx = "markdown.mdx",
},
})
end,
}

View File

@@ -1,19 +0,0 @@
local M = {}
function M.get(P)
local colors = {
base = P.white,
surface = P.gray_light,
outline = P.gray_dark,
text = P.black,
muted = P.gray,
accent = P.blue,
accent_light = P.blue_light,
syntax = P.slate_indigo,
none = "NONE",
}
return vim.tbl_extend("force", P, colors)
end
return M

View File

@@ -1,35 +0,0 @@
local M = {}
function M.get(C)
return {
Normal = { fg = C.text, bg = C.none },
Directory = { fg = C.accent },
Question = { fg = C.text },
LineNr = { fg = C.muted },
CursorLineNr = { fg = C.accent, bold = true },
CursorLine = { bg = C.surface },
Visual = { bg = C.accent_light },
ColorColumn = { bg = C.surface },
Search = { fg = C.yellow },
CurSearch = { fg = C.yellow, bg = C.none, bold = true },
IncSearch = { fg = C.yellow, bg = C.none, bold = true },
MatchParen = { fg = C.accent, bg = C.accent_light, bold = true },
EndOfBuffer = { fg = C.base }, -- End-of-buffer marker (~ lines)
WinSeparator = { fg = C.outline },
-- StatusLine = { fg = C.outline, bg = C.none }, -- Active statusline (where filename)
StatusLine = { fg = C.base, bg = C.outline, bold = false }, -- Active statusline (where filename)
StatusLineNC = { fg = C.base, bg = C.outline, bold = false }, -- Active statusline (where filename)
MsgArea = { fg = C.text, bg = C.none }, -- Command-line / message area
MsgSeparator = { fg = C.text, bg = C.surface }, -- Separator for messages
ModeMsg = { fg = C.text },
TabLine = { fg = C.muted }, -- Unselected tab
TabLineSel = { fg = C.text, bold = true }, -- Selected tab
TabLineFill = { bg = C.none }, -- Empty space in the tabline
}
end
return M

View File

@@ -1,7 +0,0 @@
local M = {}
function M.get(C)
return {}
end
return M

View File

@@ -1,9 +0,0 @@
local M = {}
function M.get(C)
return {
TelescopeMatching = { fg = C.yellow, bg = C.none, bold = true },
}
end
return M

View File

@@ -1,21 +0,0 @@
local M = {}
function M.get(C)
return {
["@constant.macro"] = { fg = C.syntax },
["@function.method"] = { fg = C.syntax },
["@type.qualifier"] = { fg = C.syntax },
["@variable.parameter"] = { fg = C.syntax },
["@variable"] = { fg = C.syntax },
["@type.definition"] = { fg = C.syntax },
["@markup.italic"] = { fg = C.syntax },
["@markup.strong"] = { fg = C.syntax },
["@markup.underline"] = { fg = C.syntax },
["@markup.strikethrough"] = { fg = C.syntax },
["@_jsx_attribute"] = { link = "Constant" },
["@string.documentation.python"] = { link = "Comment" },
}
end
return M

View File

@@ -1,38 +0,0 @@
local M = {}
function M.get(C)
return {
Comment = { fg = C.muted, italic = true },
String = { fg = C.green },
Boolean = { fg = C.accent, bold = true, italic = true },
Number = { fg = C.accent },
-- syntax color
Constant = { fg = C.syntax },
Function = { fg = C.syntax },
Type = { fg = C.syntax },
Statement = { fg = C.syntax },
Identifier = { fg = C.syntax },
Operator = { fg = C.syntax },
PreProc = { fg = C.syntax },
Special = { fg = C.syntax },
Delimiter = { fg = C.syntax },
Todo = { fg = C.syntax },
Title = { fg = C.syntax },
Underlined = { fg = C.syntax },
-- diffs
Added = { fg = C.green },
Removed = { fg = C.red },
Changed = { fg = C.yellow },
-- diagnostics
DiagnosticInfo = { fg = C.blue },
DiagnosticWarn = { fg = C.yellow },
DiagnosticError = { fg = C.red },
DiagnosticDeprecated = { fg = C.magenta },
DiagnosticUnderlineError = { fg = C.syntax, underline = true },
}
end
return M

View File

@@ -1,31 +0,0 @@
local M = {}
function M.get(C)
return {
terminal_color_0 = { fg = C.black },
terminal_color_8 = { fg = C.black },
terminal_color_1 = { fg = C.red },
terminal_color_9 = { fg = C.red },
terminal_color_2 = { fg = C.green },
terminal_color_10 = { fg = C.green },
terminal_color_3 = { fg = C.yellow },
terminal_color_11 = { fg = C.yellow },
terminal_color_4 = { fg = C.blue },
terminal_color_12 = { fg = C.blue },
terminal_color_5 = { fg = C.magenta },
terminal_color_13 = { fg = C.magenta },
terminal_color_6 = { fg = C.cyan },
terminal_color_14 = { fg = C.cyan },
terminal_color_7 = { fg = C.white },
terminal_color_15 = { fg = C.white },
}
end
return M

View File

@@ -1,14 +0,0 @@
local M = {
name = "invero",
variant = "light",
mode = "ansi",
exclude_integrations = {},
}
function M.load()
local setup = require("themes." .. M.name .. ".setup")
setup.reset(M)
setup.apply(M)
end
return M

View File

@@ -1,53 +0,0 @@
local M = {}
local modes = {
ansi = {
black = 0,
red = 1,
green = 2,
yellow = 3,
blue = 4,
magenta = 5,
cyan = 6,
white = 7,
},
default = {
black = 238,
red = 196,
green = 35,
yellow = 221,
blue = 27,
magenta = 125,
cyan = 30,
white = 255,
},
}
local shared_palette = {
gray_dark = 245,
gray = 247,
gray_light = 253,
orange = 166,
orange_light = 180,
yellow_light = 180,
blue_light = 153,
slate_indigo = 60,
}
---Get color palette
---@param mode '"ansi"'|'"default"'
---@return table
function M.get(mode)
local mode_palette = modes[mode]
if not mode_palette then
vim.notify(
string.format('Invalid palette mode: "%s" (valid: ansi, default)', tostring(mode)),
vim.log.levels.WARN,
{ title = "palette" }
)
mode_palette = modes.default
end
return vim.tbl_extend("force", mode_palette, shared_palette)
end
return M

View File

@@ -1,72 +0,0 @@
local M = {}
function M.reset(theme)
vim.opt.background = (theme.variant == "light") and "light" or "dark"
vim.g.colors_name = theme.name
end
local function list_integrations(theme_name)
local path = vim.fn.stdpath("config") .. "/lua/themes/" .. theme_name .. "/groups/integrations/"
local files = {}
for name, type in vim.fs.dir(path) do
if type == "file" then
local mod_name = vim.fn.fnamemodify(name, ":r")
table.insert(files, mod_name)
end
end
return files
end
function M.apply(theme)
local base = "themes." .. theme.name
local P = require(base .. ".palette").get(theme.mode)
local C = require(base .. ".colors").get(P)
local modules = {
require(base .. ".groups.editor"),
require(base .. ".groups.syntax"),
require(base .. ".groups.terminal"),
}
local exclude = theme.exclude_integrations or {}
local function should_load(name)
return not vim.tbl_contains(exclude, name)
end
-- auto-discover integrations
for _, plugin in ipairs(list_integrations(theme.name)) do
if should_load(plugin) then
local ok_mod, mod = pcall(require, base .. ".groups.integrations." .. plugin)
if ok_mod then
table.insert(modules, mod)
end
end
end
-- Apply highlights
for _, mod in ipairs(modules) do
local groups = mod.get(C) or {}
for group, opts in pairs(groups) do
if type(opts) ~= "table" then
print("Non-table opts detected in group:", group, "value:", vim.inspect(opts))
end
local hl = {}
for k, v in pairs(opts) do
if k == "fg" then
hl.ctermfg = v
elseif k == "bg" then
hl.ctermbg = v
else
hl[k] = v -- bold, italic, underline, sp, etc.
end
end
vim.api.nvim_set_hl(0, group, hl)
end
end
end
return M

View File

@@ -1,39 +0,0 @@
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
function M.cmap(lhs, rhs, opts)
M.map("c", lhs, rhs, opts)
end
return M

View File

@@ -1,105 +0,0 @@
-- 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

View File

@@ -0,0 +1,78 @@
[env]
# TERM = "xterm-256color"
[font]
size = 14
normal = { family = "SF Mono", style = "Regular" }
bold = { family = "SF Mono", style = "Bold" }
italic = { family = "SF Mono", style = "Regular Italic" }
bold_italic = { family = "SF Mono", style = "Bold Italic" }
# normal = { family = "Maple Mono", style = "Regular" }
# bold = { family = "Maple Mono", style = "Bold" }
# italic = { family = "Maple Mono", style = "Italic" }
# bold_italic = { family = "Maple Mono", style = "Bold Italic" }
# offset = { x = -1, y = 0 }
[window]
padding = { x = 2, y = 0 }
dynamic_padding = true
# 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
[general]
live_config_reload = true
[colors.primary]
background = "#eeeeee"
foreground = "#444444"
[colors.cursor]
text = "#eeeeee"
cursor = "#005fff"
[colors.selection]
text = "#434343"
background = "#e0e0e0"
[colors.normal]
black = "#000000"
red = "#aa3731"
green = "#448c27"
yellow = "#cb9000"
blue = "#325cc0"
magenta = "#7a3e9d"
cyan = "#0083b2"
white = "#bbbbbb"
[colors.bright]
black = "#000000"
red = "#aa3731"
green = "#448c27"
yellow = "#cb9000"
blue = "#325cc0"
magenta = "#7a3e9d"
cyan = "#0083b2"
white = "#bbbbbb"

View File

@@ -0,0 +1,27 @@
[colors.primary]
background = '#F7F7F7'
foreground = '#434343'
[colors.cursor]
text = '#F7F7F7'
cursor = '#434343'
[colors.normal]
black = '#000000'
red = '#AA3731'
green = '#448C27'
yellow = '#CB9000'
blue = '#325CC0'
magenta = '#7A3E9D'
cyan = '#0083B2'
white = '#BBBBBB'
[colors.bright]
black = '#777777'
red = '#F05050'
green = '#60CB00'
yellow = '#FFBC5D'
blue = '#007ACC'
magenta = '#E64CE6'
cyan = '#00AACB'
white = '#FFFFFF'

View File

@@ -1,135 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ATTACH_TMUX=1
DRY_RUN=0
TMUX_SESSION_DEFAULT="default"
df_platform=""
df_namespace=""
df_user=""
ssh_identity=""
ssh_host=""
ssh_args=()
usage() {
local prog
prog=$(basename "$0")
echo "Usage: $prog <platform> [user@]namespace [--no-tmux|-t] [--dry-run|-n] [-- <ssh args...>]" >&2
echo
echo "Examples:"
echo " $prog orb namespace"
echo " $prog utm user@namespace --no-tmux"
echo " $prog core user@namespace --dry-run -- -v -p 2222"
exit 1
}
parse_args() {
if [[ $# -lt 2 ]]; then
usage
fi
df_platform="$1"
local user_namespace_arg="$2"
shift 2
# Extract df_user and df_namespace
if [[ "$user_namespace_arg" == *@* ]]; then
df_user="${user_namespace_arg%@*}"
df_namespace="${user_namespace_arg#*@}"
else
df_user="$USER"
df_namespace="$user_namespace_arg"
fi
# Parse remaining flags and ssh args
while [[ $# -gt 0 ]]; do
case "$1" in
-t|--no-tmux)
ATTACH_TMUX=0
shift
;;
-n|--dry-run)
DRY_RUN=1
shift
;;
--)
shift
ssh_args+=("$@")
break
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
done
}
resolve_host() {
case "$df_platform" in
orb)
# orb-stack handles user@namespace internally
ssh_host="${df_namespace}@orb"
;;
utm)
ssh_host="${df_namespace}.utm.local"
ssh_identity="$HOME/.ssh/id_ed25519_internal"
;;
core)
ssh_host="${df_namespace}.core.lan"
ssh_identity="$HOME/.ssh/id_ed25519_internal"
;;
ec2)
ssh_host="${df_namespace}.ec2.internal"
;;
hetzner)
ssh_host="${df_namespace}.hetzner.test"
;;
*)
echo "Error: unknown platform '$df_platform'" >&2
exit 1
;;
esac
}
build_ssh_cmd() {
local cmd=(ssh -tt)
if [[ -n "$ssh_identity" ]]; then
cmd+=(-i "$ssh_identity" -o IdentitiesOnly=yes)
fi
if [[ ${#ssh_args[@]} -gt 0 ]]; then
cmd+=("${ssh_args[@]}")
fi
cmd+=("${df_user}@${ssh_host}")
if [[ $ATTACH_TMUX -eq 1 ]]; then
cmd+=("tmux" "new-session" "-As" "$TMUX_SESSION_DEFAULT"
"-e" "DF_NAMESPACE=$df_namespace"
"-e" "DF_PLATFORM=$df_platform")
fi
echo "${cmd[@]}"
}
main() {
parse_args "$@"
resolve_host
ssh_cmd=($(build_ssh_cmd))
if [[ $DRY_RUN -eq 1 ]]; then
echo "Dry run command:"
printf '%q ' "${ssh_cmd[@]}"
echo
exit 0
fi
exec "${ssh_cmd[@]}"
}
main "$@"

View File

@@ -1,23 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# URL="https://raw.githubusercontent.com/triimdev/invero.nvim/refs/heads/main/extras/ghostty/invero_day"
# THEME_DIR="$HOME/.config/ghostty/themes"
# THEME_NAME="Invero Day"
URL="https://raw.githubusercontent.com/triimdev/invero.nvim/refs/heads/main/extras/wezterm/invero_day.toml"
THEME_DIR="$HOME/.config/wezterm/colors"
THEME_NAME="Invero Day.toml"
THEME_PATH="${THEME_DIR}/${THEME_NAME}"
mkdir -p "$THEME_DIR"
if curl -fsSL -o "$THEME_PATH" "$URL"; then
echo "Theme downloaded to $THEME_PATH"
else
echo "Failed to download theme."
exit 1
fi

View File

@@ -1,11 +0,0 @@
#!/usr/bin/env bash
file=/tmp/vm-switch.txt
# Ensure the file exists
touch "$file"
echo "Listening on $file ..."
tail -n0 -F "$file" | while read vm; do
[ -n "$vm" ] && echo "Switch requested: $vm" && ~/bin/work "$vm" &
done

View File

@@ -1,3 +0,0 @@
#!/bin/sh
orbctl list > /tmp/vmlist.txt

View File

@@ -1,10 +0,0 @@
#!/bin/sh
# Usage: work <vm>
vm="$1"
if [ -z "$vm" ]; then
echo "Usage: work <vm>"
exit 1
fi
exec vm "${vm}-orb"

13
config/macos/borders/bordersrc Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
options=(
order=above
width=2.0
hidpi=on
active_color=0xff2b2b2b
inactive_color=0xff2b2b2b
# inactive_color=0x00000000
whitelist="wezterm-gui"
)
borders "${options[@]}"

View File

@@ -0,0 +1,33 @@
#term = xterm-256color
theme = Invero Day
# Font
font-family = "Maple Mono"
font-size = 13
font-thicken = true
font-thicken-strength = 120
font-feature = -liga, -dlig, -calt
adjust-underline-thickness = 1
adjust-strikethrough-thickness = 1
adjust-overline-thickness = 1
adjust-box-thickness = 1
adjust-cell-width = -7%
adjust-cell-height = -2
# Cursor
cursor-style = block
cursor-style-blink = false
mouse-hide-while-typing = true
shell-integration-features = ssh-terminfo,ssh-env,no-cursor
# Window
window-height = 80
window-width = 128
window-padding-x = 4
window-padding-y = 0
window-padding-color = extend
macos-titlebar-style = native
macos-icon = custom
window-inherit-working-directory = false

View File

@@ -1,21 +1,25 @@
tap "homebrew/bundle"
tap "homebrew/services"
brew "bash"
brew "dnsmasq", restart_service: :changed
brew "neovim"
cask "daisydisk"
brew "tmux"
cask "brave-browser"
cask "bruno"
cask "dbeaver-community"
cask "discord"
cask "firefox"
cask "font-maple-mono"
cask "font-maple-mono-nf"
cask "ghostty"
cask "google-chrome"
cask "karabiner-elements"
cask "linearmouse"
cask "obsidian"
cask "macfuse"
cask "orbstack"
cask "proton-drive"
cask "protonvpn"
cask "rectangle"
cask "slack"
cask "sol"
cask "spotify"
cask "utm"
cask "visual-studio-code"
cask "sublime-text"
cask "utm@beta"
cask "zoom"

View File

@@ -1,20 +0,0 @@
{
"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
}
]
}

View File

@@ -1,44 +0,0 @@
{
"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" }
}
]
}

View File

@@ -1,43 +0,0 @@
{
"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" }
}
]
}

View File

@@ -1,44 +0,0 @@
{
"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" }
}
]
}

View File

@@ -0,0 +1,15 @@
{
"profiles": [
{
"name": "Default profile",
"selected": true,
"simple_modifications": [
{
"from": { "key_code": "caps_lock" },
"to": [{ "key_code": "left_control" }]
}
],
"virtual_hid_keyboard": { "keyboard_type_v2": "iso" }
}
]
}

View File

@@ -4,38 +4,20 @@
{
"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": 50475,
"vendor_id": 1133
},
"ignore_vendor_events": true
},
{
"identifiers": {
"is_keyboard": true,
"product_id": 49164,
"vendor_id": 7276
"product_id": 50504,
"vendor_id": 1133
},
"simple_modifications": [
{
"from": { "key_code": "left_command" },
"to": [{ "key_code": "left_option" }]
},
{
"from": { "key_code": "left_option" },
"to": [{ "key_code": "left_command" }]
},
{
"from": { "key_code": "escape" },
"to": [{ "key_code": "grave_accent_and_tilde" }]
},
{
"from": { "key_code": "grave_accent_and_tilde" },
"to": [{ "key_code": "escape" }]
}
]
"ignore_vendor_events": true
}
],
"name": "Default profile",
@@ -46,7 +28,7 @@
"to": [{ "key_code": "left_control" }]
}
],
"virtual_hid_keyboard": { "keyboard_type_v2": "ansi" }
"virtual_hid_keyboard": { "keyboard_type_v2": "iso" }
}
]
}

View File

@@ -0,0 +1,54 @@
# ~/.config/kitty/choose_tab.py
from kitty.boss import get_boss
from kittens.tui.handler import Handler
from kittens.tui.loop import Loop
class TabPicker(Handler):
def __init__(self):
super().__init__()
boss = get_boss()
win = boss.active_window
self.osw = win.os_window if win else None
self.tabs = list(self.osw.tabs) if self.osw else []
self.index = 0
def draw(self, screen):
screen.clear()
if not self.tabs:
screen.write_line("No tabs. Esc to exit.")
else:
screen.write_line("Choose a tab (↑/↓ Enter Esc)")
for i, t in enumerate(self.tabs):
mark = "" if t is self.osw.active_tab else " "
sel = ">" if i == self.index else " "
title = t.title or f"Tab {i+1}"
screen.write_line(f"{sel} {mark} {title}")
screen.refresh()
def on_key(self, event):
if not self.tabs:
if event.key in ("escape", "enter"):
self.quit_loop()
return
k = event.key
if k in ("up", "k"):
self.index = (self.index - 1) % len(self.tabs)
elif k in ("down", "j"):
self.index = (self.index + 1) % len(self.tabs)
elif k == "enter":
self.osw.set_active_tab(self.tabs[self.index])
self.quit_loop()
elif k == "escape":
self.quit_loop()
self.refresh()
def main(args):
# Correct signature for older Kitty: pass the class name and a title string
Loop(TabPicker, "choose_tab").run()
def handle_result(args, answer, target_window_id, boss):
pass

View File

@@ -0,0 +1,35 @@
# vim:ft=kitty
background #eeeeee
foreground #444444
cursor #005fff
cursor_text_color #eeeeee
selection_background #dadada
selection_foreground #444444
url_color #005fff
# Tabs
active_tab_background #005fff
active_tab_foreground #eeeeee
inactive_tab_background #dadada
inactive_tab_foreground #9e9e9e
# normal
color0 #444444
color1 #ff0000
color2 #00af5f
color3 #d75f00
color4 #005fff
color5 #5f5f87
color6 #afd7ff
color7 #eeeeee
# bright
color8 #444444
color9 #ff0000
color10 #00af5f
color11 #d75f00
color12 #005fff
color13 #5f5f87
color14 #afd7ff
color15 #eeeeee

Binary file not shown.

View File

@@ -0,0 +1,73 @@
include invero.conf
# term xterm-256color
enable_audio_bell no
cursor_shape block
wheel_scroll_multiplier 1.0
touch_scroll_multiplier 1.0
wheel_scroll_min_lines 1
shell_integration no-cursor
cursor_blink_interval 0
remember_window_position yes
remember_window_size yes
# Font
font_family Maple Mono
font_size 13.0
# disable_ligatures always
# undercurl_style thick-sparse
modify_font cell_width 94%
modify_font cell_height -2px
# modify_font baseline 2px
# modify_font underline_thickness 180%
# modify_font underline_position 2px
# modify_font strikethrough_positon 2px
text_composition_strategy legacy
# underline_exclusion 0
placement_strategy top
window_margin_width 0 0
window_padding_width 0 4
# modify_font cell_height -1
# modify_font cell_width 90%
# Navigation / editing
# Make Option act as Alt on macOS
macos_option_as_alt yes
# Use explicit bytes (no ambiguity), not \x1bb etc.
map opt+left send_text all \x1b\x62
map opt+right send_text all \x1b\x66
map cmd+left send_text all \x01
map cmd+right send_text all \x05
map opt+backspace send_text all \x1b\x7f
map cmd+backspace send_text all \x15
map opt+delete send_text all \x1b\x64
map cmd+delete send_text all \x0b
# New window / tab
map cmd+n new_os_window
map cmd+t new_tab
map cmd+1 goto_tab 1
map cmd+2 goto_tab 2
map cmd+3 goto_tab 3
map cmd+4 goto_tab 4
map cmd+5 goto_tab 5
map cmd+6 goto_tab 6
map cmd+7 goto_tab 7
map cmd+8 goto_tab 8
map cmd+9 goto_tab 9
# BEGIN_KITTY_FONTS
# font_family family="JetBrains Mono"
bold_font auto
italic_font auto
bold_italic_font auto
# END_KITTY_FONTS

Binary file not shown.

BIN
config/macos/sol/mmkv.default Executable file

Binary file not shown.

BIN
config/macos/sol/mmkv.default.crc Executable file

Binary file not shown.

View File

@@ -0,0 +1,36 @@
[colors]
background = "#eeeeee"
foreground = "#444444"
cursor_bg = "#005fff"
cursor_border = "#9e9e9e"
cursor_fg = "#eeeeee"
selection_bg = "#dadada"
selection_fg = "#444444"
split = "#005fff"
compose_cursor = "#d75f00"
scrollbar_thumb = "#9e9e9e"
copy_mode_active_highlight_bg = { Color = "#dadada" }
copy_mode_active_highlight_fg = { Color = "#d75f00" }
copy_mode_inactive_highlight_bg = { Color = "#eeeeee" }
copy_mode_inactive_highlight_fg = { Color = "#d75f00" }
ansi = ["#444444", "#ff0000", "#00af5f", "#d75f00", "#005fff", "#5f5f87", "#afd7ff", "#eeeeee"]
brights = ["#444444", "#ff0000", "#00af5f", "#d75f00", "#005fff", "#5f5f87", "#afd7ff", "#eeeeee"]
[colors.tab_bar]
inactive_tab_edge = "#ff0000"
background = "#444444"
[colors.tab_bar.active_tab]
fg_color = "#eeeeee"
bg_color = "#444444"
intensity = "Bold"
[colors.tab_bar.inactive_tab]
fg_color = "#9e9e9e"
bg_color = "#444444"
[colors.tab_bar.inactive_tab_hover]
fg_color = "#dadada"
bg_color = "#444444"

View File

@@ -0,0 +1,72 @@
local wezterm = require("wezterm")
local config = wezterm.config_builder()
local act = wezterm.action
-- General
config.term = "wezterm"
config.color_scheme = "Invero Day"
config.use_ime = false
-- Font
config.font = wezterm.font({ family = "Maple Mono NF", weight = "Medium" })
config.font_size = 13
config.harfbuzz_features = { "calt=0", "clig=0", "liga=0" } -- disables alternates and ligatures
config.underline_position = -4
config.underline_thickness = 3
-- Appearance
config.bold_brightens_ansi_colors = false
config.window_padding = { left = "0.5cell", right = "0.5cell", top = 6, bottom = 0 }
config.window_content_alignment = { horizontal = "Center", vertical = "Top" }
config.cell_width = 0.9
config.line_height = 0.9
-- Tabs
config.use_fancy_tab_bar = false
config.show_new_tab_button_in_tab_bar = false
config.hide_tab_bar_if_only_one_tab = true
-- Events
wezterm.on("toggle-tabbar", function(window, _)
local overrides = window:get_config_overrides() or {}
if overrides.enable_tab_bar == false then
wezterm.log_info("tab bar shown")
overrides.enable_tab_bar = true
else
wezterm.log_info("tab bar hidden")
overrides.enable_tab_bar = false
end
window:set_config_overrides(overrides)
end)
-- Keybindings
config.keys = {
{ mods = "OPT", key = "LeftArrow", action = act.SendString("\x1bb") }, -- Jump back one word
{ mods = "OPT", key = "RightArrow", action = act.SendString("\x1bf") }, -- Jump forward one word
{ mods = "CMD", key = "LeftArrow", action = act.SendString("\x01") }, -- Move to start of line
{ mods = "CMD", key = "RightArrow", action = act.SendString("\x05") }, -- Move to end of line
{ mods = "OPT", key = "Backspace", action = act.SendString("\x1b\x7f") }, -- Delete previous word
{ mods = "CMD", key = "Backspace", action = act.SendString("\x15") }, -- Delete previous line
{ mods = "OPT", key = "Delete", action = act.SendString("\x1bd") }, -- Delete next word
{ mods = "CMD", key = "Delete", action = act.SendString("\x0b") }, -- Delete next line
{ mods = "CMD", key = "n", action = act.SpawnWindow }, -- New window
{ mods = "CMD", key = "t", action = act.SpawnCommandInNewTab({ cwd = wezterm.home_dir }) }, -- New tab
{ mods = "SUPER|SHIFT", key = "LeftArrow", action = act({ MoveTabRelative = -1 }) }, -- Move tab left
{ mods = "SUPER|SHIFT", key = "RightArrow", action = act({ MoveTabRelative = 1 }) }, -- Move tab right
{ mods = "SUPER|SHIFT", key = "b", action = act.EmitEvent("toggle-tabbar") },
{ mods = "SUPER|SHIFT", key = "o", action = wezterm.action.ShowTabNavigator },
{
mods = "SUPER|SHIFT",
key = "r",
action = wezterm.action.PromptInputLine({
description = "Enter new tab title",
action = wezterm.action_callback(function(window, pane, line)
if line then
window:active_tab():set_title(line)
end
end),
}),
},
}
return config

View File

@@ -1,40 +0,0 @@
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

View File

@@ -1,97 +0,0 @@
#!/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)"

View File

@@ -1,18 +0,0 @@
#!/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

View File

@@ -1,327 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
source './parse_image_ref.sh'
REGISTRY="registry.tomastm.com"
REGISTRY_ABBR="tm0"
PROJECT_DIR="$HOME/projects"
PROJECT_ABBR="p"
usage() {
cat <<'EOF'
Usage: dev <command> [options] <name>
Commands:
create -i, --image <image> -p, --project <path> <name>
exec <name> [-- <cmd>...]
connect <name>
list
info <name>
stop [--kill] <name>
rm [--force|-f] <name>
Notes:
- 'exec' treats the LAST argument as <name>; everything before it is the command to run.
- If already inside tmux, 'connect' switches to the session; otherwise it attaches.
- New tmux panes/windows created in a session always run inside the container.
- within tmux that need <name>: info, stop, rm, restore, connect
EOF
exit 1
}
fail() {
printf 'Error: %s\n' "$*" >&2
exit 1
}
resolve_path() {
local path="$1"
if command -v realpath >/dev/null 2>&1; then
realpath "$path"
else
echo "$(cd "$(dirname "$path")" && pwd)/$(basename "$path")"
fi
}
docker_container_exists() {
local name="$1"
docker container ls -a --format '{{.Names}}' | grep -Fqx "$name"
}
docker_container_running() {
local name="$1"
docker container ls --format '{{.Names}}' | grep -Fqx "$name"
}
docker_image_present() {
local ref="$1"
docker image inspect "$ref" >/dev/null 2>&1
}
cmd_create() {
local image_arg="" project_arg=""
while [[ $# -gt 0 ]]; do
case "$1" in
-i | --image)
[[ $# -ge 2 ]] || fail "Missing value for $1"
image_arg="$2"
shift 2
;;
-p | --project)
[[ $# -ge 2 ]] || fail "Missing value for $1"
project_arg="$2"
shift 2
;;
-*) usage ;;
*) break ;;
esac
done
# Check args
local name_arg="${1:-}"
if [[ -z "$name_arg" || -z "$image_arg" || -z "$project_arg" ]]; then
fail "Missing arguments"
fi
# Check container name
local cname="dev-$name_arg"
if docker_container_exists "$cname"; then
fail "Container already exists: "$cname" (from name "$name_arg")"
fi
# Check project path
local project_path
project_path="$(resolve_path "$project_arg")"
if [[ ! -d "$project_path" ]]; then
fail "Invalid project path: $project_path"
fi
# Check image
IFS=' ' read -r image_ref image_repo image_tag image_label <<<"$(parse_image_ref "$image_arg")"
if ! docker_image_present "$image_ref"; then
fail $'Image not found locally.\nTry:\n\t- docker pull '"$image_ref"
fi
# Run (= create and start container)
cmd=(
docker run -d
--name "$cname"
--label dev=true
--network host
--init # run tini as PID 1 to handle signals & reap zombies for cleaner container shutdown
-v "$project_path:/workspace"
-v /var/run/docker.sock:/var/run/docker.sock
)
[[ -d "$HOME/.ssh" ]] && cmd+=(-v "$HOME/.ssh:$CONTAINER_HOME/.ssh:ro")
[[ -f "$HOME/.npmrc" ]] && cmd+=(-v "$HOME/.npmrc:$CONTAINER_HOME/.npmrc:ro")
[[ -d "$HOME/.npm" ]] && cmd+=(-v "$HOME/.npm:$CONTAINER_HOME/.npm")
docker_gid="$(getent group docker | cut -d: -f3 || true)"
[[ -n "$docker_gid" ]] && cmd+=(--group-add "$docker_gid")
cmd+=("$image_ref" sleep infinity)
"${cmd[@]}"
echo "$cname"
}
cmd_exec() {
# usage: exec <name> [-- <cmd>...]
local name="$1"
[[ -n "$name" ]] || fail "Missing project name"
shift
local cname="dev-$name"
if ! docker_container_running "$cname"; then
fail "Container $cname not running"
fi
if [[ "$1" == "--" ]]; then
shift
local args=("$@")
if [[ -t 1 ]]; then
docker exec -it "$cname" "${args[@]}"
else
docker exec "$cname" "${args[@]}"
fi
return
fi
# No command provided -> open a shell
docker exec -it "$cname" zsh -l ||
docker exec -it "$cname" bash -l ||
docker exec -it "$cname" sh
}
cmd_connect() {
# usage: connect [--from] <name>
local from_name=""
while [[ $# -gt 0 ]]; do
case "$1" in
-f | --from)
[[ $# -ge 2 ]] || fail "Missing value for $1"
from_name="$2"
shift 2
;;
-*) usage ;;
*) break ;;
esac
done
local name="${1:from_name}"
[[ -n "$name" ]] || fail "Missing project name"
local cname="dev-$name"
if ! docker_container_exists "$cname"; then
fail "Container does not exist: ${cname}. Run: dev create ..."
fi
if ! docker_container_running "$cname"; then
docker start "$cname" >/dev/null
fi
if ! command -v tmux >/dev/null 2>&1; then
echo "tmux not found; falling back to direct exec"
exec "$0" exec "$name"
fi
local image_ref
image_ref="$(docker container inspect "$cname" --format '{{ .Config.Image }}')"
IFS=' ' read -r _image_ref image_repo image_tag image_label <<<"$(parse_image_ref "$image_ref")"
local tname="dev:$name"
if ! tmux has-session -t "$tname" 2>/dev/null; then
tmux new-session -ds "$tname" -e "DEV_IMAGE=$image_label" "$0 exec \"$name\""
tmux set-option -t "$tname" default-command "$0 exec \"$name\""
fi
if [[ -n "${TMUX-}" ]]; then
tmux switch-client -t "$tname"
else
tmux attach -t "$tname"
fi
}
shorten_project_path() {
local project="$1"
# Case 1: path is under PROJECT_DIR
if [[ "$project" == "$PROJECT_DIR"* ]]; then
project="~/$PROJECT_ABBR${project#$PROJECT_DIR}"
# Case 2: path is under HOME (but not PROJECT_DIR)
elif [[ "$project" == "$HOME"* ]]; then
project="~${project#$HOME}"
fi
echo "$project"
}
cmd_list() {
{
echo "NAME|IMAGE|PROJECT|STATUS"
docker ps -a --filter "label=dev=true" \
--format '{{.Label "dev.name"}}|{{.Image}}|{{.Label "dev.project_path"}}|{{.Status}}'
} | while IFS='|' read -r fname image project status; do
# Shorten registry prefix
image="${image/$REGISTRY\//$REGISTRY_ABBR/}"
# Shorten project path
project="$(shorten_project_path "$project")"
echo "$fname|$image|$project|$status"
done | column -t -s '|'
}
cmd_stop() {
local kill_flag=0
while [[ $# -gt 0 ]]; do
case "$1" in
--kill)
kill_flag=1
shift
;;
-*) usage ;;
*) break ;;
esac
done
local name="${1:-}"
[[ -n "$name" ]] || fail "Missing project name"
local cname="dev-$name"
docker_container_exists "$cname" || fail "Container $cname does not exist"
if ((kill_flag)); then
echo "Killing container $cname..."
docker kill "$cname"
else
echo "Stopping container $cname..."
docker stop "$cname"
fi
}
cmd_rm() {
local force_flag=0
while [[ $# -gt 0 ]]; do
case "$1" in
--force | -f)
force_flag=1
shift
;;
-*) usage ;;
*) break ;;
esac
done
local name="${1:-}"
[[ -n "$name" ]] || fail "Missing project name"
local cname="dev-$name"
docker_container_exists "$cname" || fail "Container $cname does not exist"
if ((force_flag)); then
echo "Removing container $cname (force)..."
docker rm -f "$cname"
else
echo "Removing container $cname..."
docker rm "$cname"
fi
}
cmd_respawn() {
local name="${1:-}"
[[ -n "$name" ]] || fail "Missing project name"
local cname="dev-$name"
panes=$(tmux list-panes -t "$cname" -s -F "#{session_name}:#{window_index}.#{pane_index}")
for pane in $panes; do
echo "Respawning $pane..."
tmux respawn-pane -t "$pane"
done
}
cmd_test() {
echo "Script dev is working fine!"
}
main() {
local cmd="${1:-}"
shift || true
case "$cmd" in
create) cmd_create "$@" ;;
connect) cmd_connect "$@" ;;
exec) cmd_exec "$@" ;;
list) cmd_list ;;
stop) cmd_stop "$@" ;;
rm) cmd_rm "$@" ;;
respawn) cmd_respawn "$@" ;;
test) cmd_test "$@" ;;
*) usage ;;
esac
}
main "$@"

View File

@@ -1,34 +0,0 @@
#!/bin/bash
set -e
REGISTRY="registry.tomastm.com"
DEFAULT_IMAGE="base-debian"
usage() {
echo "Usage: $0 -i <image>"
exit 1
}
# Parse arguments
while getopts ":i:" opt; do
case ${opt} in
i )
IMAGE="${OPTARG}"
;;
\? )
usage
;;
esac
done
IMAGE="${IMAGE:-$DEFAULT_IMAGE}"
FULL_IMAGE_NAME="${REGISTRY}/${IMAGE}"
docker run --rm -it \
--network host \
-v "$HOME/.ssh:/home/dev/.ssh" \
-v "$PWD:/workspace" \
--init \
--entrypoint /bin/zsh \
"$FULL_IMAGE_NAME"

View File

@@ -0,0 +1,12 @@
#!/bin/bash
/home/tomas/bin/dev "$@" 2>&1
exit_code=$?
if [ $exit_code -ne 0 ]; then
echo ""
echo "Command: $*"
echo "Failed: exit $exit_code"
fi
exit $exit_code

612
config/shared/bin/flow Executable file
View File

@@ -0,0 +1,612 @@
#!/usr/bin/env bash
set -e
source "$HOME/.local/bin/barg"
# shellcheck disable=SC2034
SPEC=(
"command;flow;DevFlow CLI - Manage instances and development containers"
"note;Use 'flow <command> --help' for command-specific options"
"command;enter;Connect to a development instance via SSH"
"note;Target format: [user@]namespace@platform (e.g., 'personal@orb' or 'root@personal@orb')"
"argument;user,u;type:option;help:SSH user (overrides user in target)"
"argument;namespace,n;type:option;help:Instance namespace (overrides namespace in target)"
"argument;platform,p;type:option;help:Platform name (overrides platform in target)"
"argument;session,s;type:option;default:default;help:Development session name (default: 'default')"
"argument;no-tmux;type:flag;dest:no_tmux;default:false;help:Skip tmux attachment on connection"
"argument;dry-run,d;type:flag;dest:dry_run;default:false;help:Show SSH command without executing"
"argument;target,t;required;help:Target instance in format [user@]namespace@platform"
"argument;ssh-args;type:rest;dest:ssh_args;help:Additional SSH arguments (after --)"
"end"
"command;sync;Git tools"
"command;check;Check all projects status"
"end"
"end"
"command;dotfiles;Manage repository dotfiles and git submodules"
"command;init;Initialize and set up all submodules"
"note;Equivalent to: git submodule update --init --recursive"
"end"
"command;pull;Update all submodules to latest remote commits"
"note;Equivalent to: git submodule update --remote --recursive"
"end"
"command;urls;Synchronize submodule URLs"
"note;Equivalent to: git submodule sync --recursive"
"end"
"command;reset;Reset submodules to the recorded commits"
"note;Equivalent to: git submodule update --init --recursive --force"
"end"
"command;status;Show current submodule status"
"note;Equivalent to: git submodule status --recursive"
"end"
"command;all;Run URLs sync, initialization, and remote update in one step"
"note;Equivalent to: git submodule sync --recursive && git submodule update --init --recursive && git submodule update --remote --recursive"
"end"
"end"
"command;create;Create and start a new development container"
"argument;image,i;required;type:option;help:Container image to use (with optional tag)"
"argument;project,p;type:option;help:Path to local project directory"
"argument;name;required;help:Container name"
"end"
"command;exec;Execute a command or open a shell in a container"
"argument;name;required;help:Container name"
"argument;cmd;type:rest;help:Command to execute inside container (after --)"
"end"
"command;connect;Attach or switch to the containers tmux session"
"note;When already inside tmux, switches to the target session instead of reattaching."
"note;New tmux panes or windows in the session automatically start inside the container."
"argument;from,f;type:option;dest:name;help:Optional source container name"
"argument;name;required;help:Target container name"
"end"
"command;list;Display all development containers and their status"
"end"
"command;stop;Stop or kill a running development container"
"argument;from;type:option;dest:name;help:Optional source container name"
"argument;kill;type:flag;help:Use kill instead of graceful stop"
"argument;name;required;help:Target container name"
"end"
"command;remove,rm;Remove a development container"
"argument;from;type:option;dest:name;help:Optional source container name"
"argument;force,f;type:flag;help:Force removal of container"
"argument;name;required;help:Target container name"
"end"
"command;respawn;Restart all tmux panes for a development session"
"argument;from;type:option;dest:name;help:Optional source container name"
"argument;name;required;help:Session or container name"
"end"
"command;test;Verify that the dev script is functioning"
"argument;from;type:option;dest:name;help:Optional source container name"
"argument;name;help:Target container name"
"end"
"end"
)
DEFAULT_REGISTRY="registry.tomastm.com"
DEFAULT_TAG="latest"
PROJECT_DIR="$HOME/projects"
PROJECT_ABBR="p"
fail() {
printf 'Error: %b\n' "$*" >&2
exit 1
}
resolve_path() {
local path="${1:-$(dirname "${BASH_SOURCE[0]}")}"
if command -v realpath >/dev/null 2>&1; then
realpath "$path"
else
echo "$(cd "$(dirname "$path")" && pwd)/$(basename "$path")"
fi
}
# shellcheck disable=SC2178,SC2128
parse_image_ref() {
local input="$1"
local image_ref registry repo tag label
if [[ $input == */* ]]; then
local prefix="${input%%/*}"
if [[ "$prefix" == "docker" ]]; then
input="docker.io/library/${input#*/}"
elif [[ "$prefix" == "tm0" ]]; then
input="${DEFAULT_REGISTRY}/${input#*/}"
fi
registry="${input%%/*}"
input=${input#*/}
else
registry="$DEFAULT_REGISTRY"
fi
if [[ "${input##*/}" == *:* ]]; then
tag="${input##*:}"
input="${input%:*}"
else
tag="$DEFAULT_TAG"
fi
repo="${registry}/${input}"
repo="${repo#*/}"
image_ref="${registry}/${repo}:${tag}"
label="${registry%.*}"
label="${label##*.}/${repo##*/}"
echo "$image_ref $repo $tag $label"
}
# shellcheck disable=SC2154,SC2155
docker_container_exists() {
local cname="$(get_cname)"
docker container ls -a --format '{{.Names}}' | grep -Fqx "$cname"
}
# shellcheck disable=SC2154,SC2155
docker_container_running() {
local cname="$(get_cname)"
docker container ls --format '{{.Names}}' | grep -Fqx "$cname"
}
docker_image_present() {
local ref="$1"
docker image inspect "$ref" >/dev/null 2>&1
}
# shellcheck disable=SC2154,SC2155
get_cname() {
printf "%s" "dev-${name_arg#dev-}"
}
cmd() {
barg_usage
}
cmd_dotfiles_init() {
echo "[dotfiles] Initializing submodules..."
git submodule update --init --recursive
}
cmd_dotfiles_pull() {
echo "[dotfiles] Updating submodules to latest remote commits..."
git submodule update --remote --recursive
}
cmd_dotfiles_urls() {
echo "[dotfiles] Syncing submodule URLs..."
git submodule sync --recursive
}
cmd_dotfiles_reset() {
echo "[dotfiles] Resetting submodules to recorded commits..."
git submodule update --init --recursive --force
}
cmd_dotfiles_status() {
echo "[dotfiles] Submodule status:"
git submodule status --recursive
}
cmd_dotfiles_all() {
echo "[dotfiles] Syncing URLs..."
git submodule sync --recursive
echo "[dotfiles] Initializing submodules..."
git submodule update --init --recursive
echo "[dotfiles] Updating submodules to latest remote commits..."
git submodule update --remote --recursive
}
# shellcheck disable=SC2154,SC2155
cmd_enter() {
# VARS: user_arg, namespace_arg, platform_arg, target_arg, session_arg, no_tmux_arg, dry_run_arg, ssh_args_arg
# Do not run inside instance
if [[ -n "$DF_NAMESPACE" && -n "$DF_PLATFORM" ]]; then
fail "It is not recommended to run this command inside an instance.\nCurrently inside: $(tput bold)${DF_NAMESPACE}@${DF_PLATFORM}$(tput sgr0)"
fi
local -A CONFIG_HOST=(
[orb.host]="<namespace>@orb"
[utm.host]="<namespace>.utm.local"
[core.host]="<namespace>.core.lan"
)
local df_platform=""
local df_namespace=""
local df_user=""
# Parse target: get user, namespace, platform
if [[ "$target_arg" == *@* ]]; then
df_platform="${target_arg##*@}"
target_arg="${target_arg%@*}"
fi
if [[ "$target_arg" == *@* ]]; then
df_namespace="${target_arg##*@}"
df_user="${target_arg%@*}"
else
df_namespace="${target_arg}"
df_user="${USER}"
fi
if [[ -n "$platform_arg" ]]; then
df_platform="$platform_arg"
fi
if [[ -n "$namespace_arg" ]]; then
df_namespace="$namespace_arg"
fi
if [[ -n "$user_arg" ]]; then
df_user="$user_arg"
fi
# Resolve host, identity (maybe check what would the host be in order to use .ssh/config)
local host_config="${CONFIG_HOST[${df_platform}.host]}"
local ssh_host="${host_config//<namespace>/$df_namespace}"
if [[ -z "$ssh_host" ]]; then
fail "Invalid platform: ${df_platform}"
fi
# Build ssh cmd: ssh + identity + tmux + envs
local ssh_cmd=(ssh -tt "${df_user}@${ssh_host}")
if [[ "$no_tmux_arg" == "false" ]]; then
# TODO: instead of tmux,maybe use "flow" in order to attach to dev container too
ssh_cmd+=("tmux" "new-session" "-As" "$session_arg"
"-e" "DF_NAMESPACE=$df_namespace"
"-e" "DF_PLATFORM=$df_platform")
fi
# Run or dryrun?
if [[ "$dry_run_arg" == "true" ]]; then
echo "Dry run command:"
printf '%q ' "${ssh_cmd[@]}"
echo
exit 0
fi
exec "${ssh_cmd[@]}"
}
# shellcheck disable=SC2154,SC2155
cmd_sync_check() {
local base_dir="$HOME/projects"
local -a needs_action=()
local -a not_git=()
for repo in "$base_dir"/*; do
[ -d "$repo" ] || continue
local git_dir="$repo/.git"
if [ ! -d "$git_dir" ]; then
not_git+=("$(basename "$repo")")
continue
fi
echo "=== $(basename "$repo") ==="
cd "$repo" || continue
local action_required=0
git fetch --all --quiet || true
local branch
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "HEAD")
# --- Uncommitted or untracked changes ---
if ! git diff --quiet || ! git diff --cached --quiet; then
echo "Uncommitted changes:"
git status --short
action_required=1
elif [ -n "$(git ls-files --others --exclude-standard)" ]; then
echo "Untracked files:"
git ls-files --others --exclude-standard
action_required=1
else
echo "No uncommitted or untracked changes."
fi
# --- Unpushed commits on current branch ---
if git rev-parse --abbrev-ref "${branch}@{u}" >/dev/null 2>&1; then
local unpushed
unpushed=$(git rev-list --oneline "${branch}@{u}..${branch}")
if [ -n "$unpushed" ]; then
echo "Unpushed commits on ${branch}:"
echo "$unpushed"
action_required=1
else
echo "No unpushed commits on ${branch}."
fi
else
echo "No upstream set for ${branch}."
action_required=1
fi
# --- Unpushed branches ---
local unpushed_branches=()
while IFS= read -r b; do
if git rev-parse --abbrev-ref "${b}@{u}" >/dev/null 2>&1; then
local ahead
ahead=$(git rev-list --count "${b}@{u}..${b}")
if [ "$ahead" -gt 0 ]; then
unpushed_branches+=("$b ($ahead ahead)")
fi
else
unpushed_branches+=("$b (no upstream)")
fi
done < <(git for-each-ref --format='%(refname:short)' refs/heads)
if [ "${#unpushed_branches[@]}" -gt 0 ]; then
echo "Unpushed branches:"
printf ' %s\n' "${unpushed_branches[@]}"
action_required=1
else
echo "No unpushed branches."
fi
echo
((action_required)) && needs_action+=("$(basename "$repo")")
done
echo "=== SUMMARY ==="
if [ "${#needs_action[@]}" -gt 0 ]; then
echo "Projects needing action:"
printf ' %s\n' "${needs_action[@]}" | sort -u
else
echo "All repositories clean and synced."
fi
if [ "${#not_git[@]}" -gt 0 ]; then
echo
echo "Directories without Git repositories:"
printf ' %s\n' "${not_git[@]}" | sort -u
fi
}
# shellcheck disable=SC2154,SC2155
cmd_create() {
# VARS: name_arg, image_arg, project_arg
# Check if container name already exists
local cname="$(get_cname)"
if docker_container_exists "$cname"; then
printf -v msg 'Container already exists: "%s" (from name "%s")' "$cname" "$name_arg"
fail "$msg"
fi
# Check if project path is valid
local project_path
project_path="$(resolve_path "$project_arg")"
if [[ ! -d "$project_path" ]]; then
fail "Invalid project path: $project_path"
fi
# Check image
IFS=' ' read -r image_ref _ _ _ <<<"$(parse_image_ref "$image_arg")"
if ! docker_image_present "$image_ref"; then
printf -v msg 'Image not found locally.\nTry:\n\t- docker pull %s' "$image_ref"
fail "$msg"
fi
# Run (= create and start container)
cmd=(
docker run -d
--name "$cname"
--label dev=true
--label "dev.name=$name_arg"
--label "dev.project_path=$project_path"
--label "dev.image_ref=$image_ref"
--network host
--init # run tini as PID 1 to handle signals & reap zombies for cleaner container shutdown
-v "$project_path:/workspace"
-v /var/run/docker.sock:/var/run/docker.sock
)
[[ -d "$HOME/.ssh" ]] && cmd+=(-v "$HOME/.ssh:$CONTAINER_HOME/.ssh:ro")
[[ -f "$HOME/.npmrc" ]] && cmd+=(-v "$HOME/.npmrc:$CONTAINER_HOME/.npmrc:ro")
[[ -d "$HOME/.npm" ]] && cmd+=(-v "$HOME/.npm:$CONTAINER_HOME/.npm")
docker_gid="$(getent group docker | cut -d: -f3 || true)"
[[ -n "$docker_gid" ]] && cmd+=(--group-add "$docker_gid")
cmd+=("$image_ref" sleep infinity)
"${cmd[@]}"
printf "Created and started container: %s" "$cname"
}
# shellcheck disable=SC2154,SC2155
cmd_connect() {
# VARS: name_arg
local cname="$(get_cname)"
if ! docker_container_exists "$cname"; then
fail "Container does not exist: ${cname}. Run: dev create ..."
fi
if ! docker_container_running "$cname"; then
docker start "$cname" >/dev/null
fi
if ! command -v tmux >/dev/null 2>&1; then
echo "tmux not found; falling back to direct exec"
exec "$0" exec "$cname"
fi
local image_ref
image_ref="$(docker container inspect "$cname" --format '{{ .Config.Image }}')"
IFS=' ' read -r _image_ref _ _ image_label <<<"$(parse_image_ref "$image_ref")"
if ! tmux has-session -t "$cname" 2>/dev/null; then
tmux new-session -ds "$cname" \
-e "DF_IMAGE=$image_label" \
-e "DF_NAMESPACE=$DF_NAMESPACE" \
-e "DF_PLATFORM=$DF_PLATFORM" \
"$0 exec \"$name_arg\""
tmux set-option -t "$cname" default-command "$0 exec \"$name_arg\""
fi
if [[ -n "${TMUX-}" ]]; then
tmux switch-client -t "$cname"
else
tmux attach -t "$cname"
fi
}
# shellcheck disable=SC2154,SC2155
cmd_exec() {
# VARS: name_arg, cmd_arg
local cname="$(get_cname)"
if ! docker_container_running "$cname"; then
fail "Container $cname not running"
fi
if [[ -n "$cmd_arg" ]]; then
if [[ -t 0 ]]; then
docker exec -it "$cname" "${cmd_arg}"
else
docker exec "$cname" "${cmd_arg}"
fi
return
fi
# No command provided -> open a shell
docker exec --detach-keys "ctrl-q,ctrl-p" -it "$cname" zsh -l ||
docker exec --detach-keys "ctrl-q,ctrl-p" -it "$cname" bash -l ||
docker exec --detach-keys "ctrl-q,ctrl-p" -it "$cname" sh
}
shorten_project_path() {
local project=$1
local home=${HOME%/}
local projdir=${PROJECT_DIR%/}
# Case 1: under PROJECT_DIR
if [[ -n ${projdir} && $project == "$projdir"/* ]]; then
# shellcheck disable=SC2088
project="~/$PROJECT_ABBR${project#"$projdir"}"
# Case 2: equals HOME
elif [[ $project == "$home" ]]; then
project="~"
# Case 3: under HOME (but not PROJECT_DIR)
elif [[ $project == "$home"/* ]]; then
project="~${project#"$home"}"
fi
printf '%s\n' "$project"
}
# shellcheck disable=SC2154,SC2155
cmd_list() {
# VARS:
{
echo "NAME|IMAGE|PROJECT|STATUS"
docker ps -a --filter "label=dev=true" \
--format '{{.Label "dev.name"}}|{{.Image}}|{{.Label "dev.project_path"}}|{{.Status}}'
} | while IFS='|' read -r fname image project status; do
# Shorten registry prefix
image="${image/$REGISTRY\//$REGISTRY_ABBR/}"
# Shorten project path
project="$(shorten_project_path "$project")"
echo "$fname|$image|$project|$status"
done | column -t -s '|'
}
tmux_fallback_to_default_if_in_session() {
# If inside tmux and current session matches the given one,
# switch to or create 'default' before proceeding.
local target_session="$1"
[[ -z "${TMUX-}" ]] && return 0 # not in tmux, nothing to do
local current_session
current_session="$(tmux display-message -p '#S')"
if [[ "$current_session" == "$target_session" ]]; then
if ! tmux has-session -t default 2>/dev/null; then
tmux new-session -ds default
fi
tmux switch-client -t default
fi
}
# shellcheck disable=SC2154,SC2155
cmd_stop() {
# VARS: kill_arg name_arg
local cname
cname="$(get_cname)"
docker_container_exists "$cname" || fail "Container $cname does not exist"
if [[ "$kill_arg" == "true" ]]; then
echo "Killing container $cname..."
docker kill "$cname"
else
echo "Stopping container $cname..."
docker stop "$cname"
fi
tmux_fallback_to_default_if_in_session "$cname"
}
# shellcheck disable=SC2154,SC2155
cmd_remove() {
# VARS: force_arg name_arg
local cname
cname="$(get_cname)"
docker_container_exists "$cname" || fail "Container $cname does not exist"
if [[ "$force_arg" == "true" ]]; then
echo "Removing container $cname (force)..."
docker rm -f "$cname"
else
echo "Removing container $cname..."
docker rm "$cname"
fi
tmux_fallback_to_default_if_in_session "$cname"
}
# shellcheck disable=SC2154,SC2155
cmd_respawn() {
# VARS: name_arg
local cname
cname="$(get_cname)"
panes=$(tmux list-panes -t "$cname" -s -F "#{session_name}:#{window_index}.#{pane_index}")
for pane in $panes; do
echo "Respawning $pane..."
tmux respawn-pane -t "$pane"
done
}
# shellcheck disable=SC2154,SC2155
cmd_test() {
# VARS: name_arg
echo "Script dev is working fine!"
if [[ -n "$name_arg" ]]; then
get_cname
fi
echo
}
barg_run SPEC[@] "$@"

39
config/shared/bin/sync-theme Executable file
View File

@@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -euo pipefail
declare -A THEME=(
["ghostty.url"]="https://raw.githubusercontent.com/triimdev/invero.nvim/refs/heads/main/extras/ghostty/invero_day"
["ghostty.dir"]="$HOME/.config/ghostty/themes"
["ghostty.name"]="Invero Day"
["wezterm.url"]="https://raw.githubusercontent.com/triimdev/invero.nvim/refs/heads/main/extras/wezterm/invero_day.toml"
["wezterm.dir"]="$HOME/.config/wezterm/colors"
["wezterm.name"]="Invero Day.toml"
)
theme="${1:-}"
if [[ -z "$theme" ]]; then
echo "Usage: $0 <theme>"
echo "Available themes: $(printf '%s\n' "${!THEME[@]}" | cut -d. -f1 | sort -u | tr '\n' ' ')"
exit 1
fi
if [[ -z "${THEME[$theme.url]+x}" ]]; then
echo "Unknown theme '$theme'. Available: $(printf '%s\n' "${!THEME[@]}" | cut -d. -f1 | sort -u | tr '\n' ' ')"
exit 1
fi
url="${THEME[$theme.url]}"
dir="${THEME[$theme.dir]}"
name="${THEME[$theme.name]}"
path="${dir}/${name}"
mkdir -p "$dir"
if curl -fsSL -o "$path" "$url"; then
echo "Theme downloaded to $path"
else
echo "Failed to download theme for '$theme'."
exit 1
fi

View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
echo
awk 'BEGIN{
s="/\\/\\/\\/\\/\\"; s=s s s s s s s 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+1,1);
}
printf "\n";
}'
# --- Environment diagnostics -------------------------------------------------
echo
echo "──────────────────────────────"
echo " Environment and Tmux Details "
echo "──────────────────────────────"
echo "TERM: ${TERM}"
echo "COLORTERM: ${COLORTERM:-undefined}"
echo
if command -v tmux >/dev/null && tmux info &>/dev/null; then
echo "Tmux RGB/Tc capabilities:"
tmux info | grep -E "RGB|Tc" || echo "(none found)"
echo
echo "Tmux server terminal options:"
tmux show-options -s | grep terminal || echo "(none found)"
else
echo "Tmux not running or unavailable."
fi
# --- Underline capability test -----------------------------------------------
echo
echo "Underline styles test:"
printf '\x1b[58:2::255:0:0m' # red underline color
printf '\x1b[4:1msingle ' # single underline
printf '\x1b[4:2mdouble ' # double underline
printf '\x1b[4:3mcurly ' # curly underline
printf '\x1b[4:4mdotted ' # dotted underline
printf '\x1b[4:5mdashed ' # dashed underline
printf '\x1b[0m\n'
echo

View File

@@ -1,16 +0,0 @@
font=monospace:size=10
pad=4x0
[key-bindings]
# scrollback-up-page=Shift+Page_Up Shift+KP_Page_Up
# scrollback-up-half-page=none
# scrollback-up-line=none
# scrollback-down-page=Shift+Page_Down Shift+KP_Page_Down
# scrollback-down-half-page=none
# scrollback-down-line=none
# scrollback-home=none
# scrollback-end=none
clipboard-copy=Control+c XF86Copy
clipboard-paste=Control+v XF86Paste
[text-bindings]
\x03=Mod4+c

View File

@@ -1,22 +0,0 @@
term = xterm-256color
theme = Invero Day
# Font
font-family = "Maple Mono NF"
font-size = 13
#font-thicken = true
adjust-cell-width = -7%
adjust-cell-height = -2
# Cursor
cursor-style = block
cursor-style-blink = false
mouse-hide-while-typing = true
shell-integration-features = no-cursor
# Window
window-padding-x = 4
window-padding-y = 0
window-padding-color = extend
macos-titlebar-style = native
macos-icon = custom

View File

@@ -1,10 +1,19 @@
[init]
defaultBranch = main
[user]
name = Tomas Mirchev
email = contact@tomastm.com
[pull]
rebase = true
name = Tomas Mirchev
email = contact@tomastm.com
[core]
editor = nvim
editor = nvim
excludesfile = ~/.gitignore
[init]
defaultBranch = main
[pull]
rebase = true
[push]
default = current
autoSetupRemote = true
[remote]
pushDefault = origin
[alias]
amend = commit -a --amend --no-edit
rename = branch -m

21
config/shared/gitignore Normal file
View File

@@ -0,0 +1,21 @@
.DS_Store
*.swp
*.swo
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
.env
.env.*
build/
dist/
build/
tmp/
temp/
logs/
*.log
.cache/
coverage/
.devflow/
.dev-flow/

View File

@@ -1,161 +0,0 @@
-- Helper function for key mappings
local function 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
-- Mode-specific mapping functions
local function nmap(lhs, rhs, opts) map("n", lhs, rhs, opts) end
local function imap(lhs, rhs, opts) map("i", lhs, rhs, opts) end
local function vmap(lhs, rhs, opts) map("v", lhs, rhs, opts) end
local function tmap(lhs, rhs, opts) map("t", lhs, rhs, opts) end
vim.opt.signcolumn = "no"
-- 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,
})
-- Keymaps
nmap("<leader>q", vim.diagnostic.setloclist, { desc = "Open diagnostic [Q]uickfix list" })
imap("jk", "<Esc>", { desc = "Exit insert mode with jk" })
nmap("<Esc>", "<cmd>nohlsearch<CR>", { desc = "Clear highlights" })
-- Prevent "x" from overriding the register
nmap("x", '"_x')
-- Window Navigation
nmap("<C-h>", "<C-w>h", { desc = "Move focus to the left window" })
nmap("<C-l>", "<C-w>l", { desc = "Move focus to the right window" })
nmap("<C-j>", "<C-w>j", { desc = "Move focus to the lower window" })
nmap("<C-k>", "<C-w>k", { desc = "Move focus to the upper window" })
-- Tab management
nmap("<Leader>tn", ":tabnew<CR>", { desc = "[T]ab [N]ew" })
nmap("<Leader>tc", ":tabclose<CR>", { desc = "[T]ab [C]lose" })
nmap("<Leader>to", ":tabonly<CR>", { desc = "[T]ab [O]nly" })
nmap("<Leader>tl", ":tabnext<CR>", { desc = "[T]ab Next" })
nmap("<Leader>th", ":tabprevious<CR>", { desc = "[T]ab Previous" })
nmap("<Leader>tm.", ":tabmove +1<CR>", { desc = "[T]ab [M]ove Right" })
nmap("<Leader>tm,", ":tabmove -1<CR>", { desc = "[T]ab [M]ove Left" })
for i = 1, 9 do
nmap(string.format("<Leader>%d", i), string.format("%dgt", i), { desc = string.format("[T]ab %d", i) })
end
-- Buffer Management
nmap("<Leader>bl", ":ls<CR>", { desc = "[B]uffer [L]ist" })
nmap("<Leader>bd", ":bdelete<CR>", { desc = "[B]uffer [D]elete" })
nmap("]b", ":bnext<CR>", { desc = "[B]uffer [N]ext" })
nmap("[b", ":bprevious<CR>", { desc = "[B]uffer [P]revious" })
nmap("<Leader>bb", ":b<Space>", { desc = "[B]uffer Select" })
nmap("<Leader>bo", ":bufdo bd|1bd<CR>", { desc = "[B]uffer Delete Others" })
-- Terminal
nmap("<Leader>tet", function()
vim.cmd("terminal")
vim.cmd("startinsert")
end, { desc = "[T]erminal" })
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" })
tmap("<Esc>", "<C-\\><C-n>", { desc = "Terminal Normal Mode" })
tmap("jk", "<C-\\><C-n>", { desc = "Terminal Normal Mode" })
tmap("<C-w>", "<C-\\><C-n><C-w>", { desc = "Terminal Window Command" })

1
config/shared/nvim Submodule

Submodule config/shared/nvim added at 4419f2e5f3

View File

@@ -4,11 +4,14 @@ set -g prefix C-Space
bind C-Space send-prefix
##### General #####
set -s default-terminal "tmux-256color"
# set -s default-terminal "tmux-256color"
# set -sa terminal-overrides "$term:rgb"
set -s escape-time 10
set -s focus-events on
set -s set-clipboard on
# set -g default-command "${SHELL}"
set -g base-index 1 # window index
set -g renumber-windows on # window index
set -g history-limit 10000
@@ -17,15 +20,16 @@ set -g mouse on
set -g set-titles on
set -g set-titles-string "#S"
# set -g remain-on-exit on
set -gw pane-base-index 1 # pane index
set -gw synchronize-panes on
##### Appearance #####
set -g status-style fg=black,bg=default
set -g window-status-current-style fg=blue,bold
set -g message-style fg=blue,bg=default
set -g status-left "#[fg=blue,bold][#S] "
set -g status-right "host:#H | machine:#{?TARGET_MACHINE,#{TARGET_MACHINE},local}"
set -g status-left "#[fg=blue,bold][#{s/^dev-//:#{session_name}}] "
set -g status-right " #{?DF_IMAGE,#{DF_IMAGE} | ,}#{?DF_NAMESPACE,#{DF_NAMESPACE},#H}@#{?DF_PLATFORM,#{DF_PLATFORM},local}"
set -g status-left-length 50
set -g status-right-length 50
set -g pane-active-border-style fg=blue
@@ -56,3 +60,9 @@ bind c confirm-before -p "kill-pane \#P? (y/n)" kill-pane
##### Misc #####
bind r source-file ~/.tmux.conf \; display "Reloaded!"
unbind d
bind e detach
bind d command-prompt -I "dev " 'run-shell "/home/tomas/bin/dev-tmux-wrapper.sh %1 --from #{session_name}"'

View File

@@ -1,106 +0,0 @@
-- wezterm.lua configuration file
local wezterm = require 'wezterm'
-- This table will hold the configuration.
local config = {}
-- In newer versions of wezterm, use the config_builder which will
-- help provide clearer error messages
if wezterm.config_builder then
config = wezterm.config_builder()
end
-- Environment variables
config.term="xterm-256color"
config.set_environment_variables = {
TERM = "xterm-256color",
}
-- Font configuration
config.font = wezterm.font('JetBrainsMono Nerd Font', {weight = 'Bold'})
-- config.freetype_render_target = "HorizontalLcd"
-- config.freetype_load_flags = 'NO_HINTING'
-- config.freetype_load_target = "Light"
config.bold_brightens_ansi_colors = false
local act = wezterm.action
config.font_size = 14
-- Alacritty's offset translates to cell_width and line_height in wezterm
-- Since your offset is 0, we're keeping default values
-- Window configuration
config.window_padding = {
left = 4,
right = 4,
top = 0,
bottom = 0,
}
-- config.window_decorations = "RESIZE|TITLE|MACOS_USE_BACKGROUND_COLOR_AS_TITLEBAR_COLOR|MACOS_FORCE_ENABLE_SHADOW" -- Similar to decorations_theme_variant = "Dark"
config.window_decorations = "TITLE|RESIZE"
config.use_resize_increments = false
-- Wezterm doesn't have direct equivalents for dynamic_padding and resize_increments
-- but we can set related options
-- Keyboard bindings
config.keys = {
{key="LeftArrow", mods="SUPER|SHIFT", action=wezterm.action{MoveTabRelative=-1}},
{key="RightArrow", mods="SUPER|SHIFT", action=wezterm.action{MoveTabRelative=1}},
-- Create new window
{
key = 'n',
mods = 'CMD',
action = wezterm.action.SpawnWindow,
},
-- Jump back one word (Alt+Left)
{
key = 'LeftArrow',
mods = 'ALT',
action = wezterm.action.SendString('\x1bb'),
},
-- Jump forward one word (Alt+Right)
{
key = 'RightArrow',
mods = 'ALT',
action = wezterm.action.SendString('\x1bf'),
},
-- Move to start of line (Cmd+Left)
{
key = 'LeftArrow',
mods = 'CMD',
action = wezterm.action.SendString('\x01'),
},
-- Move to end of line (Cmd+Right)
{
key = 'RightArrow',
mods = 'CMD',
action = wezterm.action.SendString('\x05'),
},
-- Delete backwards word (Alt+Backspace)
{
key = 'Backspace',
mods = 'ALT',
action = wezterm.action.SendString('\x1b\x7f'),
},
-- Delete backwards line (Cmd+Backspace)
{
key = 'Backspace',
mods = 'CMD',
action = wezterm.action.SendString('\x15'),
},
-- Delete forwards word (Alt+Delete)
{
key = 'Delete',
mods = 'ALT',
action = wezterm.action.SendString('\x1bd'),
},
-- Delete forwards line (Cmd+Delete)
{
key = 'Delete',
mods = 'CMD',
action = wezterm.action.SendString('\x0b'),
},
}
return config

View File

@@ -1,14 +1,16 @@
export PATH="$PATH:$HOME/bin"
export PATH="$PATH:$HOME/.local/bin:$HOME/bin"
export LANG=en_US.UTF-8
export LC_CTYPE=en_US.UTF-8
export LC_COLLATE=C
KEYTIMEOUT=1
# eval "$(dircolors)"; echo "$LS_COLORS"
export LS_COLORS='rs=0:di=01;34:ln=01;33:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=00:tw=30;42:ow=34;42:st=37;44:ex=01;32'
HISTFILE=$HOME/.zsh_history
HISTSIZE=10000
SAVEHIST=10000
setopt auto_cd interactive_comments prompt_subst
setopt auto_cd interactive_comments prompt_subst share_history
setopt append_history hist_ignore_dups hist_ignore_all_dups hist_reduce_blanks
autoload -Uz compinit
@@ -34,9 +36,16 @@ bindkey '^[[B' down-line-or-beginning-search
bindkey '^[OB' down-line-or-beginning-search
bindkey '^U' backward-kill-line
# alias ls='ls --color=auto --group-directories-first'
alias ls='ls --color=auto'
if command -v nvim >/dev/null 2>&1; then
alias vim='nvim'
fi
case "$OSTYPE" in
linux*) alias ls='ls --color=auto --group-directories-first' ;;
darwin*) alias ls='ls --color=auto' ;;
esac
alias ll='ls -lF'
alias lla='ll -a'
alias ld='ls -ld */'
alias vim=nvim

View File

@@ -10,7 +10,7 @@ import shutil
DOTFILES_DIR = Path(__file__).parent
SETUPS_DIR = DOTFILES_DIR / "setups"
CONFIG_DIR = DOTFILES_DIR / "config"
CONFIG_PATH = DOTFILES_DIR / "config.json"
CONFIG_PATH = DOTFILES_DIR / "manifest.json"
def load_config():
if not CONFIG_PATH.exists():
@@ -63,8 +63,8 @@ def get_environment_packages(config, env, search_package=None):
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>'")
# if len(link_from.split("/")) != 2:
# raise ValueError("`link.from` should be '<env>/<package>'")
package["link"] = {
"from": Path(CONFIG_DIR / link_from).expanduser(),

184
manifest.json Normal file
View File

@@ -0,0 +1,184 @@
{
"template": {
"bin": {
"link": {
"from": "shared/bin",
"to": "~/bin"
}
},
"barg": {
"link": {
"from": "shared/barg-parser/barg",
"to": "~/.local/bin/barg"
}
},
"htop": {
"link": {
"from": "shared/htop",
"to": "~/.config/htop"
}
},
"git": {
"link": {
"from": "shared/git",
"to": "~/.gitconfig"
}
},
"gitignore": {
"link": {
"from": "shared/gitignore",
"to": "~/.gitignore"
}
},
"zsh": {
"link": {
"from": "shared/zsh",
"to": "~/.zshrc"
}
},
"tmux": {
"link": {
"from": "shared/tmux",
"to": "~/.tmux.conf"
}
},
"nvim": {
"link": {
"from": "shared/nvim",
"to": "~/.config/nvim"
}
}
},
"environments": {
"linux": [
{
"package": "window-tagger",
"link": {
"from": "linux/kwin_window-tagger",
"to": "~/.config/window-tagger"
}
}
],
"macos": [
"git",
"gitignore",
"zsh",
"tmux",
"nvim",
"bin",
"barg",
{
"package": "sol",
"link": {
"from": "macos/sol",
"to": "~/.config/sol"
}
},
{
"package": "borders",
"link": {
"from": "macos/borders",
"to": "~/.config/borders"
}
},
{
"package": "karabiner",
"link": {
"from": "macos/karabiner",
"to": "~/.config/karabiner"
}
},
{
"package": "linearmouse",
"link": {
"from": "macos/linearmouse",
"to": "~/.config/linearmouse"
}
},
{
"package": "rectangle",
"link-comment": "Needs manual import from config/macos/linearmouse"
},
{
"package": "wezterm",
"link": {
"from": "macos/wezterm",
"to": "~/.config/wezterm"
}
},
{
"package": "alacritty",
"link": {
"from": "macos/alacritty",
"to": "~/.config/alacritty"
}
},
{
"package": "ghostty",
"link": {
"from": "macos/ghostty",
"to": "~/.config/ghostty"
}
},
{
"package": "kitty",
"link": {
"from": "macos/kitty",
"to": "~/.config/kitty"
}
}
],
"linux-vm": [
"bin",
"barg",
"gitignore",
{
"package": "htop",
"install": "sudo apt install -y htop"
},
{
"package": "git",
"install": "sudo apt install -y git"
},
{
"package": "zsh",
"install": "sudo apt install -y zsh",
"post-link": "./scripts/linux-setup_zsh.sh"
},
{
"package": "tmux",
"install": "sudo apt install -y tmux"
},
{
"package": "nvim",
"post-install": "echo 'Neovim needs setup'"
}
],
"container": [
"bin",
"barg",
"gitignore",
{
"package": "htop",
"install": "sudo apt install -y htop"
},
{
"package": "git",
"install": "sudo apt install -y git"
},
{
"package": "zsh",
"install": "sudo apt install -y zsh",
"post-link": "./scripts/linux-setup_zsh.sh"
},
{
"package": "tmux",
"install": "sudo apt install -y tmux"
},
{
"package": "nvim",
"post-install": "echo 'Neovim needs setup'"
}
]
}
}

196
scripts/macos-defaults.sh Executable file
View File

@@ -0,0 +1,196 @@
#!/usr/bin/env bash
set -euo pipefail
# Close any open System Preferences panes, to prevent them from overriding
# settings were about to change
osascript -e 'tell application "System Preferences" to quit'
# Ask for the administrator password upfront
sudo -v
# Keep-alive: update existing `sudo` time stamp until `.macos` has finished
while true; do
sudo -n true
sleep 60
kill -0 "$$" || exit
done 2>/dev/null &
# Save to disk (not to iCloud) by default
defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false
# Disable the “Are you sure you want to open this application?” dialog
defaults write com.apple.LaunchServices LSQuarantine -bool false
# Disable Typing features
defaults write NSGlobalDomain NSAutomaticCapitalizationEnabled -bool false
defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticPeriodSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false
defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false
# Disable press-and-hold for keys in favor of key repeat
defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false
defaults write NSGlobalDomain KeyRepeat -int 2
defaults write NSGlobalDomain InitialKeyRepeat -int 15
defaults write NSGlobalDomain AppleLanguages -array "en" "es" "bg"
defaults write NSGlobalDomain AppleLocale -string "en_US@rg=eszzzz"
## Finder
# Screenshots/captures
defaults write com.apple.screencapture location -string "${HOME}/Pictures/Screenshots"
defaults write com.apple.screencapture style -string "display"
defaults write com.apple.screencapture target -string "file"
defaults write com.apple.screencapture video -int 1
# Finder
# Interface elements
defaults write com.apple.finder ShowPathbar -bool true
defaults write com.apple.finder ShowStatusBar -bool true
defaults write com.apple.finder ShowSidebar -bool true
defaults write com.apple.finder ShowRecentTags -bool false
# View and sorting
defaults write com.apple.finder FXPreferredViewStyle -string "Nlsv"
defaults write com.apple.finder FXPreferredSearchViewStyle -string "Nlsv"
defaults write com.apple.finder _FXSortFoldersFirst -bool true
defaults write com.apple.finder FXPreferredGroupBy -string "None"
defaults write com.apple.finder FXDefaultSearchScope -string "SCcf"
# Behavior
defaults write com.apple.finder NewWindowTarget -string "PfHm"
defaults write com.apple.finder FXOpenFoldersInTabs -bool true
defaults write com.apple.finder FXRemoveOldTrashItems -bool false
defaults write com.apple.finder FXShowAllExtensions -bool true
defaults write com.apple.finder FXEnableExtensionChangeWarning -bool true
defaults write com.apple.finder FXRemoveICloudDriveWarning -bool true
defaults write com.apple.finder FXWarnBeforeEmptyingTrash -bool true
# Desktop icons (none)
defaults write com.apple.finder ShowHardDrivesOnDesktop -bool false
defaults write com.apple.finder ShowExternalHardDrivesOnDesktop -bool false
defaults write com.apple.finder ShowRemovableMediaOnDesktop -bool false
defaults write com.apple.finder ShowConnectedServersOnDesktop -bool false
# Tags
defaults write com.apple.finder FavoriteTagNames -array
# iCloud
defaults write com.apple.finder FXICloudDriveEnabled -bool false
# Finder: show all filename extensions
defaults write NSGlobalDomain AppleShowAllExtensions -bool true
# Avoid creating .DS_Store files on network or USB volumes
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true
## Dock
#!/bin/bash
set -euo pipefail
# Reset preferences
# rm -f ~/Library/Preferences/com.apple.dock.plist
# Reset Dock layout
defaults write com.apple.dock persistent-apps -array
defaults write com.apple.dock persistent-others -array
# Basic Dock preferences
defaults write com.apple.dock autohide -bool true
defaults write com.apple.dock autohide-delay -float 0
defaults write com.apple.dock autohide-time-modifier -float 0.4
defaults write com.apple.dock enterMissionControlByTopWindowDrag -bool false
defaults write com.apple.dock expose-group-apps -bool true
defaults write com.apple.dock mineffect -string "scale"
defaults write com.apple.dock minimize-to-application -bool false
defaults write com.apple.dock orientation -string "bottom"
defaults write com.apple.dock show-process-indicators -bool false
defaults write com.apple.dock show-recents -bool false
defaults write com.apple.dock showAppExposeGestureEnabled -bool true
defaults write com.apple.dock showDesktopGestureEnabled -bool false
defaults write com.apple.dock showLaunchpadGestureEnabled -bool false
defaults write com.apple.dock tilesize -int 38
# Add Brave Browser
defaults write com.apple.dock persistent-apps -array-add \
"<dict>
<key>tile-data</key>
<dict>
<key>file-data</key>
<dict>
<key>_CFURLString</key>
<string>/Applications/Brave Browser.app</string>
<key>_CFURLStringType</key>
<integer>0</integer>
</dict>
</dict>
<key>tile-type</key>
<string>file-tile</string>
</dict>"
# Add Ghostty
defaults write com.apple.dock persistent-apps -array-add \
"<dict>
<key>tile-data</key>
<dict>
<key>file-data</key>
<dict>
<key>_CFURLString</key>
<string>/Applications/Ghostty.app</string>
<key>_CFURLStringType</key>
<integer>0</integer>
</dict>
</dict>
<key>tile-type</key>
<string>file-tile</string>
</dict>"
# Add Screenshots directory (display as folder, show as grid)
defaults write com.apple.dock persistent-others -array-add \
"<dict>
<key>tile-data</key>
<dict>
<key>displayas</key>
<integer>1</integer>
<key>showas</key>
<integer>2</integer>
<key>file-data</key>
<dict>
<key>_CFURLString</key>
<string>/Users/tomas/Pictures/Screenshots</string>
<key>_CFURLStringType</key>
<integer>0</integer>
</dict>
</dict>
<key>tile-type</key>
<string>directory-tile</string>
</dict>"
# Add Downloads directory (display as folder, show as grid)
defaults write com.apple.dock persistent-others -array-add \
"<dict>
<key>tile-data</key>
<dict>
<key>displayas</key>
<integer>1</integer>
<key>showas</key>
<integer>2</integer>
<key>file-data</key>
<dict>
<key>_CFURLString</key>
<string>/Users/tomas/Downloads</string>
<key>_CFURLStringType</key>
<integer>0</integer>
</dict>
</dict>
<key>tile-type</key>
<string>directory-tile</string>
</dict>"
# Apply changes
killall Finder &>/dev/null
killall Dock &>/dev/null
echo "Setup complete."

View File

@@ -14,10 +14,6 @@ fi
NEW_HOSTNAME="$1"
if ! sudo -v; then
echo "Sudo access required. Exiting."
exit 1
fi
mkdir ~/projects
# /bin/bash ./scripts/linux-setup_sudoers.sh