# Configs My current "stack" consists of Ghostty, Neovim, Tmux, and Obsidian. ### Ghostty My config for my terminal is pretty minimal - the font I'm using is [ComicMono](https://dtinth.github.io/comic-mono-font/). ```config.txt font-size = 16 theme = abernathy font-family = "Comic Mono" font-feature = -liga ``` ### Neovim My LazyVim setup, built from [Jon Gjengset's](https://www.youtube.com/c/JonGjengset) config. ```init.lua -- always set leader first! vim.keymap.set("n", "<Space>", "<Nop>", { silent = true }) vim.g.mapleader = " " ------------------------------------------------------------------------------- -- -- preferences -- ------------------------------------------------------------------------------- -- never ever folding vim.opt.foldenable = false vim.opt.foldmethod = 'manual' vim.opt.foldlevelstart = 99 -- very basic "continue indent" mode (autoindent) is always on in neovim -- could try smartindent/cindent, but meh. -- vim.opt.cindent = true -- XXX -- vim.opt.cmdheight = 2 -- vim.opt.completeopt = 'menuone,noinsert,noselect' -- not setting updatedtime because I use K to manually trigger hover effects -- and lowering it also changes how frequently files are written to swap. -- vim.opt.updatetime = 300 -- if key combos seem to be "lagging" -- http://stackoverflow.com/questions/2158516/delay-before-o-opens-a-new-line -- vim.opt.timeoutlen = 300 -- keep more context on screen while scrolling vim.opt.scrolloff = 5 -- never show me line breaks if they're not there vim.opt.wrap = false -- always draw sign column. prevents buffer moving when adding/deleting sign vim.opt.signcolumn = 'yes' -- sweet sweet relative line numbers vim.opt.relativenumber = true -- and show the absolute line number for the current line vim.opt.number = true -- keep current content top + left when splitting vim.opt.splitright = true vim.opt.splitbelow = true -- infinite undo! -- NOTE: ends up in ~/.local/state/nvim/undo/ vim.opt.undofile = true --" Decent wildmenu -- in completion, when there is more than one match, -- list all matches, and only complete to longest common match vim.opt.wildmode = 'list:longest' -- when opening a file with a command (like :e), -- don't suggest files like there: vim.opt.wildignore = '.hg,.svn,*~,*.png,*.jpg,*.gif,*.min.js,*.swp,*.o,vendor,dist,_site' vim.opt.shiftwidth = 4 vim.opt.softtabstop = 4 vim.opt.tabstop = 4 vim.opt.expandtab = false -- case-insensitive search/replace vim.opt.ignorecase = true -- unless uppercase in search term vim.opt.smartcase = true -- never ever make my terminal beep vim.opt.vb = true -- more useful diffs (nvim -d) --- by ignoring whitespace vim.opt.diffopt:append('iwhite') --- and using a smarter algorithm --- https://vimways.org/2018/the-power-of-diff/ --- https://stackoverflow.com/questions/32365271/whats-the-difference-between-git-diff-patience-and-git-diff-histogram --- https://luppeng.wordpress.com/2020/10/10/when-to-use-each-of-the-git-diff-algorithms/ vim.opt.diffopt:append('algorithm:histogram') vim.opt.diffopt:append('indent-heuristic') -- show a column at 100 characters as a guide for long lines vim.opt.colorcolumn = '100' --- except in Rust where the rule is 100 characters vim.api.nvim_create_autocmd('Filetype', { pattern = 'rust', command = 'set colorcolumn=100' }) -- show more hidden characters -- also, show tabs nicer vim.opt.listchars = 'tab:^ ,nbsp:¬,extends:»,precedes:«,trail:•' ------------------------------------------------------------------------------- -- -- hotkeys -- ------------------------------------------------------------------------------- -- quick-open vim.keymap.set('', '<C-p>', '<cmd>Files<cr>') -- search buffers vim.keymap.set('n', '<leader>;', '<cmd>Buffers<cr>') -- quick-save -- vim.keymap.set('n', '<leader>w', '<cmd>w<cr>') -- make missing : less annoying vim.keymap.set('n', ';', ':') -- Ctrl+j and Ctrl+k as Esc vim.keymap.set('n', '<C-j>', '<Esc>') vim.keymap.set('i', '<C-j>', '<Esc>') vim.keymap.set('v', '<C-j>', '<Esc>') vim.keymap.set('s', '<C-j>', '<Esc>') vim.keymap.set('x', '<C-j>', '<Esc>') vim.keymap.set('c', '<C-j>', '<Esc>') vim.keymap.set('o', '<C-j>', '<Esc>') vim.keymap.set('l', '<C-j>', '<Esc>') vim.keymap.set('t', '<C-j>', '<Esc>') -- Ctrl-j is a little awkward unfortunately: -- https://github.com/neovim/neovim/issues/5916 -- So we also map Ctrl+k vim.keymap.set('n', '<C-k>', '<Esc>') vim.keymap.set('i', '<C-k>', '<Esc>') vim.keymap.set('v', '<C-k>', '<Esc>') vim.keymap.set('s', '<C-k>', '<Esc>') vim.keymap.set('x', '<C-k>', '<Esc>') vim.keymap.set('c', '<C-k>', '<Esc>') vim.keymap.set('o', '<C-k>', '<Esc>') vim.keymap.set('l', '<C-k>', '<Esc>') vim.keymap.set('t', '<C-k>', '<Esc>') -- Ctrl+h to stop searching vim.keymap.set('v', '<C-h>', '<cmd>nohlsearch<cr>') vim.keymap.set('n', '<C-h>', '<cmd>nohlsearch<cr>') -- Jump to start and end of line using the home row keys vim.keymap.set('', 'H', '^') vim.keymap.set('', 'L', ') -- Neat X clipboard integration -- <leader>p will paste clipboard into buffer vim.keymap.set('n', '<leader>p', '<cmd>read !pbpaste<cr>') -- <leader>c will copy entire buffer into clipboard vim.keymap.set('n', '<leader>c', '<cmd>%w !pbcopy<cr><cr>') -- <leader><leader> toggles between buffers vim.keymap.set('n', '<leader><leader>', '<c-^>') -- <leader>, shows/hides hidden characters vim.keymap.set('n', '<leader>,', ':set invlist<cr>') -- always center search results vim.keymap.set('n', 'n', 'nzz', { silent = true }) vim.keymap.set('n', 'N', 'Nzz', { silent = true }) vim.keymap.set('n', '*', '*zz', { silent = true }) vim.keymap.set('n', '#', '#zz', { silent = true }) vim.keymap.set('n', 'g*', 'g*zz', { silent = true }) -- "very magic" (less escaping needed) regexes by default vim.keymap.set('n', '?', '?\\v') vim.keymap.set('n', '/', '/\\v') vim.keymap.set('c', '%s/', '%sm/') -- open new file adjacent to current file vim.keymap.set('n', '<leader>o', ':e <C-R>=expand("%:p:h") . "/" <cr>') -- no arrow keys --- force yourself to use the home row vim.keymap.set('n', '<up>', '<nop>') vim.keymap.set('n', '<down>', '<nop>') vim.keymap.set('i', '<up>', '<nop>') vim.keymap.set('i', '<down>', '<nop>') vim.keymap.set('i', '<left>', '<nop>') vim.keymap.set('i', '<right>', '<nop>') -- let the left and right arrows be useful: they can switch buffers vim.keymap.set('n', '<left>', ':bp<cr>') vim.keymap.set('n', '<right>', ':bn<cr>') -- make j and k move by visual line, not actual line, when text is soft-wrapped vim.keymap.set('n', 'j', 'gj') vim.keymap.set('n', 'k', 'gk') -- handy keymap for replacing up to next _ (like in variable names) vim.keymap.set('n', '<leader>m', 'ct_') -- F1 is pretty close to Esc, so you probably meant Esc vim.keymap.set('', '<F1>', '<Esc>') vim.keymap.set('i', '<F1>', '<Esc>') ------------------------------------------------------------------------------- -- -- autocommands -- ------------------------------------------------------------------------------- -- highlight yanked text vim.api.nvim_create_autocmd( 'TextYankPost', { pattern = '*', command = 'silent! lua vim.highlight.on_yank({ timeout = 500 })' } ) -- jump to last edit position on opening file vim.api.nvim_create_autocmd( 'BufReadPost', { pattern = '*', callback = function(ev) if vim.fn.line("'\"") > 1 and vim.fn.line("'\"") <= vim.fn.line("quot;) then -- except for in git commit messages -- https://stackoverflow.com/questions/31449496/vim-ignore-specifc-file-in-autocommand if not vim.fn.expand('%:p'):find('.git', 1, true) then vim.cmd('exe "normal! g\'\\""') end end end } ) -- prevent accidental writes to buffers that shouldn't be edited vim.api.nvim_create_autocmd('BufRead', { pattern = '*.orig', command = 'set readonly' }) vim.api.nvim_create_autocmd('BufRead', { pattern = '*.pacnew', command = 'set readonly' }) -- leave paste mode when leaving insert mode (if it was on) vim.api.nvim_create_autocmd('InsertLeave', { pattern = '*', command = 'set nopaste' }) -- help filetype detection (add as needed) --vim.api.nvim_create_autocmd('BufRead', { pattern = '*.ext', command = 'set filetype=someft' }) -- correctly classify mutt buffers local email = vim.api.nvim_create_augroup('email', { clear = true }) vim.api.nvim_create_autocmd({ 'BufNewFile', 'BufRead' }, { pattern = '/tmp/mutt*', group = email, command = 'setfiletype mail', }) -- also, produce "flowed text" wrapping -- https://brianbuccola.com/line-breaks-in-mutt-and-vim/ vim.api.nvim_create_autocmd('Filetype', { pattern = 'mail', group = email, command = 'setlocal formatoptions+=w', }) -- shorter columns in text because it reads better that way local text = vim.api.nvim_create_augroup('text', { clear = true }) for _, pat in ipairs({'text', 'markdown', 'mail', 'gitcommit'}) do vim.api.nvim_create_autocmd('Filetype', { pattern = pat, group = text, command = 'setlocal spell tw=72 colorcolumn=73', }) end --- tex has so much syntax that a little wider is ok vim.api.nvim_create_autocmd('Filetype', { pattern = 'tex', group = text, command = 'setlocal spell tw=80 colorcolumn=81', }) --- no red highlight on tab vim.cmd("highlight! link goSpaceError NONE") -- TODO: no autocomplete in text -- copy to system clipboard vim.opt.clipboard:append("unnamedplus") -- Enforce formatoptions globally after everything else vim.api.nvim_create_autocmd('BufEnter', { pattern = '*', callback = function() vim.opt.formatoptions:remove({ 'c', 'r', 'o' }) end, }) ------------------------------------------------------------------------------- -- -- plugin configuration -- ------------------------------------------------------------------------------- -- first, grab the manager -- https://github.com/folke/lazy.nvim local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" if not vim.loop.fs_stat(lazypath) then vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", -- latest stable release lazypath, }) end if vim.fn.has('nvim-0.5') == 1 then vim.lsp.set_log_level("warn") end vim.opt.rtp:prepend(lazypath) -- then, setup! require("lazy").setup({ -- main color scheme { "scottmckendry/cyberdream.nvim", lazy = false, priority = 1000, config = function() require("cyberdream").setup({ transparent = false, italic_comments = true, theme = { highlights = { Comment = { fg = "#ff8000", bg = "NONE", italic = true }, -- Neon/Bright Orange }, }, }) vim.cmd("colorscheme cyberdream") end, }, -- nice bar at the bottom { 'itchyny/lightline.vim', lazy = false, -- also load at start since it's UI config = function() -- no need to also show mode in cmd line when we have bar vim.o.showmode = false vim.g.lightline = { active = { left = { { 'mode', 'paste' }, { 'readonly', 'filename', 'modified' } }, right = { { 'lineinfo' }, { 'percent' }, { 'fileencoding', 'filetype' } }, }, component_function = { filename = 'LightlineFilename' }, } function LightlineFilenameInLua(opts) if vim.fn.expand('%:t') == '' then return '[No Name]' else return vim.fn.getreg('%') end end -- https://github.com/itchyny/lightline.vim/issues/657 vim.api.nvim_exec( [[ function! g:LightlineFilename() return v:lua.LightlineFilenameInLua() endfunction ]], true ) end }, -- quick navigation { 'ggandor/leap.nvim', config = function() require('leap').create_default_mappings() end }, -- better % { 'andymass/vim-matchup', config = function() vim.g.matchup_matchparen_offscreen = { method = "popup" } end }, -- auto-cd to root of git project -- 'airblade/vim-rooter' { 'notjedi/nvim-rooter.lua', config = function() require('nvim-rooter').setup() end }, -- fzf support for ^p { 'junegunn/fzf.vim', dependencies = { { 'junegunn/fzf', build = './install --all' }, }, config = function() -- stop putting a giant window over my editor vim.g.fzf_layout = { down = '~20%' } -- when using :Files, pass the file list through -- -- https://github.com/jonhoo/proximity-sort -- -- to prefer files closer to the current file. function list_cmd() local base = vim.fn.fnamemodify(vim.fn.expand('%'), ':h:.:S') if base == '.' then -- if there is no current file, -- proximity-sort can't do its thing return 'fd --type file --follow' else return vim.fn.printf('fd --type file --follow | proximity-sort %s', vim.fn.shellescape(vim.fn.expand('%'))) end end vim.api.nvim_create_user_command('Files', function(arg) vim.fn['fzf#vim#files'](arg.qargs, { source = list_cmd(), options = '--tiebreak=index' }, arg.bang) end, { bang = true, nargs = '?', complete = "dir" }) end }, { 'windwp/nvim-autopairs', event = "InsertEnter", config = true, }, -- LSP { 'neovim/nvim-lspconfig', config = function() -- Setup language servers. local lspconfig = require('lspconfig') -- Rust lspconfig.rust_analyzer.setup { -- Server-specific settings. See `:help lspconfig-setup` settings = { ["rust-analyzer"] = { cargo = { allFeatures = true, }, imports = { group = { enable = false, }, }, completion = { postfix = { enable = false, }, }, }, }, } -- Java LSP local jdtls_path = "/opt/homebrew/bin/jdtls" local home = os.getenv("HOME") local workspace_dir = home .. "/workspace/java/" .. vim.fn.fnamemodify(vim.fn.getcwd(), ":p:h:t") local root_dir = require('lspconfig').util.root_pattern("pom.xml", "build.gradle", ".git") require('lspconfig').jdtls.setup { cmd = { jdtls_path, "-data", workspace_dir }, root_dir = root_dir, settings = { java = { format = { enabled = true, settings = { profile = "GoogleStyle", }, }, eclipse = { downloadSources = true, }, maven = { downloadSources = true, }, }, }, } -- Bash LSP local configs = require 'lspconfig.configs' if not configs.bash_lsp and vim.fn.executable('bash-language-server') == 1 then configs.bash_lsp = { default_config = { cmd = { 'bash-language-server', 'start' }, filetypes = { 'sh' }, root_dir = require('lspconfig').util.find_git_ancestor, init_options = { settings = { args = {} } } } } end if configs.bash_lsp then lspconfig.bash_lsp.setup {} end -- Go LSP setup lspconfig.gopls.setup { cmd = {"gopls"}, filetypes = {"go", "gomod", "gowork", "gotmpl"}, root_dir = lspconfig.util.root_pattern("go.work", "go.mod", ".git"), settings = { gopls = { analyses = { unusedparams = true, }, staticcheck = true, gofumpt = true, }, }, } -- Python LSP setup (pyright) lspconfig.pyright.setup { settings = { python = { analysis = { autoSearchPaths = true, diagnosticMode = "workspace", useLibraryCodeForTypes = true } } } } -- C LSP setup (clangd) lspconfig.clangd.setup { cmd = { "clangd" }, filetypes = { "c", "cc", "cpp", "objc", "objcpp", "h" }, root_dir = lspconfig.util.root_pattern( '.clangd', '.clang-tidy', '.clang-format', 'compile_commands.json', 'compile_flags.txt', '.git' ), on_attach = function(client, bufnr) -- Use default signature help behavior vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with( vim.lsp.handlers.signature_help, { border = "rounded" } ) end, } -- Java LSP (jdtls) lspconfig.jdtls.setup { cmd = { 'jdtls' }, root_dir = lspconfig.util.root_pattern(".git", "pom.xml", "build.gradle", ".project"), settings = { java = { format = { enabled = true, settings = { profile = "GoogleStyle", }, }, }, }, } -- Scala LSP (Metals) lspconfig.metals.setup { filetypes = {"scala", "sbt"}, -- Set the root directory pattern. root_dir = lspconfig.util.root_pattern("build.sbt", ".git", "pom.xml", "build.gradle"), -- Commane to start Metals. Make sure 'metals-run' is in your PATH or provide the full path. cmd = {"metals"}, } -- Global mappings. -- See `:help vim.diagnostic.*` for documentation on any of the below functions vim.keymap.set('n', '<leader>e', vim.diagnostic.open_float) vim.keymap.set('n', '[d', vim.diagnostic.goto_prev) vim.keymap.set('n', ']d', vim.diagnostic.goto_next) vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist) -- Use LspAttach autocommand to only map the following keys -- after the language server attaches to the current buffer vim.api.nvim_create_autocmd('LspAttach', { group = vim.api.nvim_create_augroup('UserLspConfig', {}), callback = function(ev) -- Enable completion triggered by <c-x><c-o> vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc' -- Buffer local mappings. -- See `:help vim.lsp.*` for documentation on any of the below functions local opts = { buffer = ev.buf } vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts) vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts) vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts) vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts) vim.keymap.set('n', '<C-k>', vim.lsp.buf.signature_help, opts) vim.keymap.set('n', '<leader>wa', vim.lsp.buf.add_workspace_folder, opts) vim.keymap.set('n', '<leader>wr', vim.lsp.buf.remove_workspace_folder, opts) vim.keymap.set('n', '<leader>wl', function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end, opts) --vim.keymap.set('n', '<space>D', vim.lsp.buf.type_definition, opts) vim.keymap.set('n', '<leader>r', vim.lsp.buf.rename, opts) vim.keymap.set({ 'n', 'v' }, '<leader>a', vim.lsp.buf.code_action, opts) vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts) vim.keymap.set('n', '<leader>f', function() vim.lsp.buf.format { async = true } end, opts) local client = vim.lsp.get_client_by_id(ev.data.client_id) -- When https://neovim.io/doc/user/lsp.html#lsp-inlay_hint stabilizes -- *and* there's some way to make it only apply to the current line. -- if client.server_capabilities.inlayHintProvider then -- vim.lsp.inlay_hint(ev.buf, true) -- end end, }) end }, -- LSP-based code-completion { "hrsh7th/nvim-cmp", -- load cmp on InsertEnter event = "InsertEnter", -- these dependencies will only be loaded when cmp loads -- dependencies are always lazy-loaded unless specified otherwise dependencies = { 'neovim/nvim-lspconfig', "hrsh7th/cmp-nvim-lsp", "hrsh7th/cmp-buffer", "hrsh7th/cmp-path", }, config = function() local cmp = require'cmp' cmp.setup({ snippet = { -- REQUIRED by nvim-cmp. get rid of it once we can expand = function(args) vim.fn["vsnip#anonymous"](args.body) end, }, mapping = cmp.mapping.preset.insert({ ['<C-b>'] = cmp.mapping.scroll_docs(-4), ['<C-f>'] = cmp.mapping.scroll_docs(4), ['<C-Space>'] = cmp.mapping.complete(), ['<C-e>'] = cmp.mapping.abort(), -- Accept currently selected item. -- Set `select` to `false` to only confirm explicitly selected items. ['<CR>'] = cmp.mapping.confirm({ select = true }), }), sources = cmp.config.sources({ { name = 'nvim_lsp' }, }, { { name = 'path' }, }), experimental = { ghost_text = true, }, view = { entries = "native" -- Use native view }, }) -- Enable completing paths in : cmp.setup.cmdline(':', { sources = cmp.config.sources({ { name = 'path' } }) }) end }, -- treesitter { 'nvim-treesitter/nvim-treesitter', run = ':TSUpdate', config = function() require('nvim-treesitter.configs').setup({ ensure_installed = { "bash", "c", "cpp", "go", "javascript", "json", "lua", "python", "rust", "yaml", "markdown" }, incremental_selection = { enable = true, keymaps = { init_selection = "gnn", node_incremental = "grn", scope_incremental = "grc", node_decremental = "grm", }, }, }) end, }, -- inline function signatures { "ray-x/lsp_signature.nvim", event = "VeryLazy", opts = {}, config = function(_, opts) -- Get signatures (and _only_ signatures) when in argument lists. require "lsp_signature".setup({ floating_window = false, hint_enable = true, hint_prefix = "🦧 ", doc_lines = 0, handler_opts = { border = "none" }, }) end }, -- language support -- terraform { 'hashivim/vim-terraform', ft = { "terraform" }, }, -- svelte { 'evanleck/vim-svelte', ft = { "svelte" }, }, -- toml 'cespare/vim-toml', -- yaml { "cuducos/yaml.nvim", ft = { "yaml" }, dependencies = { "nvim-treesitter/nvim-treesitter", }, }, -- rust { 'rust-lang/rust.vim', ft = { "rust" }, config = function() vim.g.rustfmt_autosave = 1 vim.g.rustfmt_emit_files = 1 vim.g.rustfmt_fail_silently = 0 vim.g.rust_clip_command = 'pbcopy' end }, -- fish 'khaveesh/vim-fish-syntax', -- markdown { 'plasticboy/vim-markdown', ft = { "markdown" }, dependencies = { 'godlygeek/tabular', }, config = function() -- never ever fold! vim.g.vim_markdown_folding_disabled = 1 -- support front-matter in .md files vim.g.vim_markdown_frontmatter = 1 -- 'o' on a list item should insert at same level vim.g.vim_markdown_new_list_item_indent = 0 -- don't add bullets when wrapping: -- https://github.com/preservim/vim-markdown/issues/232 vim.g.vim_markdown_auto_insert_bullets = 0 end }, -- Go { 'fatih/vim-go', ft = { "go" }, config = function() vim.g.go_fmt_autosave = 1 vim.g.go_fmt_command = "goimports" vim.api.nvim_create_autocmd("BufWritePre", { pattern = "*.go", callback = function() vim.lsp.buf.format() end, }) end }, -- Python { 'vim-python/python-syntax', ft = { "python" }, config = function() ---vim.g.python_highlight_all = 1 end }, -- C { 'vim-jp/vim-cpp', ft = { "c", "cpp" }, }, }) ``` ### Tmux ```.tmux.conf set -g @plugin 'tmux-plugins/tpm' set -g @plugin 'tmux-plugins/tmux-resurrect' set -g @resurrect-save on # set scroll history to 100,000 lines set-option -g history-limit 100000 # modern colors set -g default-terminal "xterm-256color" set -ga terminal-overrides ",alacritty:Tc" #mouse mode set -g mouse on # unbind the prefix and bind it to Ctrl-s (not ^a since that is main tmux) unbind C-b set -g prefix C-s bind C-s send-prefix # Avoid ESC delay set -s escape-time 0 # Fix titlebar set -g set-titles on set -g set-titles-string "#T" # VIM mode set -g mode-keys vi bind-key -T copy-mode-vi v send -X begin-selection bind-key -T copy-mode-vi y send -X copy-selection # Switch to next window bind -r n next-window # Switch to previous window bind -r p previous-window # Move between panes with vi keys bind h select-pane -L bind j select-pane -D bind k select-pane -U bind l select-pane -R ###################### ### DESIGN CHANGES ### ###################### # Avoid date/time taking up space set -g status-right ' <REMOTE> ' set -g status-right-length 9 # Colors (gruvbox dark base16) # default statusbar colors # but a shade darker to show remote set-option -g status-style "fg=#bdae93,bg=#1c1816" # default window title colors set-window-option -g window-status-style "fg=#bdae93,bg=default" # active window title colors set-window-option -g window-status-current-style "fg=#fabd2f,bg=default" # pane border set-option -g pane-border-style "fg=#3c3836" set-option -g pane-active-border-style "fg=#504945" # message text set-option -g message-style "fg=#d5c4a1,bg=#3c3836" # pane number display set-option -g display-panes-active-colour "#b8bb26" set-option -g display-panes-colour "#fabd2f" # clock set-window-option -g clock-mode-colour "#b8bb26" # copy mode highligh set-window-option -g mode-style "fg=#bdae93,bg=#504945" # bell set-window-option -g window-status-bell-style "fg=#3c3836,bg=#fb4934" run '~/.tmux/plugins/tpm/tpm' ``` ### Obsidian This website is running with Obsidian Publish with some custom CSS, borrowed from [char.blog](https://char.blog). ```publish.css @import url('https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400..700;1,400..700&display=swap'); body { font-family: 'Lora', serif; --font-default: 'Lora', serif; /* Font sizes */ --font-text-size: 16px; --font-small: 13px; --font-smaller: 11px; --font-smallest: 10px; --font-inputs: 13px; /* Font weights */ --normal-weight: 400; --bold-weight: 600; --link-weight: inherit; /* Headings */ --page-title-weight: 500; --page-title-line-height: 1.1; --h1: 1.25em; --h2: 1.1em; --h3: 1.05em; --h4: 1em; --h5: 0.85em; --h6: 0.85em; --h1-weight: 600; --h2-weight: 600; --h3-weight: 600; --h4-weight: 500; --h5-weight: 500; --h6-weight: 400; --h1-variant: normal; --h2-variant: normal; --h3-variant: normal; --h4-variant: normal; --h5-variant: small-caps; --h6-variant: small-caps; --h1-style: normal; --h2-style: normal; --h3-style: normal; --h4-style: normal; --h5-style: normal; --h6-style: normal; /* Cards */ --cards-min-width: 180px; --cards-max-width: 1fr; --cards-mobile-width: 180px; --cards-image-height: 400px; --cards-padding: 1.2em; --cards-image-fit: contain; --cards-background: transparent; --cards-border-width: 1px; --cards-aspect-ratio: auto; --cards-columns: repeat(auto-fit, minmax(var(--cards-min-width), var(--cards-max-width))); /* Images */ --image-radius: 8px; --image-grid-fit: cover; --image-grid-background: transparent; --img-grid-gap: 0.5rem; /* Line widths */ --icon-muted: 0.5; --border-width: 1px; --folding-offset: 16px; --nested-padding: 30px; /* Quotes and transclusions */ --list-padding: 2em; /* List padding */ --list-spacing: 0.075em; /* Space between list items */ } /* Mobile */ @media (max-width:400pt) { body { --cards-min-width: var(--cards-mobile-width); --img-grid-gap: 0.25rem; } } .site-footer a { display: none; } /* Default color scheme */ .theme-light, .theme-dark { --red: #d04255; --yellow: #e5b567; --green: #a8c373; --orange: #e57e43; --cyan: #73bbb2; --blue: #6c99bb; --purple: #9e86c8; --pink: #b05279; } .theme-light { /* Background Content Section */ --bg1: #ffffff; /* Background Left Menu and Mid Section */ --bg2: #f7f7f7; /* Border Lines and breaklines */ --ui1: #e1e1e1; /* Border Hover */ --ui2: #d4d4d4; /*Content Text*/ --tx1: #171717; /*Right Hand Side and tags*/ --tx2: #d04255; /*icons*/ --tx3: #262626; /*Link*/ --ax1: #d04255; /*link hover*/ --ax2: #cf374b; /*quote line color*/ --ax3: #737373; --hl1: hsla(0, 0%, 0%, 8%); --mono100: #000000; --mono0: #ffffff; } .theme-dark { /* Background Content Section */ --bg1: #000000; /* Background Left Menu and Mid Section */ --bg2: #080808; /* Border Lines and breaklines */ --ui1: #1e1e1e; /* Border Hover */ --ui2: #2b2b2b; /*Content Text*/ --tx1: #e8e8e8; /*Right Hand Side and tags*/ --tx2: #d04255; /*icons*/ --tx3: #262626; /*Link*/ --ax1: #d04255; /*link hover*/ --ax2: #cf374b; /*quote line color*/ --ax3: #8c8c8c; --hl1: hsla(0, 0%, 100%, 8%); --mono100: #ffffff; --mono0: #000000; } .theme-dark, .theme-light { --h1-color: var(--text-normal); --h2-color: var(--text-normal); --h3-color: var(--text-normal); --h4-color: var(--text-normal); --h5-color: var(--text-normal); --h6-color: var(--text-muted) } .theme-dark, .theme-light { --background-primary: var(--bg1); --background-primary-alt: var(--bg2); --background-secondary: var(--bg2); --background-secondary-alt: var(--bg1); --background-tertiary: var(--bg3); --background-table-rows: var(--bg2); --background-modifier-form-field: var(--bg1); --background-modifier-form-field-highlighted: var(--bg1); --background-modifier-accent: var(--ax3); --background-modifier-border: var(--ui1); --background-modifier-border-hover: var(--ui2); --background-modifier-border-focus: var(--ui3); --background-modifier-success: var(--color-green); --background-divider: var(--ui1); --interactive-hover: var(--ui1); --interactive-accent: var(--ax3); --interactive-accent-hover: var(--ax3); --quote-opening-modifier: var(--ui2); --modal-border: var(--ui2); --icon-color: var(--tx2); --icon-color-hover: var(--tx2); --icon-color-active: var(--tx1); --icon-hex: var(--mono0); --text-normal: var(--tx1); --text-bold: var(--tx1); --text-italic: var(--tx1); --text-muted: var(--tx2); --text-faint: var(--tx3); --text-accent: var(--ax1); --text-accent-hover: var(--ax2); --text-on-accent: white; --text-selection: var(--hl1); --text-code: var(--tx4); --text-error: var(--color-red); --text-blockquote: var(--tx2); --title-color: var(--tx1); --title-color-inactive: var(--tx2) } .published-container { --outline-heading-color-active: var(--tx1); --sidebar-left-background: var(--bg2); } .alt-title .page-header, .hide-title .page-header { display: none } .hide-title.markdown-preview-view div:nth-child(4) h1 { margin-top: .25em; font-variant: var(--page-title-variant); letter-spacing: -.015em; line-height: var(--page-title-line-height); font-size: var(--page-title-size); color: var(--page-title-color); font-weight: var(--page-title-weight); font-style: var(--page-title-style); font-family: var(--page-title-font); border: none } .h1-borders h1 { border-bottom: 1px solid var(--ui1); padding-bottom: .5em } .table-col-1-150.markdown-preview-view td:first-child { width: 150px } .table-col-1-200.markdown-preview-view td:first-child { width: 200px } .table-100 table, .table-cards table, .table-full table { width: 100% } .table-small table { --table-text-size: 85% } .table-tiny table { --table-text-size: 75% } .row-hover { --table-edge-cell-padding-first: 10px } .row-alt { --table-row-alt-background: var(--background-table-rows); --table-edge-cell-padding-first: 10px } .col-alt .markdown-rendered:not(.cards) { --table-column-alt-background: var(--background-table-rows) } .table-tabular table { font-variant-numeric: tabular-nums } .table-lines { --table-border-width: var(--border-width); --table-header-border-width: var(--border-width); --table-column-first-border-width: var(--border-width); --table-column-last-border-width: var(--border-width); --table-row-last-border-width: var(--border-width); --table-edge-cell-padding: 10px } .table-nowrap { --table-white-space: nowrap } .table-nowrap .table-wrap, .trim-cols { --table-white-space: normal } .table-numbers table { counter-reset: section } .table-numbers table>thead>tr>th:first-child::before { content: " "; padding-right: .5em; display: inline-block; min-width: 2em } .table-numbers table>tbody>tr>td:first-child::before { counter-increment: section; content: counter(section) " "; text-align: center; padding-right: .5em; display: inline-block; min-width: 2em; color: var(--text-faint); font-variant-numeric: tabular-nums } .row-lines-off .table-view-table>tbody>tr>td, .row-lines-off table tbody>tr:last-child>td, .row-lines-off table tbody>tr>td { border-bottom: none } .row-lines .table-view-table>tbody>tr>td, .row-lines table tbody>tr>td { border-bottom: var(--table-border-width) solid var(--table-border-color) } .row-lines table tbody>tr:last-child>td { border-bottom: none } .col-lines .table-view-table thead>tr>th:not(:last-child), .col-lines .table-view-table>tbody>tr>td:not(:last-child), .col-lines table tbody>tr>td:not(:last-child) { border-right: var(--table-border-width) solid var(--background-modifier-border) } .row-hover { --table-row-background-hover: hsla(var(--accent-h), 50%, 80%, 20%) } .theme-dark .row-hover, .theme-dark.row-hover { --table-row-background-hover: hsla(var(--accent-h), 30%, 40%, 20%) } img[src$="#outline"], span[src$="#outline"] img { border: 1px solid var(--ui1) } .published-container img[src$="#interface"], .published-container span[src$="#interface"] img { border: 1px solid var(--ui1); box-shadow: 0 .5px .9px rgba(0, 0, 0, .021), 0 1.3px 2.5px rgba(0, 0, 0, .03), 0 3px 6px rgba(0, 0, 0, .039), 0 10px 20px rgba(0, 0, 0, .06); margin-top: 10px; margin-bottom: 15px; border-radius: var(--radius-m) } .theme-dark img[src$="#invert"], .theme-dark span[src$="#invert"] img { filter: invert(1) hue-rotate(180deg); mix-blend-mode: screen } .theme-light img[src$="#invertW"], .theme-light span[src$="#invertW"] img { filter: invert(1) hue-rotate(180deg) } img[src$="#circle"], span[src$="#circle"] img { border-radius: 50%; aspect-ratio: 1/1 } body { --image-grid-fit: cover; --image-grid-background: transparent; --img-grid-gap: 0.5rem } @media(max-width:400pt) { body { --img-grid-gap: 0.25rem } } .img-grid-ratio { --image-grid-fit: contain } .img-grid .image-embed { line-height: 0; display: flex } .img-grid .image-embed.is-loaded img { background-color: var(--image-grid-background) } .img-grid .image-embed.is-loaded img:active { background-color: rgba(0, 0, 0, 0) } .img-grid .markdown-preview-section>div:has(.image-embed)>p { display: grid; margin-block-start: var(--img-grid-gap); margin-block-end: var(--img-grid-gap); grid-column-gap: var(--img-grid-gap); grid-row-gap: 0; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)) } .img-grid .markdown-preview-section>div:has(.image-embed)>p>br { display: none } .img-grid .markdown-preview-section>div:has(.image-embed)>p>img { object-fit: var(--image-grid-fit); align-self: stretch; height: 100% } .img-grid .markdown-preview-section>div:has(.image-embed)>p>.internal-embed img { object-fit: var(--image-grid-fit); align-self: center; height: 100% } .table-cards table { --table-width: 100%; --table-edge-cell-padding-first: calc(var(--cards-padding)/2); --table-edge-cell-padding-last: calc(var(--cards-padding)/2); --table-cell-padding: calc(var(--cards-padding)/3) calc(var(--cards-padding)/2); line-height: 1.3 } .table-cards table tbody { clear: both; padding: .5rem 0; display: grid; grid-template-columns: var(--cards-columns); grid-column-gap: .75rem; grid-row-gap: .75rem } .table-cards table>tbody>tr { background-color: var(--cards-background); border: var(--cards-border-width) solid var(--background-modifier-border); display: flex; flex-direction: column; margin: 0; padding: 0 0 calc(var(--cards-padding)/3) 0; border-radius: 6px; overflow: hidden; transition: box-shadow .15s linear; max-width: var(--cards-max-width) } .table-cards table>tbody>tr:hover { border: var(--cards-border-width) solid var(--background-modifier-border-hover); box-shadow: 0 4px 6px 0 rgba(0, 0, 0, .05), 0 1px 3px 1px rgba(0, 0, 0, .025); transition: box-shadow .15s linear } .table-cards table tbody>tr>td:first-child { font-weight: var(--bold-weight); border: none } .table-cards table tbody>tr>td:first-child a { display: block } .table-cards table tbody>tr>td:last-child { border: none } .table-cards table tbody>tr>td:not(:first-child) { font-size: calc(var(--table-text-size)*.9); color: var(--text-muted) } .table-cards table tbody>tr>td>* { padding: calc(var(--cards-padding)/3) 0 } .table-cards table tbody>tr>td:not(:last-child):not(:first-child) { padding: 4px 0; border-bottom: 1px solid var(--background-modifier-border); width: calc(100% - var(--cards-padding)); margin: 0 calc(var(--cards-padding)/2) } .table-cards table tbody>tr>td a { text-decoration: none } .table-cards table tbody>tr>td>button { width: 100%; margin: calc(var(--cards-padding)/2) 0 } .table-cards table tbody>tr>td:last-child>button { margin-bottom: calc(var(--cards-padding)/6) } .table-cards table tbody>tr>td>ul { width: 100%; padding: .25em 0 !important; margin: 0 auto !important } .table-cards table tbody>tr>td:has(img) { padding: 0 !important; background-color: var(--background-secondary); display: block; margin: 0; width: 100% } .table-cards table tbody>tr>td img { aspect-ratio: var(--cards-aspect-ratio); width: 100%; object-fit: var(--cards-image-fit); max-height: var(--cards-image-height); background-color: var(--background-secondary); vertical-align: bottom } .table-cards table thead { display: none } .list-cards.markdown-preview-view .list-bullet, .list-cards.markdown-preview-view .list-collapse-indicator, .list-cards.markdown-preview-view.markdown-rendered.show-indentation-guide li>ul::before { display: none } .list-cards.markdown-preview-view div>ul { display: grid; gap: .75rem; grid-template-columns: var(--cards-columns); padding: 0; line-height: var(--line-height-tight) } .list-cards.markdown-preview-view div>ul>li { background-color: var(--cards-background); padding: calc(var(--cards-padding)/2); border-radius: var(--radius-s); border: var(--cards-border-width) solid var(--background-modifier-border); overflow: hidden } .list-cards.markdown-preview-view div>ul .image-embed { padding: 0; display: block; background-color: var(--background-secondary); border-radius: var(--image-radius) } .list-cards.markdown-preview-view div>ul .image-embed img { aspect-ratio: var(--cards-aspect-ratio); object-fit: var(--cards-image-fit); max-height: var(--cards-image-height); background-color: var(--background-secondary); vertical-align: bottom } .list-cards.markdown-preview-view div>ul>li>a { --link-decoration: none; --link-external-decoration: none; font-weight: var(--bold-weight) } .list-cards.markdown-preview-view div ul>li:hover { border-color: var(--background-modifier-border-hover) } .list-cards.markdown-preview-view div ul ul { display: block; width: 100%; color: var(--text-muted); font-size: var(--font-smallest); margin: calc(var(--cards-padding)/-4) 0; padding: calc(var(--cards-padding)/2) 0 } .list-cards.markdown-preview-view div ul ul ul { padding-bottom: calc(var(--cards-padding)/4) } .list-cards.markdown-preview-view div ul ul>li { display: block } .list-cards.table-cards-16-9, .table-cards.table-cards-16-9 { --cards-aspect-ratio: 16/9 } .list-cards.table-cards-1-1, .table-cards.table-cards-1-1 { --cards-aspect-ratio: 1/1 } .list-cards.table-cards-2-1, .table-cards.table-cards-2-1 { --cards-aspect-ratio: 2/1 } .list-cards.table-cards-2-3, .table-cards.table-cards-2-3 { --cards-aspect-ratio: 2/3 } .list-cards.table-cards-cols-1, .table-cards.table-cards-cols-1 { --cards-columns: repeat(1, minmax(0, 1fr)) } .list-cards.table-cards-cols-2, .table-cards.table-cards-cols-2 { --cards-columns: repeat(2, minmax(0, 1fr)) } .list-cards.table-cards-cover, .table-cards.table-cards-cover { --cards-image-fit: cover } .list-cards.table-cards-align-bottom table tbody>tr>td:last-child, .table-cards.table-cards-align-bottom table tbody>tr>td:last-child { margin-top: auto } @media(max-width:400pt) { .table-cards table tbody>tr>td:not(:first-child) { font-size: 80% } } @media(min-width:400pt) { .table-cards-cols-3 { --cards-columns: repeat(3, minmax(0, 1fr)) } .table-cards-cols-4 { --cards-columns: repeat(4, minmax(0, 1fr)) } .table-cards-cols-5 { --cards-columns: repeat(5, minmax(0, 1fr)) } .table-cards-cols-6 { --cards-columns: repeat(6, minmax(0, 1fr)) } .table-cards-cols-7 { --cards-columns: repeat(7, minmax(0, 1fr)) } .table-cards-cols-8 { --cards-columns: repeat(8, minmax(0, 1fr)) } } .markdown-preview-view code { color: var(--tx4); font-size: .85em } .theme-light :not(pre)>code[class*=language-], .theme-light pre[class*=language-] { background-color: var(--bg2) } iframe, img { border-radius: var(--image-radius) } .lightbox { z-index: 99999; position: fixed; width: 100%; height: 100%; max-width: 100%; top: 0; left: 0; background: rgba(0, 0, 0, .6); display: flex; align-items: center; justify-content: center; height: 100% } .lightbox .internal-embed { max-width: 96%; max-height: 96vh; cursor: zoom-out; display: flex } .lightbox img { cursor: zoom-out; object-fit: contain } .img-zoom .image-embed { cursor: zoom-in } input[type=email], input[type=number], input[type=password], input[type=search], input[type=text] { border-color: var(--ui1) } input[type=email]:hover, input[type=number]:hover, input[type=password]:hover, input[type=search]:hover, input[type=text]:hover { border-color: var(--ui2) } input[type=email]:active, input[type=email]:focus, input[type=number]:active, input[type=number]:focus, input[type=password]:active, input[type=password]:focus, input[type=search]:active, input[type=search]:focus, input[type=text]:active, input[type=text]:focus { border-color: var(--ui2); box-shadow: 0 0 0 2px var(--ui2) } ol>li::marker, ul>li::marker { color: var(--tx3) } body { --table-header-border-width: 0; --table-column-first-border-width: 0; --table-column-last-border-width: 0; --table-row-last-border-width: 0; --table-edge-cell-padding-first: 0; --table-edge-cell-padding-last: 10px; --table-cell-padding: 4px 10px; --table-header-size: var(--table-text-size) } .markdown-preview-view table { border: var(--border-width) solid var(--border-color); border-collapse: collapse; margin-block-start: 1em } .markdown-preview-view td, .markdown-preview-view th { padding: var(--table-cell-padding) } .markdown-preview-view td:first-child, .markdown-preview-view th:first-child { padding-left: var(--table-edge-cell-padding-first) } .markdown-preview-view td:last-child, .markdown-preview-view th:last-child { padding-right: var(--table-edge-cell-padding-last) } .markdown-preview-view .tag:not(.token) { background-color: rgba(0, 0, 0, 0); border: 1px solid var(--ui1); color: var(--tx2); font-size: var(--font-small) } .tooltip { display: none } .site-footer a { display: none; } .markdown-preview-view pre { max-height: 400px; overflow: auto; white-space: pre-wrap; } ``` As for Obsidian itself - I haven't spent much time looking through and installing extensions. I will customize it more to my liking some other time.