├── .gitignore ├── Screenshot.png ├── colors.conf ├── README.md ├── tmux.conf └── lualine.lua /.gitignore: -------------------------------------------------------------------------------- 1 | plugins/ 2 | .DS_store 3 | -------------------------------------------------------------------------------- /Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naivecynics/primary-tmux/HEAD/Screenshot.png -------------------------------------------------------------------------------- /colors.conf: -------------------------------------------------------------------------------- 1 | # ~/.config/tmux/colors.conf 2 | 3 | set -g @thm_rosewater "#f2d5cf" 4 | set -g @thm_flamingo "#eebebe" 5 | set -g @thm_pink "#f4b8e4" 6 | set -g @thm_mauve "#ca9ee6" 7 | set -g @thm_red "#e78284" 8 | set -g @thm_maroon "#ea999c" 9 | set -g @thm_peach "#ef9f76" 10 | set -g @thm_yellow "#e5c890" 11 | set -g @thm_green "#a6d189" 12 | set -g @thm_teal "#81c8be" 13 | set -g @thm_sky "#99d1db" 14 | set -g @thm_sapphire "#85c1dc" 15 | set -g @thm_blue "#8caaee" 16 | set -g @thm_lavender "#babbf1" 17 | set -g @thm_text "#c6d0f5" 18 | set -g @thm_subtext1 "#b5bfe2" 19 | set -g @thm_subtext0 "#a5adce" 20 | set -g @thm_overlay2 "#949cbb" 21 | set -g @thm_overlay1 "#838ba7" 22 | set -g @thm_overlay0 "#737994" 23 | set -g @thm_surface2 "#626880" 24 | set -g @thm_surface1 "#51576d" 25 | set -g @thm_surface0 "#414559" 26 | set -g @thm_base "#303446" 27 | set -g @thm_mantle "#292c3c" 28 | set -g @thm_crust "#232634" 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tmux & Neovim Configuration 2 | 3 | This is a personal Tmux and Neovim configuration that creates a cohesive and visually appealing terminal experience. The style is inspired by the Catppuccin theme and a desire for a clean, modern, and functional setup. 4 | 5 | This configuration is based on the setup discussed in [this GitHub discussion](https://github.com/catppuccin/tmux/discussions/317#discussioncomment-11064512). 6 | 7 | ## Screenshot 8 | 9 | ![Screenshot of the Tmux and Neovim setup](Screenshot.png) 10 | 11 | ## Features 12 | 13 | ### Tmux 14 | 15 | * **Catppuccin Theme:** The configuration uses the Catppuccin color palette for a consistent look and feel. The colors are defined in `colors.conf`. 16 | * **Custom Status Bar:** The status bar is customized to show important information at a glance, including: 17 | * Session name 18 | * Current command 19 | * Current path 20 | * Zoom status 21 | * Memory and CPU usage 22 | * Battery percentage 23 | * **Icon-Based Window Status:** Instead of text, the window status uses icons to represent the current application running in each window (e.g., zsh, nvim, git, etc.). 24 | * **Custom Keybindings:** The prefix key is set to `` ` `` (backtick) for easier access. Keybindings are set up for intuitive pane navigation, resizing, and window management. 25 | * **TPM (Tmux Plugin Manager):** The configuration uses TPM to manage Tmux plugins. The following plugins are included: 26 | * `tmux-plugins/tpm` 27 | * `tmux-plugins/tmux-battery` 28 | * `tmux-plugins/tmux-cpu` 29 | * `thewtex/tmux-mem-cpu-load` 30 | * `laktak/extrakto` 31 | 32 | ### Neovim (Lualine) 33 | 34 | The `lualine.lua` file configures the Lualine plugin for Neovim to match the Tmux theme. 35 | 36 | * **Catppuccin Colors:** The Lualine theme uses the same Catppuccin colors as the Tmux configuration. 37 | * **Custom Components:** The Lualine status bar is customized to include: 38 | * Mode indicator 39 | * Git branch 40 | * File information (icon, name, and status) 41 | * Buffer list 42 | * File format, encoding, and size 43 | * Diagnostics 44 | * Progress and location 45 | * **Custom Separators:** The status bar uses custom separators for a clean and modern look. 46 | 47 | ## Installation 48 | 49 | 1. **Clone the repository:** 50 | ```bash 51 | git clone https://github.com/your-username/your-repo-name.git ~/.config/tmux 52 | ``` 53 | 2. **Install TPM (Tmux Plugin Manager):** 54 | ```bash 55 | git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm 56 | ``` 57 | 3. **Install the plugins:** 58 | * Start Tmux. 59 | * Press `prefix` + `I` (capital I, as in **I**nstall) to fetch the plugins. 60 | 4. **Install Neovim and the necessary plugins:** 61 | * Install Neovim. 62 | * Install a plugin manager for Neovim (e.g., Packer, lazy.nvim). 63 | * Add the `nvim-lualine/lualine.nvim` plugin to your Neovim configuration. 64 | 65 | ## Usage 66 | 67 | * **Reload Tmux configuration:** `prefix` + `r` 68 | * **Split panes:** 69 | * `prefix` + `\` for a horizontal split. 70 | * `prefix` + `/` for a vertical split. 71 | * **Navigate panes:** `prefix` + `h`/`j`/`k`/`l` 72 | * **Resize panes:** `prefix` + `^h`/`^j`/`^k`/`^l` 73 | * **Copy mode:** `prefix` + `v` 74 | 75 | ## Color Palette 76 | 77 | The color palette is defined in `colors.conf` and is based on the Catppuccin theme. 78 | 79 | | Color Name | Hex Code | 80 | | :---------- | :-------- | 81 | | Rosewater | `#f2d5cf` | 82 | | Flamingo | `#eebebe` | 83 | | Pink | `#f4b8e4` | 84 | | Mauve | `#ca9ee6` | 85 | | Red | `#e78284` | 86 | | Maroon | `#ea999c` | 87 | | Peach | `#ef9f76` | 88 | | Yellow | `#e5c890` | 89 | | Green | `#a6d189` | 90 | | Teal | `#81c8be` | 91 | | Sky | `#99d1db` | 92 | | Sapphire | `#85c1dc` | 93 | | Blue | `#8caaee` | 94 | | Lavender | `#babbf1` | 95 | | Text | `#c6d0f5` | 96 | | Subtext1 | `#b5bfe2` | 97 | | Subtext0 | `#a5adce` | 98 | | Overlay2 | `#949cbb` | 99 | | Overlay1 | `#838ba7` | 100 | | Overlay0 | `#737994` | 101 | | Surface2 | `#626880` | 102 | | Surface1 | `#51576d` | 103 | | Surface0 | `#414559` | 104 | | Base | `#303446` | 105 | | Mantle | `#292c3c` | 106 | | Crust | `#232634` | -------------------------------------------------------------------------------- /tmux.conf: -------------------------------------------------------------------------------- 1 | # ~/.config/tmux/tmux.conf 2 | bind r source-file "$HOME/.config/tmux/tmux.conf" \; display-message "Config reloading.." 3 | unbind C-b 4 | set-option -g prefix ` 5 | bind-key C-a send-prefix 6 | set-option -g mouse on 7 | set -g allow-passthrough on 8 | setw -g monitor-activity on 9 | set -g base-index 1 10 | set -g default-terminal "tmux-256color" 11 | set -s escape-time 0 12 | set -s repeat-time 300 13 | # window 14 | unbind '"' 15 | bind '/' splitw -v -c '#{pane_current_path}' 16 | unbind '%' 17 | bind '\' splitw -h -c '#{pane_current_path}' 18 | bind ` last-window 19 | bind -r k select-pane -U 20 | bind -r j select-pane -D 21 | bind -r h select-pane -L 22 | bind -r l select-pane -R 23 | bind -r ^k resizep -U 4 24 | bind -r ^j resizep -D 4 25 | bind -r ^h resizep -L 8 26 | bind -r ^l resizep -R 8 27 | # copy 28 | setw -g mode-keys vi 29 | bind -r v copy-mode 30 | bind -T copy-mode-vi v send-keys -X begin-selection 31 | bind -T copy-mode-vi y send-keys -X copy-selection-and-cancel 32 | 33 | # bootstrap tpm 34 | if "test ! -d ~/.tmux/plugins/tpm" \ 35 | "run 'git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm && ~/.tmux/plugins/tpm/bin/install_plugins'" 36 | set -g @plugin 'tmux-plugins/tpm' 37 | set -g @plugin 'tmux-plugins/tmux-battery' 38 | set -g @plugin 'tmux-plugins/tmux-cpu' 39 | set -g @plugin 'thewtex/tmux-mem-cpu-load' 40 | set -g @plugin 'laktak/extrakto' 41 | 42 | # config catppucin color 43 | if-shell '[ -f ~/.config/tmux/colors.conf ]' "source-file ~/.config/tmux/colors.conf" 44 | 45 | # status left look and feel 46 | set -g status-left-length 100 47 | set -g status-left "" 48 | set -ga status-left "#{?client_prefix,#{#[bg=#{@thm_red},fg=default,bold]  #S },#{#[bg=default,fg=#{@thm_red},bold]  #S }}" 49 | set -ga status-left "#[bg=default,fg=#{@thm_overlay0},none,bold]│" 50 | set -ga status-left "#[bg=default,fg=#{@thm_green},bold]  #{pane_current_command} " 51 | set -ga status-left "#[bg=default,fg=#{@thm_overlay0},none,bold]│" 52 | set -ga status-left "#[bg=default,fg=#{@thm_blue},bold]  #{=/-10/...:#{s|$USER|~|:#{b:pane_current_path}}} " 53 | set -ga status-left "#[bg=default,fg=#{@thm_overlay0},none,bold]#{?window_zoomed_flag,│,}" 54 | set -ga status-left "#[bg=default,fg=#{@thm_yellow},bold]#{?window_zoomed_flag,  zoom ,}" 55 | 56 | # status right look and feel 57 | set -g status-right-length 100 58 | set -g status-right "" 59 | set -ga status-right "#[bg=default,fg=#{@thm_blue},bold]  #($TMUX_PLUGIN_MANAGER_PATH/tmux-mem-cpu-load/tmux-mem-cpu-load -i 2 -m 2 | awk \'{print substr($1, 1, 4)}\')%% " 60 | set -ga status-right "#[bg=default,fg=#{@thm_overlay0},none,bold]│" 61 | set -ga status-right "#[bg=default,fg=#{@thm_green},bold] 󰍛 #{cpu_percentage} " 62 | set -ga status-right "#[bg=default,fg=#{@thm_overlay0},none,bold]│" 63 | set -ga status-right "#[bg=default,fg=#{@thm_red},bold] 󱐋#{?#{e|>=:20,#{battery_percentage}},#{#[bg=#{@thm_red},fg=default,bold]},#{#[bg=default,fg=#{@thm_red},bold]}} #{battery_percentage} " 64 | # set -ga status-right "#[bg=default,fg=#{@thm_red},bold] 󱐋#{?#{e|>=:20,#{battery_percentage}},#{#[bg=#{@thm_red},fg=default,bold]},#{#[bg=default,fg=#{@thm_green},bold]}} #{battery_percentage} " 65 | # set -ga status-right "#[bg=default,fg=#{@thm_overlay0},none,bold]│" 66 | # set -ga status-right "#[bg=default,fg=#{@thm_red},bold] 󰭦 %m-%d 󰅐 %H:%M " 67 | 68 | # Configure Tmux 69 | set -g status-position top 70 | set -g status-style "bg=default" 71 | set -g status-justify "absolute-centre" 72 | 73 | # pane border look and feel 74 | setw -g pane-border-status off 75 | # setw -g pane-border-status top 76 | setw -g pane-border-format "" 77 | setw -g pane-border-style "bg=default,fg=#{@thm_overlay0}" 78 | setw -g pane-active-border-style "bg=default,fg=#{@thm_red}" 79 | setw -g pane-border-lines single 80 | 81 | # window content (number) 82 | # set -wg automatic-rename on 83 | # set -g automatic-rename-format "window" 84 | # set -g window-status-current-format " #I#{?#{!=:#{window_name},window},: #W,} " 85 | # set -g window-status-format " #I#{?#{!=:#{window_name},window},: #W,} " 86 | 87 | # set -g window-status-style "bg=default,fg=#{@thm_rosewater}" 88 | # set -g window-status-last-style "bg=default,fg=#{@thm_peach}" 89 | # set -g window-status-activity-style "bg=#{@thm_red},fg=#{@thm_base}" 90 | # set -g window-status-bell-style "bg=#{@thm_red},fg=#{@thm_base},bold" 91 | # set -g window-status-current-style "bg=#{@thm_peach},fg=#{@thm_base},bold" 92 | # set -gF window-status-separator "#[bg=default,fg=#{@thm_overlay0}]│" 93 | 94 | # window content (icon) 95 | set -g automatic-rename off 96 | set -g allow-rename off 97 | set -g window-status-format '\ 98 | #{?#{==:#{pane_current_command},zsh},  ,\ 99 | #{?#{==:#{pane_current_command},fish}, 󰈺 ,\ 100 | #{?#{==:#{pane_current_command},nvim},  ,\ 101 | #{?#{==:#{pane_current_command},git}, 󰊢 ,\ 102 | #{?#{==:#{pane_current_command},htop}, ,\ 103 | #{?#{==:#{pane_current_command},yazi}, 󰀶 ,\ 104 | #{?#{==:#{pane_current_command},python}, 󰌠 ,\ 105 | #{?#{==:#{pane_current_command},bash},  ,\ 106 | #{?#{==:#{pane_current_command},ssh},  ,\ 107 | #{?#{==:#{pane_current_command},node},  ,\ 108 | #{?#{==:#{pane_current_command},cargo},  ,\ 109 | #{?#{==:#{pane_current_command},rustc},  ,\ 110 | #{?#{==:#{pane_current_command},lua},  ,\ 111 | 󰘧 }}}}}}}}}}}}}' 112 | set -g window-status-current-format '\ 113 | #{?#{==:#{pane_current_command},zsh},  ,\ 114 | #{?#{==:#{pane_current_command},fish}, 󰈺 ,\ 115 | #{?#{==:#{pane_current_command},nvim},  ,\ 116 | #{?#{==:#{pane_current_command},git}, 󰊢 ,\ 117 | #{?#{==:#{pane_current_command},htop}, ,\ 118 | #{?#{==:#{pane_current_command},yazi}, 󰀶 ,\ 119 | #{?#{==:#{pane_current_command},python}, 󰌠 ,\ 120 | #{?#{==:#{pane_current_command},bash},  ,\ 121 | #{?#{==:#{pane_current_command},ssh},  ,\ 122 | #{?#{==:#{pane_current_command},node},  ,\ 123 | #{?#{==:#{pane_current_command},cargo},  ,\ 124 | #{?#{==:#{pane_current_command},rustc},  ,\ 125 | #{?#{==:#{pane_current_command},lua},  ,\ 126 | 󰘧 }}}}}}}}}}}}}' 127 | # window style 128 | set -g window-status-style "bg=default,fg=#{@thm_rosewater}" 129 | set -g window-status-last-style "bg=default,fg=#{@thm_flamingo}" 130 | set -g window-status-current-style "bg=default,fg=#{@thm_peach},bold" 131 | set -g window-status-activity-style "bg=default,fg=#{@thm_pink},bold" 132 | set -g window-status-bell-style "bg=default,fg=#{@thm_red},bold" 133 | # set -gF window-status-separator "#[bg=default,fg=#{@thm_overlay2}]│" 134 | 135 | # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) 136 | run '~/.tmux/plugins/tpm/tpm' 137 | -------------------------------------------------------------------------------- /lualine.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "nvim-lualine/lualine.nvim", 3 | opts = function(_, opts) 4 | local auto = require("lualine.themes.auto") 5 | 6 | local colors = { 7 | rosewater = "#f2d5cf", 8 | flamingo = "#eebebe", 9 | pink = "#f4b8e4", 10 | mauve = "#ca9ee6", 11 | red = "#e78284", 12 | maroon = "#ea999c", 13 | peach = "#ef9f76", 14 | yellow = "#e5c890", 15 | green = "#a6d189", 16 | teal = "#81c8be", 17 | sky = "#99d1db", 18 | sapphire = "#85c1dc", 19 | blue = "#8caaee", 20 | lavender = "#babbf1", 21 | text = "#c6d0f5", 22 | subtext1 = "#b5bfe2", 23 | subtext0 = "#a5adce", 24 | overlay2 = "#949cbb", 25 | overlay1 = "#838ba7", 26 | overlay0 = "#737994", 27 | surface2 = "#626880", 28 | surface1 = "#51576d", 29 | surface0 = "#414559", 30 | base = "#303446", 31 | mantle = "#292c3c", 32 | crust = "#232634", 33 | } 34 | 35 | local function separator() 36 | return { 37 | function() 38 | return "│" 39 | end, 40 | color = { fg = colors.surface0, bg = "NONE", gui = "bold" }, 41 | padding = { left = 1, right = 1 }, 42 | } 43 | end 44 | 45 | local function custom_branch() 46 | local gitsigns = vim.b.gitsigns_head 47 | local fugitive = vim.fn.exists("*FugitiveHead") == 1 and vim.fn.FugitiveHead() or "" 48 | local branch = gitsigns or fugitive 49 | if branch == nil or branch == "" then 50 | return "" 51 | else 52 | return " " .. branch 53 | end 54 | end 55 | 56 | local modes = { "normal", "insert", "visual", "replace", "command", "inactive", "terminal" } 57 | for _, mode in ipairs(modes) do 58 | if auto[mode] and auto[mode].c then 59 | auto[mode].c.bg = "NONE" 60 | end 61 | end 62 | 63 | opts.options = vim.tbl_deep_extend("force", opts.options or {}, { 64 | theme = auto, 65 | component_separators = "", 66 | section_separators = "", 67 | globalstatus = true, 68 | disabled_filetypes = { statusline = {}, winbar = {} }, 69 | }) 70 | 71 | opts.sections = { 72 | lualine_a = { 73 | { 74 | "mode", 75 | fmt = function(str) 76 | return str:sub(1, 1) 77 | end, 78 | color = function() 79 | local mode = vim.fn.mode() 80 | if mode == "\22" then 81 | return { fg = "none", bg = colors.red, gui = "bold" } 82 | elseif mode == "V" then 83 | return { fg = colors.red, bg = "none", gui = "underline,bold" } 84 | else 85 | return { fg = colors.red, bg = "none", gui = "bold" } 86 | end 87 | end, 88 | padding = { left = 0, right = 0 }, 89 | }, 90 | }, 91 | lualine_b = { 92 | separator(), 93 | { 94 | custom_branch, 95 | color = { fg = colors.green, bg = "none", gui = "bold" }, 96 | padding = { left = 0, right = 0 }, 97 | }, 98 | { 99 | "diff", 100 | colored = true, 101 | diff_color = { 102 | added = { fg = colors.teal, bg = "none", gui = "bold" }, 103 | modified = { fg = colors.yellow, bg = "none", gui = "bold" }, 104 | removed = { fg = colors.red, bg = "none", gui = "bold" }, 105 | }, 106 | symbols = { added = "+", modified = "~", removed = "-" }, 107 | source = nil, 108 | padding = { left = 1, right = 0 }, 109 | }, 110 | }, 111 | lualine_c = { 112 | separator(), 113 | { 114 | "filetype", 115 | icon_only = true, 116 | colored = false, 117 | color = { fg = colors.blue, bg = "none", gui = "bold" }, 118 | padding = { left = 0, right = 1 }, 119 | }, 120 | { 121 | "filename", 122 | file_status = true, 123 | path = 0, 124 | shorting_target = 20, 125 | symbols = { 126 | modified = "[+]", 127 | readonly = "[-]", 128 | unnamed = "[?]", 129 | newfile = "[!]", 130 | }, 131 | color = { fg = colors.blue, bg = "none", gui = "bold" }, 132 | padding = { left = 0, right = 0 }, 133 | }, 134 | separator(), 135 | { 136 | function() 137 | local bufnr_list = vim.fn.getbufinfo({ buflisted = 1 }) 138 | local total = #bufnr_list 139 | local current_bufnr = vim.api.nvim_get_current_buf() 140 | local current_index = 0 141 | 142 | for i, buf in ipairs(bufnr_list) do 143 | if buf.bufnr == current_bufnr then 144 | current_index = i 145 | break 146 | end 147 | end 148 | 149 | return string.format(" %d/%d", current_index, total) 150 | end, 151 | color = { fg = colors.yellow, bg = "none", gui = "bold" }, 152 | padding = { left = 0, right = 0 }, 153 | }, 154 | }, 155 | lualine_x = { 156 | { 157 | "fileformat", 158 | color = { fg = colors.yellow, bg = "none", gui = "bold" }, 159 | symbols = { 160 | unix = "", 161 | dos = "", 162 | mac = "", 163 | }, 164 | padding = { left = 0, right = 0 }, 165 | }, 166 | { 167 | "encoding", 168 | color = { fg = colors.yellow, bg = "none", gui = "bold" }, 169 | padding = { left = 1, right = 0 }, 170 | }, 171 | separator(), 172 | { 173 | function() 174 | local size = vim.fn.getfsize(vim.api.nvim_buf_get_name(0)) 175 | if size < 0 then 176 | return "-" 177 | else 178 | if size < 1024 then 179 | return size .. "B" 180 | elseif size < 1024 * 1024 then 181 | return string.format("%.1fK", size / 1024) 182 | elseif size < 1024 * 1024 * 1024 then 183 | return string.format("%.1fM", size / (1024 * 1024)) 184 | else 185 | return string.format("%.1fG", size / (1024 * 1024 * 1024)) 186 | end 187 | end 188 | end, 189 | color = { fg = colors.blue, bg = "none", gui = "bold" }, 190 | padding = { left = 0, right = 0 }, 191 | }, 192 | }, 193 | lualine_y = { 194 | separator(), 195 | { 196 | "diagnostics", 197 | sources = { "nvim_diagnostic", "coc" }, 198 | sections = { "error", "warn", "info", "hint" }, 199 | diagnostics_color = { 200 | error = function() 201 | local count = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR }) 202 | return { fg = (count == 0) and colors.green or colors.red, bg = "none", gui = "bold" } 203 | end, 204 | warn = function() 205 | local count = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN }) 206 | return { fg = (count == 0) and colors.green or colors.yellow, bg = "none", gui = "bold" } 207 | end, 208 | info = function() 209 | local count = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO }) 210 | return { fg = (count == 0) and colors.green or colors.blue, bg = "none", gui = "bold" } 211 | end, 212 | hint = function() 213 | local count = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT }) 214 | return { fg = (count == 0) and colors.green or colors.teal, bg = "none", gui = "bold" } 215 | end, 216 | }, 217 | symbols = { 218 | error = "󰅚 ", 219 | warn = "󰀪 ", 220 | info = "󰋽 ", 221 | hint = "󰌶 ", 222 | }, 223 | colored = true, 224 | update_in_insert = false, 225 | always_visible = true, 226 | padding = { left = 0, right = 0 }, 227 | }, 228 | }, 229 | lualine_z = { 230 | separator(), 231 | { 232 | "progress", 233 | color = { fg = colors.red, bg = "none", gui = "bold" }, 234 | padding = { left = 0, right = 0 }, 235 | }, 236 | { 237 | "location", 238 | color = { fg = colors.red, bg = "none", gui = "bold" }, 239 | padding = { left = 1, right = 0 }, 240 | }, 241 | }, 242 | } 243 | 244 | return opts 245 | end, 246 | } 247 | --------------------------------------------------------------------------------