214 Commits
Author SHA1 Message Date
branderson cd06db0274 Merge pull request 'Scroll copy mode 4 lines per mouse wheel tick instead of half a page' (#8) from tmux-wheel-scroll-4 into master
Reviewed-on: #8
Reviewed-by: branderson <brad@branderson.io>
2026-09-02 18:58:20 -07:00
branderson eacaebfdef Scroll copy mode 4 lines per mouse wheel tick instead of half a page 2026-09-02 18:32:22 -07:00
branderson b0a2f0b132 Merge pull request 'Fix basedpyright install failure on Debian' (#7) from nvim-basedpyright-venv into master
Reviewed-on: #7
Reviewed-by: branderson <brad@branderson.io>
2026-08-17 14:42:55 -07:00
branderson 237a56fb6c Fix basedpyright install failure on Debian
Debian ships venv's ensurepip in a separate python3-venv package. Without
it, `python3 -m venv` exits 1, so mason cannot build the venv it installs
basedpyright into, and mason-lspconfig reports a failed install on every
startup.

Add python3-venv to the apt package list, and guard the basedpyright entry
in ensure_installed the same way the npm-sourced servers are already
guarded, so a machine missing it gets one warning instead of a failed
install every time.
2026-08-17 14:36:39 -07:00
branderson 7849b91f06 Merge pull request 'Fix multi-line paste corruption in nested tmux on 3.5/3.5a' (#6) from tmux-extended-keys-paste into master
Reviewed-on: #6
Reviewed-by: branderson <brad@branderson.io>
2026-08-17 14:27:55 -07:00
branderson 123c68dbae Fix multi-line paste corruption in nested tmux on 3.5/3.5a
Pasting multi-line text into a tmux session reached over ssh from inside
another tmux replaced every newline with a literal CSI 27;5;106~, i.e.
C-j -- the pasted newline -- rendered in modifyOtherKeys form rather than
sent as a newline.

tmux 3.5 rewrote extended-key handling and encodes keys inside a
bracketed paste; the layer further in passes those bytes through verbatim
instead of decoding them, so the application receives the escape as text.
A hop only corrupts when whatever sits downstream of it has asked for
modifyOtherKeys mode 2. A nested tmux always asks, because of the
"*:extkeys" terminal-feature above it; an application running directly
under screen-256color generally does not. That is why one tmux in the
chain was fine and two were not.

Confirmed by building 3.2a, 3.3a, 3.4, 3.5a, 3.6b and 3.7c and driving a
real bracketed paste through a pty into every outer/inner combination:
only 3.5 and 3.5a corrupt, and only on the requesting hop. Fixed upstream
in 3.6, so upgrading is the real answer where it is available.

For hosts pinned to a distro tmux, disable extended keys on exactly those
two versions. Nothing narrower works: extended-keys-format csi-u only
changes which escape lands in the text, and withholding the extkeys
terminal-feature stops a tmux asking its own parent for extended keys
without stopping it encoding them for its pane. With the guard in place
all sixteen version combinations paste correctly, and extended keys stay
on everywhere except 3.5/3.5a.

The guard tests the version with an awk END block rather than a bare
exit, so that empty input -- a tmux -V that failed for any reason --
leaves extended keys on instead of silently disabling them.

Also corrects the comment that attributed this to a Claude Code paste
tokenizer bug. It reproduces just as readily pasting into neovim.
2026-08-17 14:20:42 -07:00
branderson 86d19db1e9 Merge pull request 'Open Claude Code in its own tab on dejima auto-start' (#5) from nvim-claude-tab into master
Reviewed-on: #5
Reviewed-by: branderson <brad@branderson.io>
2026-08-10 14:14:56 -07:00
branderson 068dd8fe25 Open Claude Code in its own tab on dejima auto-start
The auto-start left the Claude terminal only as a narrow right split. Follow it with a tab split so the same terminal buffer also gets a full-screen tab, while the original tab keeps the side-by-side layout with the editor.
2026-08-10 14:11:06 -07:00
branderson 1b9b98c424 Update gitea utils 2026-08-03 20:24:34 -07:00
branderson fe27e8178e Merge pull request 'Add tmux-fzf for session/window/pane navigation' (#4) from tmux-fzf-navigation into master
Reviewed-on: #4
2026-08-02 23:30:30 -07:00
branderson 3cbe6b31b2 Add tmux-fzf for session/window/pane navigation
Many concurrent sessions with many panes each make it hard to track what is
running where, and moving a pane between windows means join-pane with a
hand-typed target, so it rarely gets done.

tmux-fzf gives a fuzzy-searchable list of every session, window and pane with
a live preview of each, and implements break/join/swap as pane actions --
which is the pane-movement gap. fzf is already in apt.global, arch.global and
brew.global, so no new packages are needed.

Checked out as a submodule rather than left for TPM to clone on first
prefix+I: ~/.tmux symlinks to config/tmux, so a TPM-installed plugin lands
inside this repo as untracked files. The submodule pins a version and
installs via the existing "git submodule update --init". TPM still sources it
from the @plugin line and can still update it.

prefix+F is the plugin's own top-level menu. prefix+P/W/S skip straight to
the pane, window and session panels. TMUX_FZF_CLIENT pins each action to the
client that opened it, as the plugin's own binding does -- run-shell has no
client context, so tmux otherwise targets the most recently active client,
which is wrong when a second client is attached to the same session.

No env-var configuration was needed: preview is already on by default, and
the TMUX_FZF_* variables are read from the environment only, so the README's
suggestion to set them in .tmux.conf is not valid tmux syntax.

Tested against tmux 3.5a and fzf 0.38.0: config parses with no errors, all
three bindings register, existing bindings are unaffected, TPM sources the
plugin and binds prefix+F, the three scripts pass bash -n, and the plugin's
fzf-version detection resolves to fzf-tmux with preview enabled. The
interactive picker itself needs a real terminal and is left to manual check.
2026-08-02 23:07:57 -07:00
branderson bd8cb97548 Don't leave insert mode after scroll in Claude Code nvim plugin 2026-07-28 18:19:15 -07:00
branderson a53f854095 Various fixes for claude-sandbox -> dejima 2026-07-27 16:45:17 -07:00
branderson 889e51f10d Add claude-code statusline 2026-07-24 15:23:40 -07:00
branderson 55a5d7ab01 Add CLAUDE.md and installer logic for if it's absent 2026-07-24 15:12:03 -07:00
branderson 99634aadc1 Fix terminal mode inconsistent behavior in nvim 2026-07-24 14:47:15 -07:00
branderson 792e2a1940 nvim: guard clipboard-copy integration on executable(), not assumed present
vim.g.clipboard pointed unconditionally at ~/dotfiles/bin/clipboard-copy,
which isn't there on every machine this config runs on now - claude-sandbox
mounts in only the nvim config directory itself, not the rest of dotfiles.
Without the guard, every yank errored inside the sandbox. Same
gracefully-degrade approach the colorscheme fallback already uses elsewhere
in this config.
2026-07-23 18:54:30 -07:00
branderson dc03a79f70 Migrate claude-sandbox out of dotfiles 2026-07-23 13:00:47 -07:00
branderson b360904421 Merge pull request 'claude-sandbox: host-matching container user + dedicated headless SSH agent' (#3) from worktree-claude-sandbox-ssh-and-plugin-mounts into master
Reviewed-on: #3
2026-07-22 13:05:37 -07:00
branderson 621bc28f7a claude-sandbox: document SANDBOX_SSH_KEY in Security notes; warn on default-looking personal keys
Second-round review follow-up. Security notes was written as the
canonical list of residual risks but never mentioned the new
SANDBOX_SSH_KEY mechanism, which has the same "signs for any repo it can
reach" shape as the forwarded agent (already documented) - add a bullet
covering it and the /root-only mount.

Also nothing enforced that SANDBOX_SSH_KEY actually be a dedicated
low-privilege key rather than a real personal identity, which is the
whole basis for accepting it as passphrase-less and left loaded for an
entire unattended session. bin/claude-sandbox now warns (non-fatal) if
it looks like a default personal keyfile (id_rsa, id_ed25519, etc).
2026-07-22 13:03:30 -07:00
branderson 5fef8dcf90 claude-sandbox: mount the dedicated SSH key source under /root, not $HOME
The headless-SSH-key feature claimed the plaintext key was "deleted
immediately after being loaded into the agent, so nothing readable is
left on disk" - but entrypoint.sh only deleted the copy it made; the
original bind-mounted source at $SANDBOX_HOME/.ssh-sandbox-key-src stayed
mounted, readable, for the container's whole life. Combined with the
sandbox user's uid now matching the host user's, that file was directly
readable by the very process the sandbox exists to constrain, letting a
compromised session exfiltrate the raw key instead of being limited to
signing through the local agent socket.

Move the mount to /root/.ssh-sandbox-key-src (root:root, 700 by default)
so only entrypoint.sh's root-run startup code can ever reach it; the
sandbox user has no path to that directory at all. Update the matching
static/runtime tests (the runtime one now asserts the sandbox user
actually gets permission denied reading the source) and correct the
README's description of the mechanism.
2026-07-22 12:36:40 -07:00
branderson 6b833bd222 claude-sandbox: support a dedicated in-container SSH agent for headless git push 2026-07-21 23:59:52 -07:00
branderson 075f4b2ba4 claude-sandbox: build the container image tagged and configured for the real host user, fixing plugin/skill resolution 2026-07-21 21:42:57 -07:00
branderson 46f57624e6 claude-sandbox: parametrize the container user, defaulting to today's node/1000/1000//home/node 2026-07-21 21:17:41 -07:00
branderson df3399b0d3 Add Playwright/Chromium for testing frontend changes
Installs playwright + a matching Chromium build at image build time
(system deps as root via install-deps, npm package + browser binary as
node so they land in node's own npm prefix/cache), so a session never
needs network access for either. NODE_PATH makes require("playwright")
work from any script, not just one with its own local node_modules -
global npm install alone only puts the CLI on PATH.

Testing against a project's own local dev server needs no firewall
changes: localhost traffic never goes through the egress firewall.
Verified the firewall does apply to the browser's own traffic for
anything else, the same as curl/git - a non-allowlisted domain gets
blocked from inside Playwright too, not silently bypassed, while an
allowlisted one still works.

Chromium's own internal sandbox is documented honestly rather than
assumed either way: it launches without --no-sandbox and without error,
but its setuid helper isn't actually setuid here, and this host has the
same unprivileged-userns restriction that blocks bubblewrap - so it's
likely not providing real isolation, just not hard-failing about it the
way bubblewrap does. Not treated as a security boundary regardless: this
container is already the boundary, and a compromised session already has
full node-level bash access that a Chromium exploit couldn't exceed.

Test suite grew to 29: Playwright is installed and require()-able, it
actually launches and renders (not just installs), and the firewall
applies to its traffic.
2026-07-20 17:32:07 -07:00
branderson 7267e1ca77 Carry git identity into the sandbox; warn on an empty ssh-agent
Git commits inside the sandbox need a user.name/user.email. Carries over
a throwaway copy of the host's ~/.gitconfig, generated by bin/claude-sandbox
and mounted as its own directory (not the real file, and not a single-file
bind mount at ~/.gitconfig) with GIT_CONFIG_GLOBAL pointing git at the file
inside it.

That took two iterations to get right, both caught by actually testing gh
auth setup-git (the thing that makes GitHub read-only from in here) rather
than just checking the identity resolved:
- Mounting the real file read-only broke gh auth setup-git outright, which
  needs to *write* a credential-helper entry into the global gitconfig
  ("could not write config file: Device or resource busy").
- Mounting a read-write *copy* of the file directly at ~/.gitconfig hit the
  exact same error - a single-file bind mount can't have its backing inode
  replaced, and git config writes via the usual write-temp-then-rename
  pattern. Only a directory mount, with git pointed at a file inside it,
  actually supports that.
Verified end to end this time: gh auth setup-git completes cleanly, the
credential-helper entries land in the sandbox's copy, user.name/email
resolve correctly, and the real host ~/.gitconfig is untouched throughout.

Also has bin/claude-sandbox warn (non-fatally) at launch if ssh-agent has
zero identities loaded - the forwarded socket still connects fine either
way, but git-over-ssh silently fails until a key's been ssh-add'ed, which
otherwise only surfaces confusingly deep into a session as a failed push.
Confirmed the forwarding mechanism itself works correctly by testing with
a throwaway key - the reported failure was the host agent having no
identities loaded, not a bug in the forwarding.

Test suite grew to 26 with a check for the gitconfig mount shape.
2026-07-20 01:03:20 -07:00
branderson 7249da8fc3 Add a Go toolchain to the sandbox
Installs the latest stable Go release, fetched and verified the same way
as gosu: go.dev's own release JSON gives both the download URL and a
SHA256 per file, checked before extracting since this runs as root.

Also allowlists proxy.golang.org and sum.golang.org (Go's module proxy and
checksum database) - go build/go mod download need them reachable at
runtime, same as registry.npmjs.org/pypi.org for npm/pip.

Verified end to end: go version, and a real `go mod tidy` + `go run`
against an actual module (rsc.io/quote, pulling in transitive
dependencies) through the real firewall - not just that the binary
installs. All 25 existing tests still pass.
2026-07-20 00:19:27 -07:00
branderson 0c3c3aacad Disable Claude Code's internal sandbox in claude-sandbox; fix worktree location
Claude Code's own per-command sandboxing (~/.claude/settings.json's
"sandbox" block) is redundant on top of this container - which is already
a real, working sandbox on its own - and it couldn't even function here
anyway (bwrap can't create a namespace on this host; even CAP_SYS_ADMIN
only got it to a mount-propagation error, not further). Rather than
leaving it half-broken, disable it properly: settings.json is mounted
read-only specifically so a session can't tamper with it, so it can't be
patched from inside - bin/claude-sandbox now generates a sandbox-specific
copy (real settings.json with sandbox.enabled forced to false) on the
host and mounts that instead. bubblewrap/socat (added for this last
commit, never actually working) are removed - nothing needs them now.

Also fixes a real bug found in the same session: sandbox-context.sh told
agents to worktree via `git worktree add ../<branch>`, a sibling of the
mounted project directory. That path isn't backed by real host storage -
only the exact bind-mounted directory is - so a worktree created there
(observed landing under /home/node/<branch> in practice) silently
disappears, along with whatever work went into it, when the container
exits. Now instructs `.worktrees/<branch>` under the project root instead,
plus a .git/info/exclude entry so it doesn't clutter the user's real
checkout's git status.

Test suite extended to 25: sandbox.enabled=false generation, no
bubblewrap/socat, and no worktree instruction pointing outside the mounted
project. All pass.
2026-07-20 00:06:15 -07:00
branderson 0b7857eb3f Mount ~/specs read-write; add bubblewrap/socat (partial fix)
~/.claude/CLAUDE.md (already carried into the container) tells agents to
write specs to ~/specs/ instead of a project-local path - that instruction
was already in effect inside the sandbox, but nothing mounted the
directory it points at, so an agent following it would write into a path
that vanishes with the container. Bind-mounted read-write at the fixed
host path ~/specs (auto-created if missing), same pattern as the shared
scratch space but not configurable - it's tied to the CLAUDE.md
convention, not a per-run choice.

Also adds bubblewrap/socat, which Claude Code checks for before offering
its own internal per-command sandboxing and /remote-control. This clears
the "Sandbox disabled: dependencies are missing" warning, but doesn't
actually fix /remote-control: bwrap still can't create a namespace on this
host ("kernel does not allow non-privileged user namespaces"), and even
adding CAP_SYS_ADMIN to the container only got further to a mount-
propagation permission error, not further progress. Making it actually
work would need privilege escalation approaching full --privileged mode,
which would undo most of this session's hardening - not pursued. Kept the
packages anyway since they at least make the startup warning accurate
rather than noise, in case a future decision revisits this tradeoff.

All 22 existing tests still pass.
2026-07-19 23:45:01 -07:00
branderson 832aaef3d8 Add a bats test suite for the sandbox's security invariants
Addresses the "no regression protection" gap called out in Security notes:
everything there was hand-verified at a point in time, with nothing to
catch a future change silently breaking one of those properties again -
which had already happened once (the ipset -exist bug hit twice, on two
different ipsets, before being caught).

entrypoint.sh gets a SANDBOX_TEST_MODE hook: run the real DNS-proxy/
firewall/logging setup exactly as normal, then exec `sleep infinity` as
node instead of nvim (which needs a real tty). Lets the suite attach to a
live, fully-initialized container and assert against it, rather than
reimplementing the setup sequence in the test file where it could drift
out of sync with the real thing.

test/static.bats: fast, no Docker required - sudo/sudoers absence, every
ipset add is duplicate-safe, no docker.sock/host-credential mounts, the
~/.claude read-only overlay lines are present, claude-sandbox-allow's
input validation.

test/runtime.bats: builds the image, boots a container in test mode,
asserts IPv6 is blocked, DNS/IP allowlist enforcement in both directions,
GitHub read-only, no working sudo/iptables/init-firewall.sh as node,
capabilities are actually stripped (not just absent because docker exec
doesn't have them to begin with), ulogd2 runs unprivileged, and the
dynamic-ipset CDN-rotation fix actually re-syncs on a fresh DNS answer.

Container/network names are derived from bats' own BATS_FILE_TMPDIR rather
than $$ (caught via a real failure: bats reruns each file's top-level code
in a fresh subshell per test, so $$ differs across setup_file/tests/
teardown_file, silently pointing them at different, nonexistent
containers - several tests "passed" only because asserting failure against
a missing container also happens to return nonzero). BATS_FILE_TMPDIR is
guaranteed stable across the whole file's run, verified directly before
relying on it.

All 22 tests pass cleanly against the current sandbox.
2026-07-19 22:08:15 -07:00
branderson d7858d9579 Document sandbox threat model and tradeoffs honestly in README
Adds an explicit threat-model framing to Security notes: this reduces
blast radius for a compromised/prompt-injected session, it isn't a hard
adversarial boundary. Names the gaps that weren't written down anywhere -
the mounted project has no write protection (hooks are fast-fail regex
guards, not a security boundary), allowlisting a domain doesn't stop
exfiltration via that service's own request surface, this is container-
level isolation sharing the host kernel rather than VM-level, and none of
this is regression-tested going forward, only hand-verified at a point in
time.

Also fixes a real internal LAN IP (the Loki example) that had ended up in
this public repo as a "for instance" - swapped for a placeholder hostname.
2026-07-19 20:46:52 -07:00
branderson 0f3e2c8362 Add cowsay/fortune, auto-open Claude Code, and a shared scratch volume to sandbox
cowsay/cowthink/fortune install to /usr/games on Debian, not on this image's
PATH by default - added the packages and extended PATH via ENV so nvim's
start-screen header (plugins/ui.lua) can actually find them as non-login
subprocesses. That surfaced a real, pre-existing bug in ui.lua itself
(unrelated to the sandbox): `cowsay -l` wraps cow names across multiple
space-separated lines after a header line, but the code treated each whole
line as a single cow name, so a wrapped line got passed to cowthink -f as
one bogus multi-word argument. Fixed to parse every name from every line.
Verified directly against the real cowsay/fortune installed in the image.

The sandbox now opens claudecode.nvim's terminal on startup (CLAUDE_SANDBOX-
gated, so this doesn't affect normal host nvim use) instead of requiring
<leader>ac - starting a Claude session is the point of being in there.
:ClaudeCode is only defined once the plugin loads (it's lazy-loaded on that
keymap, no `cmd` in its spec), so the autocmd force-loads it first.

Also adds an optional read-write scratch volume (~/shared in the container,
$SANDBOX_SHARE_DIR on the host, auto-created) separate from the project
mount, for passing files back and forth with a sandboxed session without
touching the actual project checkout. Mentioned in sandbox-context.sh so a
sandboxed agent knows it's there.
2026-07-19 19:11:12 -07:00
branderson a86fefc663 Fix firewall init crash on overlapping GitHub CIDR ranges
Same class of bug as 718f6b7, on the newer github-domains ipset that
didn't exist yet at the time of that fix: aggregate -q dedupes overlapping
ranges within each of GitHub meta's web/api/git lists individually, but not
necessarily across all three combined once merged, so ipset add without
-exist could hit a duplicate and error - which set -e turns into the whole
firewall, and thus the whole container, failing to start with no clear
error surfaced to the user. Reproduced against live GitHub meta data
(exactly what was seen), fixed with -exist, and reran the same firewall
init end to end to confirm it now completes.
2026-07-19 18:16:40 -07:00
branderson 5294e72a32 Keep sandbox firewall ipsets fresh and batch Loki log shipping
init-firewall.sh's ipset population was a one-time snapshot at container
start: an already-allowed domain could still start failing to connect
later if its CDN edge rotated to an IP that was never added
(pypi.org/files.pythonhosted.org/GitHub's release-assets CDN all do this),
and allowing a domain like crates.io didn't help traffic that actually
goes to a different hostname under it (index.crates.io/static.crates.io).

dns-proxy.sh's dnsmasq now also uses --ipset= so the resolved IP gets added
on every fresh answer it serves for the life of the session, not just once
at boot - verified this actually repopulates after a real (non-cached)
re-resolution, and that dnsmasq tolerates the target ipset not existing yet
when its config is generated (it runs before init-firewall.sh creates it).

Also batches log-shipper.sh's Loki pushes (up to 20 lines or 2s, whichever
first) instead of one HTTP request per line - a burst of activity (e.g.
npm install resolving/connecting to many hosts quickly) would otherwise
spam Loki with one request per line. Verified via the sandbox's own
connection logging: 15 rapid lines produced 2 requests instead of 15.
2026-07-19 18:09:16 -07:00
branderson 07926638d4 Add ulogd user 2026-07-19 17:58:24 -07:00
branderson 04c1b1e1f4 Add DNS allowlisting, IPv6 block, and network logging to sandbox
DNS resolution was previously unrestricted - only the resulting IP
connections were firewalled - so a compromised session could still
exfiltrate data by encoding it into query names to an attacker-controlled
domain. dns-proxy.sh now runs a local dnsmasq with no fallback resolver;
only allowlisted names (shared with init-firewall.sh via fixed-domains.sh)
get forwarded, everything else is refused outright.

IPv6 is blocked outright via ip6tables DROP-all, since there was no IPv6
equivalent of the IPv4 allowlist.

If LOKI_URL is set, every DNS query and every new outbound connection
attempt (allowed or rejected, via NFLOG + ulogd2) ships to Loki as JSON,
for visibility in the existing Grafana/Prometheus setup.

Also fixes two bugs found along the way:
- init-firewall.sh's script-wide IFS (set for stricter splitting elsewhere)
  silently broke EXTRA_ALLOWED_DOMAINS whenever it held more than one
  space-separated entry, collapsing it into a single bogus token.
- bin/claude-sandbox-allow interpolated the domain argument directly into a
  bash -c string executed via docker exec - a command injection path,
  since sandbox-context.sh tells a sandboxed agent to hand this exact
  command to the user to copy-paste. Fixed with upfront domain validation
  and positional-argument passing instead of string interpolation.
2026-07-19 17:16:55 -07:00
branderson b4d22b97c0 Add quick allowlist for domains in sandbox 2026-07-19 16:26:58 -07:00
branderson 4551dc5a59 Limit push privileges 2026-07-19 16:10:47 -07:00
branderson ca76b46750 Lock down .claude in sandbox 2026-07-19 13:45:35 -07:00
branderson 373655963a Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2026-07-19 13:07:03 -07:00
branderson fae504043e Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2026-07-19 13:03:55 -07:00
branderson bdb8c8b149 Fix profile scope issue 2026-07-19 13:03:32 -07:00
branderson d76d2f4b3a Fix clipboard OSC 52 fallback: walk past nvim's tty-less embed process
Nvim isn't a single process attached to the terminal: the process that
actually spawns jobs (clipboard-copy included) is a separate `nvim --embed`
core process with no tty of its own (ps shows `?`); the real pty belongs to
a distinct parent UI process. Checking only the immediate parent's tty (as
the previous fix did) found the embed process's `?` and fell through to the
broken /dev/tty path every time in real interactive use, even though it
looked fine in headless testing. Walk up the process tree past any tty-less
ancestors instead.

Verified against the real docker-compose path in actual (non-headless) TUI
mode, with real keystrokes fed through a pty: the OSC 52 sequence now
reaches the terminal with no error, where it previously still failed.
2026-07-19 11:46:31 -07:00
branderson 08a2ae52f1 Fix clipboard OSC 52 write and mason registry access in the sandbox
- clipboard-copy: nvim's job-spawned clipboard provider process doesn't get
  its own controlling terminal, so /dev/tty (ENXIO) fails. Resolve the real
  tty from the parent (nvim)'s recorded tty via ps instead.
- entrypoint.sh: chown the allocated pty to node before dropping privileges.
  A normal login/ssh session always does this; this entrypoint skipped it,
  leaving the tty root-owned so node couldn't write to it directly even
  after resolving the right path.
- init-firewall.sh/README: allow release-assets.githubusercontent.com.
  GitHub release assets (e.g. mason-registry's own index) redirect here,
  a separate CDN from github.com's published IP ranges - without it mason
  can't even look up a package's install spec, regardless of PyPI access.

All three verified against a rebuilt image: OSC 52 write reaches the real
pty with no error, and mason's registry refresh succeeds through the
firewall.
2026-07-19 04:08:14 -07:00
branderson 718f6b7600 Fix firewall init crash on overlapping IPs across allowlisted domains
pypi.org and files.pythonhosted.org share Fastly edge IPs, so the second
domain's ipset add hit a duplicate-element error. Without -exist, that
error plus set -e killed the whole firewall init (and thus the container)
before nvim ever started. Reported by the user as a silent hang after a
successful build.
2026-07-19 03:31:50 -07:00
branderson 18e111b00c Fix sandbox dotfiles path, terminal type, and PyPI access
- Bind-mount dotfiles at node's own $HOME/dotfiles too, not just the
  host-path mount needed for the ~/.claude/hooks symlink: node's $HOME is
  /home/node, which broke clipboard-copy and anything else in this repo
  assuming ~/dotfiles.
- Forward the host's real TERM into the container instead of letting
  Docker's tty allocation default to a generic xterm, which was breaking
  the Ctrl-H/Backspace disambiguation the tmux config sets up.
- Add pypi.org/files.pythonhosted.org to the firewall's default allowlist
  so mason's pip-installed Python tools (ruff, basedpyright, debugpy) can
  actually install; verified with a real venv pip install.
2026-07-19 03:23:11 -07:00
branderson a2be0e5678 Sandbox hardening 2026-07-19 02:43:17 -07:00
branderson b5e18a1b29 Fix mount path 2026-07-19 01:50:38 -07:00
branderson e0ce0e79fc Fix allowlist of domains 2026-07-19 01:33:31 -07:00
branderson bcc0d4ab14 Fix permissions issue 2026-07-19 01:01:41 -07:00
branderson 37e77a4c30 Add claude code container sandbox 2026-07-19 00:30:05 -07:00
branderson 93b93b30b8 Fix Ctrl+J in claude code 2026-07-18 17:22:48 -07:00
branderson 49c638cda8 Re-enable extended keys 2026-07-18 17:15:46 -07:00
branderson efd1ddebd9 Fix corruption in copy-paste over nested tmux 2026-07-18 16:03:19 -07:00
branderson ea5a2b77d4 Fix some stale comments 2026-07-17 16:34:37 -07:00
branderson bd4d579a90 Fix remote tmux copy 2026-07-17 16:02:43 -07:00
branderson 0ba29f8d89 Fix clipboard copy across terminal emulator -> tmux -> SSH -> tmux -> nvim 2026-07-17 15:13:40 -07:00
branderson 25dcfc6802 Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2026-07-17 14:05:13 -07:00
branderson a56e04a0aa Make alacritty's highlight copy to system clipboard 2026-07-17 14:05:00 -07:00
asphodel 1ec5e0258d Add htop and jq to apt globals 2026-07-17 13:15:53 -07:00
branderson 1caa1be1d2 Support <Shift><Enter> through multiple nested tmux's and alacritty 2026-07-17 12:51:53 -07:00
branderson aa71eebf0b Fix nvim errors when editing html 2026-07-16 14:39:28 -07:00
branderson 9987dcacd8 Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2026-07-14 21:12:17 -07:00
branderson 58a3512c28 Disable claude-code systemd limits 2026-07-14 21:11:35 -07:00
branderson 7b61fde6e9 Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2026-07-14 19:45:30 -07:00
branderson db267226a8 Enable sixel for iTerm2 2026-07-14 18:39:48 -07:00
branderson 521c1b1c4d Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2026-07-14 18:08:06 -07:00
branderson a94e283e98 Add sandboxing tools to global install 2026-07-14 18:07:59 -07:00
branderson b26e564672 Use cargo build instead of prebuilt binary for tree-sitter-cli manual install 2026-07-14 14:23:06 -07:00
branderson 1deb25008f Make nvim installation helpers platform-aware and add local install helper for tree-sitter-cli 2026-07-14 14:11:42 -07:00
branderson 9ffe754410 Add claude gruvbox theme, fix nvim errors with custom npm 2026-07-14 13:48:36 -07:00
branderson d0a4cb0db7 Add authorship disclaimer to LLM generated PR summaries 2026-07-13 18:28:08 -07:00
branderson 46ca53e0c0 Prevent runaway claude-code 2026-07-13 18:24:22 -07:00
branderson ddd7f6bf2c Merge pull request 'gitea-pr: token-file auth + skip duplicate PR creation' (#2) from worktree-gitea-pr-review-workflow into master
Reviewed-on: #2
2026-07-12 22:15:01 -07:00
branderson 06e60bda8c Match existing-PR check on base branch too, not just head
The lookup was matching on head.ref alone, so running create with a
different --base for the same branch would silently return an
unrelated PR's URL instead of opening a new one. Resolve base before
the check and filter on both head.ref and base.ref.
2026-07-12 22:14:07 -07:00
branderson 567d0a1718 Skip creating a duplicate PR when one is already open for the branch
gitea-pr create now checks for an existing open PR on the current
branch first and returns its URL instead of creating a new one. Only
matches open PRs by design -- once merged, new commits on the same
branch correctly get a new PR.
2026-07-12 22:14:07 -07:00
branderson eec71b5f82 Add gitea-pr script and PR review workflow (#1)
Adds bin/gitea-pr script for gitea PR workflow.
Reviewed-on: #1
Co-authored-by: Brad Anderson <brad@branderson.io>
Co-committed-by: Brad Anderson <brad@branderson.io>
2026-07-12 18:49:36 -07:00
branderson 4e8c3c6269 Add keybind to fix missing cursor after SSH timeout in tmux 2026-07-11 13:11:14 -07:00
branderson 8badfdb9b8 Fix copy-paste in tmux 2026-07-10 19:10:41 -07:00
branderson 1eb4ee50d8 Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2026-07-10 18:36:42 -07:00
branderson 5bf98d5b1d Make ,, work in terminal mode nvim 2026-07-10 18:36:30 -07:00
branderson 90d67c5a4a Fix file modification issue in non-modifiable nvim buffers 2026-07-10 17:16:28 -07:00
branderson ad9a5072d3 Handle shellcheck cleanly in vim 2026-07-10 16:26:09 -07:00
branderson c6c51c81ef Improve <leader>? keybind search 2026-07-10 16:21:34 -07:00
branderson f318cd953f Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2026-07-10 16:04:27 -07:00
branderson f75adf42ae Add nvim debugging for python 2026-07-10 16:04:12 -07:00
branderson 192b457c61 Add new nvim deps to apt.global 2026-07-10 15:43:45 -07:00
branderson 0d3260dab1 Fix issues when nvim plugin deps aren't available and make system clipboard more consistent 2026-07-10 15:38:33 -07:00
branderson e8f6eeb8fb Fix a few nvim issues 2026-07-09 22:27:07 -07:00
branderson 3f420bf740 Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2026-07-09 21:17:17 -07:00
branderson 30effbb474 Port neovim configs from vimscript to lua 2026-07-09 21:15:47 -07:00
branderson cbda5efd3c Add tmux selection highlight for nested sessions 2026-07-03 17:34:22 -07:00
branderson baf24a5198 Merge branch 'master' of https://gitbox.branderson.io/branderson/dotfiles 2026-07-03 15:26:07 -07:00
branderson 69a3dfed30 Modernize and clean up tmux configs 2026-07-03 15:25:56 -07:00
branderson b650051b81 Add Claude Code plugin to nvim 2026-07-02 13:51:49 -07:00
Brad Anderson a0b6b93831 Merge branch 'master' of https://gitbox.branderson.io/branderson/dotfiles 2026-07-01 15:55:48 -07:00
Brad Anderson e4a76e28e9 Fix issue with profile leading to '1' files being created 2026-07-01 15:50:50 -07:00
branderson a6a9b44784 Fix picom.conf deprecated settings 2026-06-01 21:51:59 -07:00
branderson 535b6dc8f9 Add VSCodium config 2026-06-01 21:50:17 -07:00
branderson 99b90050ae Remove picom configuration which produces warnings 2026-03-19 15:05:14 -07:00
branderson 3e40b07e76 Fix Arch linux corrupted keys issues 2026-03-19 13:24:38 -07:00
branderson f849865294 Fix wallpaper updater monitor order to apply wallpapers to correct monitors 2026-01-16 17:49:47 -08:00
branderson b4ee1e28ef Add ideavimrc 2026-01-12 17:10:18 -08:00
branderson 2e3f837cbb Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2025-12-15 15:36:16 -08:00
branderson 54fee7544b Allow disabling loading SSH keys 2025-12-15 15:36:05 -08:00
branderson 1e121a3ece Backup instead of skipping existing dotfiles and disable installing templates for local dotfiles 2025-12-13 14:36:24 -08:00
Brad Anderson d1bbe70964 Fix local templates being linked and add markdown preview plugin to nvim 2025-10-21 13:32:42 -07:00
branderson 4bc636f494 Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2025-10-12 15:54:29 -07:00
branderson 340d9b725a Add better support for pyenv, set up GTK themes, and add (manually linkable for now) application shortcuts 2025-10-12 15:53:30 -07:00
branderson 80ced6b8f0 Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2025-10-09 00:54:02 -07:00
branderson 54494ca8ac Add some helper scripts for working with docker postgres 2025-10-09 00:43:15 -07:00
branderson 40b2710bad Fix automount for CIFS shares on Debian not mounting on boot 2025-10-08 18:25:58 -07:00
branderson cc7c6227d0 Change keybindings for new workspace and clipboard history 2025-10-07 19:28:25 -07:00
branderson 93a8c07a5a Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2025-10-06 01:12:28 -07:00
branderson dfa080ebb4 Add shortcut to move container to new empty workspace for i3 2025-10-06 01:12:19 -07:00
branderson 94fdec8f41 Make wallpaper autostart in i3 work 2025-10-05 17:15:01 -07:00
branderson ddf6a180cd Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2025-10-05 16:40:08 -07:00
branderson e638cd74ae Disable ohmyzsh corrections because it's more annoying than anything 2025-10-05 16:39:59 -07:00
branderson 72022f3940 Remove .profile messing with SSH_AUTH_SOCK to fix error 2025-10-05 16:31:42 -07:00
branderson ff607b428e Only use ssh-add if SSH_AUTH_SOCK set 2025-10-05 16:12:55 -07:00
branderson 0e8cfb9670 Only check for SSH keys if ssh-add available 2025-10-05 16:06:37 -07:00
branderson 4d2082994c Fix bug in AUR installer 2025-10-04 22:14:00 -07:00
branderson 2ad1035ddd Add some docker shortcut scripts to PATH 2025-10-03 23:50:01 -07:00
branderson 2a4453ac35 Create .ssh if it doesn't exist 2025-10-03 18:34:29 -07:00
branderson ac59b7b305 Make default selections clear 2025-10-03 14:03:50 -07:00
branderson f58a2ac4d3 Make /mnt/ dirs for SMB if they don't exist 2025-10-02 21:41:44 -07:00
branderson 9927dc903e Install the correct powerline through apt 2025-10-02 20:45:27 -07:00
branderson 5409a9140f Fix issue with setting ZSH as default 2025-10-02 20:21:11 -07:00
branderson 6f929ee958 Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2025-10-02 20:13:07 -07:00
branderson 4fe6c591f2 Add zsh to global apt packages 2025-10-02 20:11:40 -07:00
branderson 39fd88d207 Add fstab management for SMB configuration 2025-10-02 19:45:33 -07:00
branderson 9cedb773a6 Fix some issues in install complete 2025-10-02 18:02:09 -07:00
branderson a2a5666d75 Clean up bin and add better i3 output control 2025-10-01 21:10:47 -07:00
branderson b47a893e4b Fix firewalld reload when installing gpu-monitoring 2025-09-29 18:51:06 -07:00
branderson fb1eea31ae Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2025-09-28 20:36:47 -07:00
branderson 372ebf45a1 Add dotfiles-install option to install Nvidia GPU monitoring 2025-09-28 20:36:37 -07:00
branderson 7134b55487 Fix powerline in non-default dotfiles directory 2025-09-27 14:05:18 -07:00
branderson cb5e2ced19 Fix wallpapers in i3 and add some functions 2025-09-27 00:29:40 -07:00
branderson 7cc0ece887 Output missing dependencies in a single line 2025-09-22 18:14:54 -07:00
branderson 874db62c5f Fix infinite loop in interactive run 2025-09-22 17:33:04 -07:00
branderson b6c656ce94 Improve interface consistency and support positional argument command 2025-09-20 02:48:19 -07:00
branderson 3381b9e54d Fix issue with using env variable before it's set 2025-09-18 01:41:32 -07:00
branderson 481bf28d44 .dotfiles-dir -> .dotfiles-config 2025-09-18 01:39:35 -07:00
branderson ca2f0e18b4 Always update submodules 2025-09-18 00:31:42 -07:00
branderson d7c60e2f7b Put installer script in PATH 2025-09-17 23:37:34 -07:00
branderson 8f2cbb62aa Use POWERLINE_ROOT without additional lookups if set and valid 2025-09-17 20:02:49 -07:00
branderson eb6633fc7e Add thefuck shell initialization 2025-09-17 13:52:42 -07:00
branderson 1ea4bcc0e4 Fix zsh powerline 2025-09-17 00:58:21 -07:00
branderson bf7621b151 Optimize installs and add support for apt powerline 2025-09-17 00:55:47 -07:00
branderson 46d487fe32 Add support for apt powerline 2025-09-17 00:24:36 -07:00
branderson 7d31673399 Fix local-dotfiles clone initial branch 2025-09-16 23:55:54 -07:00
branderson 13d19cb8fc Fix powerline bash setup to support bash 3.2 without global array support 2025-09-16 17:34:19 -07:00
Brad Anderson ff49aba967 Make powerline support python virtualenvs without breaking prompt 2025-09-16 17:12:05 -07:00
branderson ec7c0acadc Fixing some dotfiles-local output 2025-09-16 12:26:47 -07:00
branderson 0ec2d1f6ce Use return values rather than output for bash functions 2025-09-16 12:12:36 -07:00
branderson 54db5b59be Fix SSH agent issues 2025-09-16 11:11:22 -07:00
branderson 388ec2ef7f Make function returns comply to POSIX and differ output if existing dotfiles are links or files/dirs 2025-09-16 10:35:52 -07:00
branderson e6444f9f86 Merge branch 'master' of https://gitbox.branderson.io/branderson/dotfiles 2025-09-16 08:40:52 -07:00
branderson 91318a32ad Add tmux and nvim local configurations 2025-09-16 08:40:33 -07:00
branderson 2df4cc4c30 Remove dotfiles-local submodule for real 2025-09-15 23:35:44 -07:00
branderson 095da7e302 Fix some issues 2025-09-15 23:31:40 -07:00
branderson 2dda647ba6 Generalize public keys to check for 2025-09-15 22:02:59 -07:00
branderson d82f92d52c Make dotfiles-local not a submodule and reorganize zshrc and profile 2025-09-15 21:10:03 -07:00
Brad Anderson 6b91a5053b Fix bash dependencies 2025-09-15 17:44:12 -07:00
branderson f9890fb2bd Support mac SSH key loading in .profile and skip ssh-add if no public keys found 2025-09-15 13:09:44 -07:00
branderson d2c73a5b48 Set correct default dotfiles-local branch 2025-09-15 12:57:08 -07:00
branderson 5f8d9c1047 Add fzf dependency, bash powerline, only ssh-add if not in keyring already 2025-09-14 01:40:55 -07:00
branderson a6d895dedf Clean up and reorganize zshrc 2025-09-13 21:24:32 -07:00
branderson cde4f66571 Fix dotfiles-local empty spaces in output 2025-09-13 20:25:58 -07:00
branderson 233378d20c Fix issue with submodule initialization in non-interactive run 2025-09-13 20:12:37 -07:00
branderson 7217ce8a41 Fix non-interactive dotfiles-local and skip pushing branch if no local changes 2025-09-13 18:43:55 -07:00
branderson 6d8f3594d7 Remove fixed TODO 2025-09-12 23:32:39 -07:00
branderson 48111eecbd Make sure dotfiles-local branch off main branch initially 2025-09-12 23:25:01 -07:00
branderson cced83f09b Fix issues with dotfiles-local 2025-09-12 12:59:57 -07:00
branderson c20eeab2cc Add local dotfiles management system 2025-09-12 01:20:00 -07:00
branderson bb1c607a29 Merge branch 'master' of gitbox.bradina.localdomain:branderson/dotfiles 2025-09-09 19:14:45 -07:00
branderson 6dc3dc7b2d Install coder option 2025-09-09 19:14:35 -07:00
branderson ca009bc794 Add support for mac 2025-09-09 17:48:49 -07:00
Brad Anderson 72d1fbcd16 Add bashrc and bash_profile 2025-09-08 14:31:12 -07:00
branderson 0a75d65f01 Fix setting wallpaper on startup 2025-09-06 18:00:19 -07:00
branderson 8fc175077c Update default config and respect config 2025-08-31 07:36:34 +00:00
branderson dd60653474 Move zshrc PATH assignment up-front for commands 2025-08-31 00:31:16 -07:00
branderson 8382c423f0 Silence output from git fetch 2025-08-31 00:26:07 -07:00
branderson a26151086d Extend PATH 2025-08-31 00:24:34 -07:00
branderson cd8aaae817 Fix sh issue 2025-08-31 00:16:28 -07:00
branderson b434313676 Add toggles for zsh startup behavior with sane defaults 2025-08-31 00:11:59 -07:00
branderson 8b79f58be4 Fix zsh configs when ~/.dotfiles-dir not set 2025-08-30 23:36:48 -07:00
branderson caa3d4a286 Automatic configuration of dotfile-dir on install 2025-08-31 03:12:03 +00:00
branderson 6d43be3029 Add initial git submodule update in zshrc 2025-08-30 19:47:42 -07:00
branderson ba6d9aeefd Add dotfiles-dir environment variable support and dotfile 2025-08-30 19:43:16 -07:00
branderson fdcb5de550 Fix local-templates install 2025-08-30 19:21:58 -07:00
branderson e4421bb2f0 Make powerline config sourcing automatic 2025-08-31 02:15:39 +00:00
branderson 27296ea69f Fix local template install 2025-08-30 14:33:06 -07:00
branderson 0d854ac137 Fix vim-plugged plugin directory 2025-08-29 14:55:53 -07:00
branderson a7101ebab8 Fix non-interactive run and add additional apt packages 2025-08-29 14:48:15 -07:00
branderson c9f242178b Fix some issues 2025-08-26 22:06:16 -07:00
branderson 7c765d0cf0 Support non-interactive install 2025-08-26 21:57:46 -07:00
branderson 0d9eafcaab Automatically set wallpapers on display change and at login 2025-08-08 19:49:51 -07:00
branderson 2a8051c68b Update wallpaper script to detect display layout and set wallpapers appropriately 2025-08-08 15:20:44 -07:00
branderson 60b126a4d1 Pipx support and changes from laptop 2025-06-29 15:51:47 -07:00
branderson 85c649acab Fix for gnome-keyring in i3 2025-06-29 15:25:36 -07:00
branderson a7d521917a Various fixes, wallpaper script, fix notebook 2025-05-06 13:43:08 -07:00
branderson 506a85843d Merge branch 'master' of https://github.com/branderson/dotfiles 2024-09-09 20:19:38 -07:00
branderson a31646fcd5 Fix enabling ssh-agent for root instead of user 2024-09-09 20:19:13 -07:00
branderson f5679802d5 Add some more apt packages 2024-08-31 15:56:57 -07:00
branderson 950231154b Add initial configs for apt-based systems 2024-08-31 15:50:51 -07:00
branderson 0276ace6df Add SSH key setup and distribution and monitoring/ssh scratchpads 2024-04-01 19:11:14 -07:00
branderson 1267a1eb17 Add monitoring window in scratchpad 2024-03-15 20:39:24 -07:00
branderson ee34303cb0 Add powerline gruvbox colorscheme 2024-03-14 14:10:21 -07:00
branderson 0277d42a7b Add gruvbox powerline and local config template setup 2024-03-14 13:57:25 -07:00
branderson b3fa0242b0 Create i3 desktop environment overrides folder if it doesn't exist 2024-03-12 17:08:14 -07:00
branderson 324716c7bd Fix i3 config issue and add local i3 config support 2024-03-12 16:29:24 -07:00
branderson 259b10c061 Fix wayland-sessions install and check for plasma/bare-i3 configs before linking 2024-03-12 16:14:37 -07:00
branderson 59cfcb76e2 Add support for picking between plasma + i3 or i3 alone 2024-03-12 16:04:53 -07:00
150 changed files with 7791 additions and 838 deletions
+8 -2
View File
@@ -1,10 +1,16 @@
existing
minimal
*.local
install_local.sh
bin/dotfiles-install
config/dejima
config/i3/config.de
config/i3/config.local
config/gtk-3.0/bookmarks
config/xfce4/xfconf/xfce-perchannel-xml
config/xfce4/terminal
config/powerline
config/themes
config/icons
config/VSCodium
dependencies/dotfiles-local
packages/*.local
.claude
+9
View File
@@ -16,3 +16,12 @@
[submodule "dependencies/gruvbox"]
path = dependencies/gruvbox
url = https://github.com/morhetz/gruvbox
[submodule "config/tmux/plugins/tpm"]
path = config/tmux/plugins/tpm
url = https://github.com/tmux-plugins/tpm
[submodule "dependencies/fzf"]
path = dependencies/fzf
url = https://github.com/junegunn/fzf.git
[submodule "config/tmux/plugins/tmux-fzf"]
path = config/tmux/plugins/tmux-fzf
url = https://github.com/sainnhe/tmux-fzf
+64
View File
@@ -0,0 +1,64 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Update all locally existing PGP keys in pacman's gnupg keyring, that are
# relevant for Arch Linux packaging using the distribution's Web Key Directory
# (WKD).
# This ensures, that new signatures on already existing keys are fetched before
# a new version of archlinux-keyring is installed. Fetching signatures early
# prevents marginal trust issues with packages that are signed by keys which
# only gain full trust when updating to a new version of archlinux-keyring in
# that same system upgrade action.
set -eu
readonly main_key_domain_match="@master-key.archlinux.org$"
readonly packager_domain_match="@archlinux.org$"
readonly homedir="$(pacman-conf GPGDir)"
domain_match=""
uid=""
gpg_locate_external=(
# force update a key using WKD
gpg
--homedir
"$homedir"
--quiet
--no-permission-warning
--auto-key-locate
"clear,nodefault,wkd"
--locate-external-keys
)
# a list of <fingerprint> <mbox> tuples of all keys in the keyring
# e.g.:
# C7E7849466FE2358343588377258734B41C31549 dvzrv@archlinux.org
# 8FC15A064950A99DD1BD14DD39E4B877E62EB915 svenstaro@gmail.com
fingerprint_mboxes="$(
gpg --homedir "$homedir" --no-permission-warning --list-keys --list-options show-only-fpr-mbox
)"
# a list of <fingerprints> of all revoked keys and keys that have no valid main
# key signatures
old_fingerprints="$(
gpg --homedir "$homedir" --no-permission-warning --list-keys --with-colons |
awk -F: '$1 == "pub" && $2 ~ /-|q|r/ { getline; print $10 }'
)"
if (( EUID != 0 )); then
printf "This script must be run as root.\n" >&2
exit 1
fi
# first update the main signing keys, then the packager keys
for domain_match in "$main_key_domain_match" "$packager_domain_match"; do
while read -ra fpr_email; do
if [[ ${fpr_email[1]} =~ $domain_match && ! "$old_fingerprints" =~ ${fpr_email[0]} ]]; then
printf "Refreshing key %s with UID %s...\n" "${fpr_email[0]}" "${fpr_email[1]}"
"${gpg_locate_external[@]}" "${fpr_email[1]}"
else
printf "Skipping key %s with UID %s...\n" "${fpr_email[0]}" "${fpr_email[1]}"
fi
done <<< "$fingerprint_mboxes"
done
+45
View File
@@ -0,0 +1,45 @@
#!/bin/sh
# Copy stdin to the system clipboard, regardless of platform or how deep in
# ssh/tmux this shell is: prefer a local clipboard tool for the current
# display server, and fall back to a single plain OSC 52 write when no local
# tool is available (e.g. a headless remote host). Any tmux hops in between
# here and the real terminal relay that onward themselves, recursively, via
# the pane-set-clipboard hook in tmux.conf -- this doesn't need to know or
# guess how many hops there are.
if command -v pbcopy >/dev/null 2>&1; then
exec pbcopy
elif [ -n "$WAYLAND_DISPLAY" ] && command -v wl-copy >/dev/null 2>&1; then
# wl-copy/xclip both hold the selection by staying alive as a background
# process (X11/Wayland selections have no central store -- the owner has
# to serve paste requests live). setsid -f detaches that process from
# our session so tmux's copy-pipe job cleanup can't kill it right after.
setsid -f wl-copy
elif [ -n "$DISPLAY" ] && command -v xclip >/dev/null 2>&1; then
setsid -f xclip -selection clipboard
else
data=$(base64 | tr -d '\n')
# /dev/tty needs this process's own session to have a controlling
# terminal, but a job spawned by nvim's clipboard provider doesn't get
# one (nvim's job-spawning doesn't establish a ctty for children). Nvim
# itself also isn't a single process: the one actually spawning jobs is
# a `nvim --embed` core process with no tty of its own (shown as `?` in
# ps) -- the real terminal belongs to a separate parent UI process. Walk
# up the process tree past any tty-less ancestors to find it.
real_tty=""
pid="$PPID"
i=0
while [ "$i" -lt 10 ] && [ -n "$pid" ] && [ "$pid" != "0" ]; do
t=$(ps -o tty= -p "$pid" 2>/dev/null | tr -d ' ')
if [ -n "$t" ] && [ "$t" != "?" ]; then
real_tty="/dev/$t"
break
fi
pid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ')
i=$((i + 1))
done
if [ -n "$real_tty" ] && [ -w "$real_tty" ]; then
printf '\033]52;c;%s\a' "$data" > "$real_tty"
else
printf '\033]52;c;%s\a' "$data" > /dev/tty
fi
fi
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
docker compose pull
docker compose down
docker compose up -d
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
docker compose down
docker compose up -d
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
find . -type f -name "docker-compose.y*ml" -exec dirname {} \; | while read dir
do
if [[ "$dir" != *"DEPRECATED"* ]] && [[ "$dir" != *"MIGRATED"* ]] ; then
pushd "$dir"
docker compose down
docker compose pull
docker compose up -d
popd
fi
done
+255
View File
@@ -0,0 +1,255 @@
#!/bin/bash
# Read and write Gitea issues from a shell - the issue-side counterpart to
# gitea-pr, and deliberately its twin rather than its sibling: both are
# copied into the sandbox image as single self-contained files, and gitea-pr
# also lives in a dotfiles checkout, so a shared library would be a third
# thing to keep in step across three places. The duplicated config/token/curl
# preamble is pinned in both files by test/static.bats instead.
set -euo pipefail
GITEA_TOKEN_FILE="${GITEA_TOKEN_FILE:-$HOME/.config/gitea/token}"
function usage() {
echo "Usage: gitea-issue list [--state open|closed|all] [--limit N]"
echo " gitea-issue view NUMBER"
echo " gitea-issue create --title TITLE [--body BODY | --body-file FILE]"
echo " gitea-issue comment NUMBER (--body BODY | --body-file FILE)"
echo " gitea-issue close NUMBER"
echo " gitea-issue reopen NUMBER"
echo ""
echo "--body-file reads the body from FILE, or from stdin when FILE is '-'."
echo "Prefer it over --body for anything with quotes, backticks or newlines."
echo ""
echo "Requires GITEA_SSH_HOST and GITEA_API set in the environment (e.g. in" \
"your shell profile), and a token at $GITEA_TOKEN_FILE (or GITEA_TOKEN" \
"set for this invocation only)."
}
function require_config() {
if [ -z "${GITEA_SSH_HOST:-}" ]; then
echo "GITEA_SSH_HOST is not set. Add 'export GITEA_SSH_HOST=<gitea ssh hostname>'" \
"(e.g. gitea.example.com) to ~/.profile.local" >&2
exit 1
fi
if [ -z "${GITEA_API:-}" ]; then
echo "GITEA_API is not set. Add 'export GITEA_API=https://<gitea host>/api/v1'" \
"(e.g. https://gitea.example.com/api/v1) to ~/.profile.local" >&2
exit 1
fi
}
function require_token() {
if [ -z "${GITEA_TOKEN:-}" ] && [ -f "$GITEA_TOKEN_FILE" ]; then
GITEA_TOKEN=$(<"$GITEA_TOKEN_FILE")
fi
if [ -z "${GITEA_TOKEN:-}" ]; then
echo "No Gitea token found. Generate one in the Gitea web UI" \
"(Settings > Applications, scopes write:repository + write:issue)" \
"and save it to $GITEA_TOKEN_FILE (chmod 600), or set GITEA_TOKEN" \
"in the environment for this invocation only." >&2
exit 1
fi
}
# Feeds the auth header to curl as a config on stdin rather than as an
# argument. Command lines are world-readable through /proc, so `-H
# "Authorization: token $GITEA_TOKEN"` exposes the token to every other
# process on the host for as long as the request runs - and to anything that
# scrapes `ps` output, including the agents this repo exists to sandbox.
# printf is a bash builtin, so the token never lands in another argv.
function gitea_api() {
printf 'header = "Authorization: token %s"\n' "$GITEA_TOKEN" |
curl -sS -w '\n%{http_code}' -K - "$@"
}
# Splits gitea_api's combined output into the globals `json` and `http_code`
# and fails with the body on any non-2xx. Every call site did this by hand in
# gitea-pr; there are six of them here, and six hand-rolled copies is where
# one of them quietly stops checking.
function api_or_die() {
local what="$1"; shift
local response
response=$(gitea_api "$@")
http_code=$(echo "$response" | tail -1)
json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "Failed to $what (HTTP $http_code):" >&2
echo "$json" >&2
exit 1
fi
}
# Reads a body from a file, or from stdin for '-'. The point is to keep prose
# out of argv: a body composed on a command line has to survive shell quoting,
# and the things that break it - an apostrophe, a backtick, a $ - are exactly
# what English and code fences are made of. A file (or a heredoc into '-') has
# no such layer.
function read_body_file() {
local file="$1"
if [ "$file" = "-" ]; then
cat
return
fi
if [ ! -f "$file" ]; then
echo "No such body file: $file" >&2
exit 1
fi
cat "$file"
}
function gitea_owner_repo() {
local remote_url host owner_repo
remote_url=$(git remote get-url origin 2>/dev/null) || {
echo "No 'origin' remote found in this repository" >&2
exit 1
}
host=$(echo "$remote_url" | sed -E 's#^[^@]+@([^:]+):.*#\1#')
if [ "$host" != "$GITEA_SSH_HOST" ]; then
echo "origin remote ($remote_url) is not on $GITEA_SSH_HOST; gitea-issue only supports this host" >&2
exit 1
fi
owner_repo=$(echo "$remote_url" | sed -E 's#^[^@]+@[^:]+:##; s#\.git$##')
echo "$owner_repo"
}
function require_number() {
if ! [[ "${1:-}" =~ ^[0-9]+$ ]]; then
echo "Expected an issue number, got '${1:-}'" >&2
exit 1
fi
}
# Sets `body` from --body/--body-file, rejecting both. Shared by create and
# comment so the two cannot drift into disagreeing about which one wins.
function parse_body_args() {
body=""
local body_file=""
parsed_title=""
while [ "$#" -gt 0 ]; do
case "$1" in
--title) parsed_title="$2"; shift 2 ;;
--body) body="$2"; shift 2 ;;
--body-file) body_file="$2"; shift 2 ;;
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
esac
done
# Rejected rather than ranked: silently preferring one would make a caller
# that passed both ship a body it didn't mean to.
if [ -n "$body" ] && [ -n "$body_file" ]; then
echo "Pass --body or --body-file, not both" >&2
exit 1
fi
if [ -n "$body_file" ]; then
body="$(read_body_file "$body_file")"
fi
}
if [ "$#" -lt 1 ]; then
usage
exit 1
fi
subcommand="$1"
shift
case "$subcommand" in
list|view|create|comment|close|reopen)
require_config
require_token
owner_repo=$(gitea_owner_repo)
owner="${owner_repo%%/*}"
repo="${owner_repo##*/}"
;;
*)
usage
exit 1
;;
esac
issues_api="${GITEA_API}/repos/${owner}/${repo}/issues"
case "$subcommand" in
list)
state="open"
limit="30"
while [ "$#" -gt 0 ]; do
case "$1" in
--state) state="$2"; shift 2 ;;
--limit) limit="$2"; shift 2 ;;
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
esac
done
case "$state" in
open|closed|all) ;;
*) echo "--state must be open, closed or all" >&2; exit 1 ;;
esac
if ! [[ "$limit" =~ ^[0-9]+$ ]]; then
echo "--limit must be a number" >&2
exit 1
fi
# type=issues is load-bearing: Gitea's issues endpoint returns pull
# requests too, since a PR *is* an issue with a branch attached.
# Without it every open PR shows up here as an issue, which reads as
# a work list that is quietly twice as long as the real one.
api_or_die "list issues" \
"${issues_api}?state=${state}&type=issues&limit=${limit}"
echo "$json" | jq -r '.[] | "#\(.number)\t[\(.state)]\t\(.title)\t(\(.comments) comments)"'
;;
view)
require_number "${1:-}"
number="$1"
api_or_die "fetch issue #${number}" "${issues_api}/${number}"
echo "$json" | jq -r '"#\(.number) [\(.state)] \(.title)\n[\(.user.login) @ \(.created_at)]\n\(.body // "(no description)")\n"'
echo "=== Comments ==="
api_or_die "fetch comments for issue #${number}" "${issues_api}/${number}/comments"
echo "$json" | jq -r '.[] | "[\(.user.login) @ \(.created_at)]\n\(.body)\n"'
;;
create)
parse_body_args "$@"
if [ -z "$parsed_title" ]; then
echo "gitea-issue create requires --title" >&2
exit 1
fi
body="**Filed by LLM agent**
${body}"
api_or_die "create issue" -X POST "$issues_api" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg title "$parsed_title" --arg body "$body" \
'{title: $title, body: $body}')"
echo "$json" | jq -r '.html_url'
;;
comment)
require_number "${1:-}"
number="$1"
shift
parse_body_args "$@"
if [ -z "$body" ]; then
echo "gitea-issue comment requires --body or --body-file" >&2
exit 1
fi
body="**Comment by LLM agent**
${body}"
api_or_die "comment on issue #${number}" -X POST "${issues_api}/${number}/comments" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg body "$body" '{body: $body}')"
echo "$json" | jq -r '.html_url'
;;
close|reopen)
require_number "${1:-}"
number="$1"
new_state="closed"
[ "$subcommand" = "reopen" ] && new_state="open"
api_or_die "${subcommand} issue #${number}" -X PATCH "${issues_api}/${number}" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg state "$new_state" '{state: $state}')"
echo "$json" | jq -r '"#\(.number) is now \(.state): \(.html_url)"'
;;
esac
Executable
+246
View File
@@ -0,0 +1,246 @@
#!/bin/bash
set -euo pipefail
GITEA_TOKEN_FILE="${GITEA_TOKEN_FILE:-$HOME/.config/gitea/token}"
function usage() {
echo "Usage: gitea-pr create [--title TITLE] [--body BODY | --body-file FILE] [--base BRANCH]"
echo " gitea-pr comments PR_NUMBER"
echo " gitea-pr merge PR_NUMBER"
echo ""
echo "--body-file reads the body from FILE, or from stdin when FILE is '-'."
echo "Prefer it over --body for anything with quotes, backticks or newlines."
echo ""
echo "Requires GITEA_SSH_HOST and GITEA_API set in the environment (e.g. in" \
"your shell profile), and a token at $GITEA_TOKEN_FILE (or GITEA_TOKEN" \
"set for this invocation only)."
}
function require_config() {
if [ -z "${GITEA_SSH_HOST:-}" ]; then
echo "GITEA_SSH_HOST is not set. Add 'export GITEA_SSH_HOST=<gitea ssh hostname>'" \
"(e.g. gitea.example.com) to ~/.profile.local" >&2
exit 1
fi
if [ -z "${GITEA_API:-}" ]; then
echo "GITEA_API is not set. Add 'export GITEA_API=https://<gitea host>/api/v1'" \
"(e.g. https://gitea.example.com/api/v1) to ~/.profile.local" >&2
exit 1
fi
}
function require_token() {
if [ -z "${GITEA_TOKEN:-}" ] && [ -f "$GITEA_TOKEN_FILE" ]; then
GITEA_TOKEN=$(<"$GITEA_TOKEN_FILE")
fi
if [ -z "${GITEA_TOKEN:-}" ]; then
echo "No Gitea token found. Generate one in the Gitea web UI" \
"(Settings > Applications, scopes write:repository + write:issue)" \
"and save it to $GITEA_TOKEN_FILE (chmod 600), or set GITEA_TOKEN" \
"in the environment for this invocation only." >&2
exit 1
fi
}
# Feeds the auth header to curl as a config on stdin rather than as an
# argument. Command lines are world-readable through /proc, so `-H
# "Authorization: token $GITEA_TOKEN"` exposes the token to every other
# process on the host for as long as the request runs - and to anything that
# scrapes `ps` output, including the agents this repo exists to sandbox.
# printf is a bash builtin, so the token never lands in another argv.
function gitea_api() {
printf 'header = "Authorization: token %s"\n' "$GITEA_TOKEN" |
curl -sS -w '\n%{http_code}' -K - "$@"
}
# Reads a body from a file, or from stdin for '-'. The point is to keep prose
# out of argv: a body composed on a command line has to survive shell quoting,
# and the things that break it - an apostrophe, a backtick, a $ - are exactly
# what English and code fences are made of. A file (or a heredoc into '-') has
# no such layer.
function read_body_file() {
local file="$1"
if [ "$file" = "-" ]; then
cat
return
fi
if [ ! -f "$file" ]; then
echo "No such body file: $file" >&2
exit 1
fi
cat "$file"
}
function gitea_owner_repo() {
local remote_url host owner_repo
remote_url=$(git remote get-url origin 2>/dev/null) || {
echo "No 'origin' remote found in this repository" >&2
exit 1
}
host=$(echo "$remote_url" | sed -E 's#^[^@]+@([^:]+):.*#\1#')
if [ "$host" != "$GITEA_SSH_HOST" ]; then
echo "origin remote ($remote_url) is not on $GITEA_SSH_HOST; gitea-pr only supports this host" >&2
exit 1
fi
owner_repo=$(echo "$remote_url" | sed -E 's#^[^@]+@[^:]+:##; s#\.git$##')
echo "$owner_repo"
}
if [ "$#" -lt 1 ]; then
usage
exit 1
fi
subcommand="$1"
shift
case "$subcommand" in
create|comments|merge)
require_config
require_token
owner_repo=$(gitea_owner_repo)
owner="${owner_repo%%/*}"
repo="${owner_repo##*/}"
;;
*)
usage
exit 1
;;
esac
case "$subcommand" in
create)
title=""
body=""
body_file=""
base=""
while [ "$#" -gt 0 ]; do
case "$1" in
--title) title="$2"; shift 2 ;;
--body) body="$2"; shift 2 ;;
--body-file) body_file="$2"; shift 2 ;;
--base) base="$2"; shift 2 ;;
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
esac
done
# Rejected rather than ranked: silently preferring one would make a
# caller that passed both ship a body it didn't mean to.
if [ -n "$body" ] && [ -n "$body_file" ]; then
echo "Pass --body or --body-file, not both" >&2
exit 1
fi
if [ -n "$body_file" ]; then
body="$(read_body_file "$body_file")"
fi
body="**Summary generated by LLM agent**
${body}"
current_branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$current_branch" = "HEAD" ]; then
echo "Detached HEAD: check out the feature branch before creating a PR" >&2
exit 1
fi
if [ -z "$base" ]; then
base=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's#refs/remotes/origin/##' || true)
base="${base:-main}"
fi
response=$(gitea_api "${GITEA_API}/repos/${owner}/${repo}/pulls?state=open")
http_code=$(echo "$response" | tail -1)
json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "Failed to check for an existing PR (HTTP $http_code):" >&2
echo "$json" >&2
exit 1
fi
existing_url=$(echo "$json" | jq -r --arg head "$current_branch" --arg base "$base" \
'.[] | select(.head.ref == $head and .base.ref == $base) | .html_url' | head -1)
if [ -n "$existing_url" ]; then
echo "$existing_url"
exit 0
fi
if [ -z "$title" ]; then
title="$current_branch"
fi
response=$(gitea_api -X POST "${GITEA_API}/repos/${owner}/${repo}/pulls" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg head "$current_branch" --arg base "$base" --arg title "$title" --arg body "$body" \
'{head: $head, base: $base, title: $title, body: $body}')")
http_code=$(echo "$response" | tail -1)
json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "Failed to create PR (HTTP $http_code):" >&2
echo "$json" >&2
exit 1
fi
echo "$json" | jq -r '.html_url'
;;
comments)
pr_number="${1:-}"
if [ -z "$pr_number" ]; then
echo "Usage: gitea-pr comments PR_NUMBER" >&2
exit 1
fi
echo "=== Issue comments ==="
response=$(gitea_api "${GITEA_API}/repos/${owner}/${repo}/issues/${pr_number}/comments")
http_code=$(echo "$response" | tail -1)
json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "Failed to fetch issue comments (HTTP $http_code):" >&2
echo "$json" >&2
exit 1
fi
echo "$json" | jq -r '.[] | "[\(.user.login) @ \(.created_at)]\n\(.body)\n"'
echo "=== Reviews ==="
response=$(gitea_api "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/reviews")
http_code=$(echo "$response" | tail -1)
reviews_json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "Failed to fetch reviews (HTTP $http_code):" >&2
echo "$reviews_json" >&2
exit 1
fi
echo "$reviews_json" | jq -r '.[] | select(.body != "") | "[\(.user.login) @ \(.submitted_at) — \(.state)]\n\(.body)\n"'
echo "=== Inline review comments ==="
review_ids=$(echo "$reviews_json" | jq -r '.[] | select(.comments_count > 0) | .id')
for review_id in $review_ids; do
response=$(gitea_api \
"${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/reviews/${review_id}/comments")
http_code=$(echo "$response" | tail -1)
json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "Failed to fetch comments for review ${review_id} (HTTP $http_code):" >&2
echo "$json" >&2
exit 1
fi
echo "$json" | jq -r '.[] | "[\(.user.login) @ \(.path):\(.line // "?")]\n\(.body)\n"'
done
;;
merge)
pr_number="${1:-}"
if [ -z "$pr_number" ]; then
echo "Usage: gitea-pr merge PR_NUMBER" >&2
exit 1
fi
response=$(gitea_api -X POST "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/merge" \
-H "Content-Type: application/json" \
-d '{"Do": "merge"}')
http_code=$(echo "$response" | tail -1)
json=$(echo "$response" | sed '$d')
if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
echo "Failed to merge PR #${pr_number} (HTTP $http_code):" >&2
echo "$json" >&2
exit 1
fi
echo "Merged PR #${pr_number}"
;;
esac
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
function usage() {
echo "Usage: postgres-docker-backup container_name db_user dump_file"
}
if [[ ! "$#" == 3 ]]; then
usage
exit 1
fi
container_name="$1"
db_user="$2"
dump_file="$3"
if [ -z "$container_name" ] || [ -z "$db_user" ] || [ -z "$dump_file" ]; then
usage
exit 1
fi
docker exec "$container_name" '/bin/sh' -c "pg_dumpall -U $db_user" > $dump_file
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
function usage() {
echo "Usage: postgres-docker-restore container_name db_user"
}
if [[ ! "$#" == 2 ]]; then
usage
exit 1
fi
container_name="$1"
db_user="$2"
if [ -z "$container_name" ] || [ -z "$db_user" ]; then
usage
exit 1
fi
docker exec -it "$container_name" '/bin/sh' -c "psql -U $db_user"
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
function usage() {
echo "Usage: postgres-docker-restore container_name db_user dump_file"
echo " Note that dump_file is relative to docker filesystem and must be mounted"
}
if [[ ! "$#" == 3 ]]; then
usage
exit 1
fi
container_name="$1"
db_user="$2"
dump_file="$3"
if [ -z "$container_name" ] || [ -z "$db_user" ] || [ -z "$dump_file" ]; then
usage
exit 1
fi
docker exec -it "$container_name" '/bin/sh' -c "psql -U $db_user < $dump_file"
+8
View File
@@ -0,0 +1,8 @@
#!/bin/sh
# Read clipboard content on stdin (e.g. from `tmux save-buffer -`) and write
# it as a raw OSC 52 escape sequence directly to the given tty device path.
# Intended to be called from tmux's pane-set-clipboard hook as:
# tmux save-buffer - | tmux-clipboard-relay "#{client_tty}"
tty_path="$1"
data=$(base64 | tr -d '\n')
printf '\033]52;c;%s\a' "$data" > "$tty_path"
+77
View File
@@ -0,0 +1,77 @@
#!/bin/bash
# TODO: Dotfiles may be in a different place
if [ ! -f "$HOME/.dotfiles-config" ]; then
echo "$HOME/.dotfiles-config not found, please run dotfiles/install.sh to create it"
exit 1
fi
source "$HOME/.dotfiles-config"
source "$DOTFILES_DIR/functions.sh"
# XAUTHORITY file may be in /tmp or it may be ~/.XAUTHORITY
if [ -f "$HOME/.Xauthority" ]; then
export XAUTHORITY="$HOME/.Xauthority"
else
auth_path="$(find /tmp -maxdepth 1 -name "xauth_*")"
if [ ! -z "$auth_path" ]; then
export XAUTHORITY="$auth_path"
else
echo "No Xauthority file found. Exiting"
exit 1
fi
fi
wallpapers_path="$HOME/wallpapers"
wallpapers_vertical_path="$HOME/wallpapers-vertical"
if [ ! -d "$wallpapers_path" ]; then
echo "ERROR: Wallpaper directory not found!"
echo "Please create wallpapers directory in $wallpapers_path"
exit 1
fi
if program_installed xrandr; then
display_count="$(xrandr | grep ' connected ' | wc -l)"
display_order="$(xrandr --listmonitors | tail -n +2 | sed 's/[\+\*]//g' | awk '{ print $2}')"
# Build feh command
feh_args=("--bg-fill")
for i in $(seq 1 "$display_count"); do
display_name="$(echo "$display_order" | sed "${i}q;d")"
# Get information about the current display, need verbose to always return rotation
# and remove 'primary' for consistent column placement
display_info="$(xrandr --query --verbose | grep "$display_name" | sed 's/primary //')"
# Get the selected resolution for the display
resolution="$(echo "$display_info" | awk '{ print $3 }' | sed 's/\+.*//')"
# Get the rotation for each display
rotation="$(echo "$display_info" | awk '{ print $5 }')"
path="$wallpapers_path"
resolution_segment=""
if [ "$rotation" != "normal" ] && [ "$rotation" != "inverted" ]; then
if [ ! -d "$wallpapers_vertical_path" ]; then
echo "$rotation"
echo "ERROR: Vertical display detected, but vertical wallpapers directory not found!"
echo "Please create vertical wallpapers directory in $wallpapers_vertical_path"
exit 1
fi
path="$wallpapers_vertical_path"
fi
# If we have a resolution-specific path for the display, use it
if [ -d "$path/1080p" ]; then
resolution_segment="/1080p"
fi
if [ -d "$path/4k" ]; then
if [ "$resolution" = "3840x2160" ] || [ "$resolution" = "2160x3840" ]; then
resolution_segment="/4k"
fi
fi
display_wallpaper="$(shuf -en1 "$path$resolution_segment"/*)"
feh_args+=("$display_wallpaper")
done
echo "feh ${feh_args[@]}"
feh "${feh_args[@]}"
else
# Default to ~/wallpapers/1080p or ~/wallpapers for first display if no xrandr
if [ -d "$path/1080p" ]; then
feh --bg-fill "$(shuf -en1 $wallpapers_path/1080p/*)"
else
feh --bg-fill "$(shuf -en1 $wallpapers_path/*)"
fi
fi
+59
View File
@@ -0,0 +1,59 @@
{
"workbench.colorTheme": "Gruvbox Dark Medium",
"vim.camelCaseMotion.enable": true,
"vim.easymotion": true,
"vim.enableNeovim": true,
"vim.handleKeys": {
"<C-a>": false,
"<C-d>": true,
"<C-f>": false,
"<C-s>": false,
"<C-z>": false
},
"vim.insertModeKeyBindingsNonRecursive": [
{
"before": [",", ","],
"after": ["<Esc>"]
}
],
"vim.normalModeKeyBindingsNonRecursive": [
{
"before": ["<leader>", "d"],
"after": ["d", "d"]
},
{
"before": ["<leader>", "d"],
"after": ["d", "d"]
},
{
"before": [",", ",", "<Esc>"],
"commands": [":nohl"]
},
{
"before": ["<leader>", "q"],
"commands": [":bp"]
},
{
"before": ["<leader>", "w"],
"commands": [":bn"]
},
{
"before": ["<leader>", "r", "r"],
"commands": [":action "]
},
{
"before": ["<leader>", "<leader>", "c"],
"commands": [":Blose"],
"silent": true
}
],
"vim.leader": ",",
// To improve performance
"extensions.experimental.affinity": {
"vscodevim.vim": 1
},
"vim.neovimUseConfigFile": true,
"editor.fontFamily": "'Source Code Pro', regular",
"vim.normalModeKeyBindings": [],
"python.venvPath": "~/.pyenv"
}
+27 -3
View File
@@ -1,6 +1,3 @@
import = [
"~/.config/alacritty/themes/themes/gruvbox_dark.toml"
]
[font]
size = 9.0
@@ -20,3 +17,30 @@ style = "Italic"
[font.normal]
family = "Source Code Pro for Powerline"
style = "Regular"
[general]
import = [
"~/.config/alacritty/themes/themes/gruvbox_dark.toml"
]
[selection]
# X11 always sets PRIMARY (middle-click paste) on text selection; that part
# needs no config. CLIPBOARD (Ctrl+V / Ctrl+Shift+V) is a separate buffer
# that nothing populates without this, so mirror every selection into it
# too. This is handled by Alacritty itself, so it covers anything visible
# on screen -- local shell, nested tmux, SSH'd remote shells -- regardless
# of whether the app underneath knows how to talk to the clipboard.
save_to_clipboard = true
[keyboard]
# Alacritty doesn't implement the CSI-u/Kitty keyboard protocol that lets a
# terminal report Shift+Enter as distinct from plain Enter, so it needs an
# explicit binding. Sending a raw line feed makes Shift+Enter equivalent to
# Ctrl+J, which Claude Code (and most other terminal apps) already treats
# as "insert newline" with zero further configuration -- this works
# unchanged through any depth of nested tmux, since it's just a literal
# byte rather than an escape sequence that needs to be interpreted along
# the way.
bindings = [
{ key = "Return", mods = "Shift", chars = "\n" },
]
+7
View File
@@ -0,0 +1,7 @@
[Desktop Entry]
Name=USDB Syncer
Comment=Download karaoke songs
Exec=usdb_syncer
Terminal=false
Type=Application
Categories=Software;
@@ -6,7 +6,7 @@
# picom: https://wiki.archlinux.org/title/Picom
# manpage: https://man.archlinux.org/man/picom.1.en
# Enable if not using compositor included with plasma
#exec_always --no-startup-id picom --experimental-backends -b --config ~/.config/picom.conf
exec_always --no-startup-id picom --experimental-backends -b --config ~/.config/picom.conf
##################
# window manager #
@@ -14,13 +14,20 @@
# Only enable when using i3 without a DE (eg plasma)
# dex execute .desktop files + apps using /etc/xdg/autostart.
#exec --no-startup-id dex --autostart --environment i3
exec --no-startup-id dex --autostart --environment i3
################
# applications #
################
# set wallpaper
exec --no-startup-id sleep 1 && ~/dotfiles/bin/update-wallpaper
# exec --no-startup-id sleep 1 && systemctl start update-wallpaper.service
# start keyring
exec --no-startup-id dbus-update-activation-environment --all
#exec_always --no-startup-id conky -c ~/.config/conky/conkyrc-stats
#exec --no-startup-id sleep 7 && firefox https://todo.bradina.haus/
+70
View File
@@ -0,0 +1,70 @@
############################################
# bar settings (input comes from i3blocks) #
############################################
# Start i3bar to display a workspace bar
# (plus the system information i3status finds out, if available)
bar {
# TODO: Figure out how to add an applications menu button on the left of bar
# font pango: Source Code Pro (monospace) 10 #Noto Sans Regular 10
font pango: Source Code Pro for Powerline 10
status_command i3blocks -c ~/.config/i3/i3blocks.conf
position bottom
output DP-0
output DP-2
#tray_padding 0
# When strip_workspace_numbers is set to yes,
# any workspace that has a name of the form
# “[n][:][NAME]” will display only the name.
strip_workspace_numbers yes
##strip_workspace_name no
colors {
# gruvbox colors
background $bg
statusline $yellow
# workspaces section
# border bg txt
focused_workspace $aqua $aqua $darkgray
inactive_workspace $darkgray $darkgray $yellow
active_workspace $darkgray $darkgray $yellow
urgent_workspace $red $red $bg
}
}
# you can add different bars for multidisplay setups on each display:
# set output HDMI-0 to the display you want the bar, --transparency can be set.
# Transparency needs rgba color codes to be used where the last two letters are the transparency factor see here:
# https://gist.github.com/lopspower/03fb1cc0ac9f32ef38f4
# #08052be6 --> e6=90%
bar {
font pango: Noto Sans Regular 10
status_command i3blocks -c ~/.config/i3/i3blocks-2.conf
i3bar_command i3bar --transparency
output HDMI-0
position bottom
colors {
# gruvbox colors
background $bg
statusline $yellow
# workspaces section
# border bg txt
focused_workspace $aqua $aqua $darkgray
inactive_workspace $darkgray $darkgray $yellow
active_workspace $darkgray $darkgray $yellow
urgent_workspace $red $red $bg
}
# colors {
# separator $purple
# background $darkbluetrans
# statusline $white
# border bg txt indicator
# focused_workspace $lighterblue $lighterblue $darkblue $purple
# active_workspace $lightdblue $lightdblue $darkblue $purple
# inactive_workspace $darkblue $darkblue $lightdblue $purple
# urgent_workspace $urgentred $urgentred $white $purple
# }
}
+34
View File
@@ -0,0 +1,34 @@
# Volume
# use meta keys without showing osc
#bindsym XF86AudioRaiseVolume exec --no-startup-id amixer -D pulse sset Master 5%+ && pkill -RTMIN+1 i3blocks
#bindsym XF86AudioLowerVolume exec --no-startup-id amixer -D pulse sset Master 5%- && pkill -RTMIN+1 i3blocks
# use meta keys showing osc using dunst
bindsym XF86AudioRaiseVolume exec --no-startup-id ~/.config/i3/scripts/volume_brightness.sh volume_up
bindsym XF86AudioLowerVolume exec --no-startup-id ~/.config/i3/scripts/volume_brightness.sh volume_down
# gradular volume control
bindsym $mod+XF86AudioRaiseVolume exec --no-startup-id amixer -D pulse sset Master 1%+ && pkill -RTMIN+1 i3blocks
bindsym $mod+XF86AudioLowerVolume exec --no-startup-id amixer -D pulse sset Master 1%- && pkill -RTMIN+1 i3blocks
#bindsym XF86AudioMute exec --no-startup-id amixer sset Master toggle && killall -USR1 i3blocks
# use meta keys showing osc using dunst
bindsym XF86AudioMute exec --no-startup-id ~/.config/i3/scripts/volume_brightness.sh volume_mute
# Backlight control
# Backlight setting using dunst osc
#bindsym XF86MonBrightnessUp exec --no-startup-id ~/.config/i3/scripts/volume_brightness.sh brightness_up
#bindsym XF86MonBrightnessDown exec --no-startup-id ~/.config/i3/scripts/volume_brightness.sh brightness_down
# mic mute toggle
bindsym XF86AudioMicMute exec amixer sset Capture toggle
# exit-menu
bindsym $mod+Shift+e exec --no-startup-id ~/.config/i3/scripts/powermenu
# Lock the system
# lock by blurring the screen:
bindsym $mod+Delete exec --no-startup-id ~/.config/i3/scripts/blur-lock
# applications
bindsym $mod+n exec /usr/bin/thunar
+1
View File
@@ -0,0 +1 @@
alias vim=nvim
+142
View File
@@ -0,0 +1,142 @@
function program_installed {
local return_=0
type $1 >/dev/null 2>&1 || { local return_=1; }
return "$return_"
}
function list_processes() {
# List all processes matching the given process name string
ps aux | grep $(whoami) | grep -i "$1" | grep -v grep
}
function kill_all() {
# Kill all processes matching the given process name string
if [ ! "$1" ]; then
echo "kill_all requires a process name to kill all instances of"
return 1
fi
kill_flag=15
if [ "$15" ]; then
kill_flag="$15"
fi
count=$(list_processes "$1" | wc -l)
echo "Killing $count running processes matching $1"
kill -"$kill_flag" $(list_processes "$1" | awk '{print $2}')
count=$(list_processes "$1" | wc -l)
if [ $count -gt 0 ]; then
echo "$count processes could not be killed"
fi
}
function ranger-cd() {
# Make shell cd to ranger directory
tempfile=$(mktemp)
ranger --choosedir="$tempfile" "${@:-$(pwd)}" < $TTY
test -f "$tempfile" &&
if [ "$(cat -- "$tempfile")" != "$(echo -n `pwd`)" ]; then
cd $(cat $tempfile)
fi
zle reset-prompt
printf '\n'
rm -f -- "$tempfile"
}
function terminal-clock() {
tty-clock -tcb < $TTY
zle reset-prompt
printf '\n'
}
function check_dotfiles_version {
# Check if the version of the dotfiles directory is the latest version
# Return 0 if repo is present and the latest version
# Return 1 if the repo is not present
# Return 2 if the repo is behind the remote
# Return 3 if the repo is ahead of the remote
# Return 4 if the repo has diverged from the remote
# Return 5 if DOTFILES_DIR is not set
if [ -z $DOTFILES_DIR ]; then
return 5
fi
if [ ! -d $DOTFILES_DIR ]; then
return 2
fi
pushd $DOTFILES_DIR > /dev/null
# TODO: This may be gitbox
git fetch origin > /dev/null
UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "$UPSTREAM")
BASE=$(git merge-base @ "$UPSTREAM")
popd > /dev/null
if [[ $LOCAL = $REMOTE ]]; then
return 0
elif [[ $LOCAL = $BASE ]]; then
return 2
elif [[ $REMOTE = $BASE ]]; then
return 3
else
return 4
fi
}
function python_roots {
if [ -d $HOME/.local/lib/ ]; then
for directory in $(echo $HOME/.local/lib/python*); do
echo "$directory"
done
fi
if [ -d $HOME/.local/share/pipx/venvs/powerline-status/lib/ ]; then
for directory in $(echo $HOME/.local/share/pipx/venvs/powerline-status/lib/python*); do
echo "$directory"
done
fi
if [ -d $HOME/.local/pipx/venvs/powerline-status/lib/ ]; then
for directory in $(echo $HOME/.local/pipx/venvs/powerline-status/lib/python*); do
echo "$directory"
done
fi
if [ -d /usr/lib/ ]; then
for directory in $(echo /usr/lib/python*); do
echo "$directory"
done
fi
if [ -d /usr/local/lib/ ]; then
# TODO: Make this not print warnings when the directory doesn't exit
for directory in $(echo /usr/local/lib/python*); do
echo "$directory"
done
fi
}
function powerline_bash_sources {
# To support bash 3.2 on macOS, can't use declare -ag so workaround with capturing output
PYTHON_ROOTS=( $(python_roots) )
# Powerline plugin from distribution agnostic install directory
## Assemble list of possible sources
if [[ -a $POWERLINE_ROOT/bindings/bash/powerline.sh ]]; then
# Prefer user-set powerline directory
echo "$POWERLINE_ROOT/bindings/bash/powerline.sh"
fi
if [ -d /usr/share/powerline ]; then
# Apt installs here
echo "/usr/share/powerline/bindings/bash/powerline.sh"
fi
# If $POWERLINE_ROOT not set or set incorrectly, try default locations
for directory in "${PYTHON_ROOTS[@]}"; do
if [ -d "$directory" ]; then
echo "$directory"/site-packages/powerline/bindings/bash/powerline.sh
echo "$directory"/dist-packages/powerline/bindings/bash/powerline.sh
fi
done
}
+6
View File
@@ -0,0 +1,6 @@
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
+84
View File
@@ -0,0 +1,84 @@
#PATHs
if [ -d "$HOME/.local/bin" ]; then
export PATH="$HOME/.local/bin:$PATH"
fi
if [ -f "$HOME/.bash_functions" ]; then
source "$HOME/.bash_functions"
fi
# User profiles
source $HOME/.profile
# Define $POWERLINE_ROOT
if [ -f $HOME/.profile.local ]; then
set -a
source $HOME/.profile.local
set +a
fi
if [ -n "$DOTFILES_DIR" ] && [ -d "$DOTFILES_DIR" ]; then
# Gruvbox colors
[[ -f "$DOTFILES_DIR/dependencies/gruvbox/gruvbox_256palette.sh" ]] && source "$DOTFILES_DIR/dependencies/gruvbox/gruvbox_256palette.sh"
fi
# Italic support
if [ -f $HOME/.xterm-256color-italic.terminfo ]; then
tic $HOME/.xterm-256color-italic.terminfo
fi
if [ -f $HOME/.screen-256color-italic.terminfo ]; then
tic $HOME/.screen-256color-italic.terminfo
fi
# Use neovim where available
if program_installed neovim; then
alias vim='nvim'
fi
# fzf fuzzy finder
if program_installed fzf; then
# TODO: This is broken when fzf is old, should include a local copy
eval "$(fzf --bash)"
fi
# thefuck command correction
if program_installed fuck; then
eval "$(thefuck --alias)"
fi
# aactivator
if program_installed aactivator; then
eval "$(aactivator init)"
fi
# Preferred editor for local and remote sessions
export EDITOR='vim'
# Powerline
if program_installed powerline; then
if [ -n "$POWERLINE_ROOT" ] && \
[ -f "$POWERLINE_ROOT" ] && \
[ -f "$POWERLINE_ROOT/bindings/bash/powerline.sh" ]; then
# Skip lookup if location is known
source "$POWERLINE_ROOT/bindings/bash/powerline.sh"
else
POWERLINE_BASH_SOURCES=( $(powerline_bash_sources) )
found=0
for file in "${POWERLINE_BASH_SOURCES[@]}"; do
if [[ -a $file ]]; then
# TODO: Store the POWERLINE_ROOT in .profile.local if found
source $file
found=1
break
fi
done
if [ $found -eq 0 ]; then
echo "Powerline binding not found."
echo "Please set \$POWERLINE_ROOT in .profile.local"
fi
fi
fi
# Local overrides
if [ -f $HOME/.bashrc_local ]; then
source $HOME/.bashrc_local
fi
+39
View File
@@ -0,0 +1,39 @@
# Global preferences
## Development Guidelines
- ALWAYS implement minimal changes to accomplish your task, nothing unecessary
- NEVER introduce unecessary complexity or side-effects on other code
- NEVER write unecessary comments, only minimal comments to describe functionality which isn't obvious from reading the code
- ALWAYS respect the existing style of the repository
- ALWAYS implement the best possible solution to a problem you can find
- NEVER reinvent the wheel. if there's an established, accepted way to do something which doesn't introduce unecessary complexity, use it
- NEVER include co-authorship lines in a git commit
- NEVER commit to a git repository except when bootstrapping your own fresh repositories
## Spec documents
When a skill or workflow (e.g. brainstorming) would write a design spec/plan document
to a project-local path like `docs/superpowers/specs/`, write it to `~/specs/` instead,
using the same `YYYY-MM-DD-<topic>-design.md` naming convention. Do not commit spec
documents into project git repositories unless explicitly asked to.
## Gitea PR review workflow
For repos whose `origin` remote is on `gitbox.bradina.localdomain`: when the
finishing-a-development-branch skill's "Push and create PR" option is chosen,
after pushing, also run `gitea-pr create` (from dotfiles `bin/`) to actually
open the PR, and report the printed URL back. Always pass `--title`/`--body`
with a real summary of the changes, the reasoning behind them, and what was
tested — never placeholder or throwaway text, even for a call made mainly to
test other behavior (e.g. testing that a duplicate-PR check short-circuits):
if it turns out to actually create a PR, that text ships as the PR
description.
When asked to check or address PR feedback, run `gitea-pr comments <PR#>`,
make the requested changes, commit, push, and report back. Repeat for as many
rounds as needed. Only check feedback when explicitly asked — do not poll
proactively.
Never run `gitea-pr merge` unless explicitly instructed to merge in that turn.
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# PreToolUse hook: block obviously destructive Bash commands regardless of permission mode.
# Exit 2 blocks the tool call and returns stderr to Claude as feedback.
command=$(jq -r '.tool_input.command // empty')
deny_patterns=(
'rm[[:space:]]+(-[a-zA-Z]*[rR][a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*[rR])[[:space:]]+/($|[[:space:]])'
'rm[[:space:]]+(-[a-zA-Z]*[rR][a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*[rR])[[:space:]]+(--no-preserve-root|~($|/)|\*)'
':\(\)[[:space:]]*\{[[:space:]]*:.*\|.*:.*&.*\}[[:space:]]*;[[:space:]]*:'
'dd[[:space:]].*of=/dev/(sd|nvme|vd|hd)'
'mkfs(\.[a-zA-Z0-9]+)?[[:space:]]'
'>[[:space:]]*/dev/(sd|nvme|vd|hd)[a-z0-9]*($|[[:space:]])'
'chmod[[:space:]]+-R[[:space:]]+[0-7]{3,4}[[:space:]]+/($|[[:space:]])'
'chown[[:space:]]+-R[[:space:]].*[[:space:]]+/($|[[:space:]])'
'(^|[[:space:]])(shutdown|reboot|poweroff|halt)([[:space:]]|$)'
'wipefs[[:space:]]'
'shred[[:space:]].*/dev/'
'curl[[:space:]].*\|[[:space:]]*(sudo[[:space:]]+)?(sh|bash|zsh)($|[[:space:]])'
'wget[[:space:]].*-O-.*\|[[:space:]]*(sudo[[:space:]]+)?(sh|bash|zsh)($|[[:space:]])'
)
for pattern in "${deny_patterns[@]}"; do
if [[ "$command" =~ $pattern ]]; then
echo "Blocked by local denylist hook (~/.claude/hooks/deny-dangerous-bash.sh): command matches pattern '$pattern'" >&2
exit 2
fi
done
exit 0
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
# Claude Code statusLine command: model, dir/branch, context usage, rate limits.
# See: https://code.claude.com/docs/en/statusline
input=$(cat)
MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
FIVE_H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
# Claude Code omits rate_limits when ANTHROPIC_BASE_URL isn't the literal
# api.anthropic.com host (e.g. the dejima sandbox's credential-injecting
# loopback proxy), even though the usage endpoint itself works fine through
# it. Fetch it ourselves in that case, cached briefly to avoid a network
# round-trip on every render.
if [ -z "$FIVE_H" ] && [ -n "${ANTHROPIC_BASE_URL:-}" ] && [ -n "${ANTHROPIC_AUTH_TOKEN:-}" ]; then
CACHE="${TMPDIR:-/tmp}/claude-statusline-usage-${UID}.json"
if [ ! -s "$CACHE" ] || [ -n "$(find "$CACHE" -mmin +1 2>/dev/null)" ]; then
if curl -fsS --max-time 3 "$ANTHROPIC_BASE_URL/api/oauth/usage" \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
-H "anthropic-beta: oauth-2025-04-20" \
-o "$CACHE.tmp" 2>/dev/null; then
mv "$CACHE.tmp" "$CACHE"
fi
fi
FIVE_H=$(jq -r '.five_hour.utilization // empty' "$CACHE" 2>/dev/null)
WEEK=$(jq -r '.seven_day.utilization // empty' "$CACHE" 2>/dev/null)
fi
GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; RESET='\033[0m'
if [ "$PCT" -ge 90 ]; then BAR_COLOR="$RED"
elif [ "$PCT" -ge 70 ]; then BAR_COLOR="$YELLOW"
else BAR_COLOR="$GREEN"; fi
BAR_WIDTH=10
FILLED=$((PCT * BAR_WIDTH / 100))
EMPTY=$((BAR_WIDTH - FILLED))
BAR=""
[ "$FILLED" -gt 0 ] && printf -v FILL "%${FILLED}s" && BAR="${FILL// /▓}"
[ "$EMPTY" -gt 0 ] && printf -v PAD "%${EMPTY}s" && BAR="${BAR}${PAD// /░}"
BRANCH=""
git -C "$DIR" rev-parse --git-dir > /dev/null 2>&1 && BRANCH=" | 🌿 $(git -C "$DIR" branch --show-current 2>/dev/null)"
LIMITS=""
[ -n "$FIVE_H" ] && LIMITS="5h: $(printf '%.0f' "$FIVE_H")%"
[ -n "$WEEK" ] && LIMITS="${LIMITS:+$LIMITS }7d: $(printf '%.0f' "$WEEK")%"
echo -e "[$MODEL] 📁 ${DIR##*/}${BRANCH}"
if [ -n "$LIMITS" ]; then
echo -e "${BAR_COLOR}${BAR}${RESET} ${PCT}% | ${LIMITS}"
else
echo -e "${BAR_COLOR}${BAR}${RESET} ${PCT}%"
fi
+30
View File
@@ -0,0 +1,30 @@
{
"name": "Gruvbox Dark",
"base": "dark",
"overrides": {
"claude": "#d3869b",
"text": "#ebdbb2",
"inactive": "#665c54",
"subtle": "#7c6f64",
"muted": "#928374",
"success": "#b8bb26",
"error": "#fb4934",
"warning": "#fabd2f",
"link": "#83a598",
"highlight": "#fabd2f",
"selection": "#504945",
"diffAdded": "#b8bb26",
"diffRemoved": "#fb4934",
"promptBorder": "#504945",
"bashBorder": "#504945",
"mcpBorder": "#504945",
"planMode": "#83a598",
"spinner": "#d3869b",
"header": "#8ec07c",
"separator": "#3c3836",
"badge": "#fe8019",
"permission": "#fe8019",
"suggestion": "#8ec07c",
"fastMode": "#fabd2f"
}
}
+84
View File
@@ -0,0 +1,84 @@
@define-color borders_breeze #4c4e51;
@define-color content_view_bg_breeze #141618;
@define-color error_color_backdrop_breeze #da4453;
@define-color error_color_breeze #da4453;
@define-color error_color_insensitive_backdrop_breeze #55242b;
@define-color error_color_insensitive_breeze #55242b;
@define-color insensitive_base_color_breeze #131517;
@define-color insensitive_base_fg_color_breeze #606263;
@define-color insensitive_bg_color_breeze #1f2124;
@define-color insensitive_borders_breeze #2d3033;
@define-color insensitive_fg_color_breeze #686a6c;
@define-color insensitive_selected_bg_color_breeze #1f2124;
@define-color insensitive_selected_fg_color_breeze #686a6c;
@define-color insensitive_unfocused_bg_color_breeze #1f2124;
@define-color insensitive_unfocused_fg_color_breeze #686a6c;
@define-color insensitive_unfocused_selected_bg_color_breeze #1f2124;
@define-color insensitive_unfocused_selected_fg_color_breeze #686a6c;
@define-color link_color_breeze #926ee4;
@define-color link_visited_color_breeze #9b59b6;
@define-color success_color_backdrop_breeze #27ae60;
@define-color success_color_breeze #27ae60;
@define-color success_color_insensitive_backdrop_breeze #19482f;
@define-color success_color_insensitive_breeze #19482f;
@define-color theme_base_color_breeze #141618;
@define-color theme_bg_color_breeze #202326;
@define-color theme_button_background_backdrop_breeze #292c30;
@define-color theme_button_background_backdrop_insensitive_breeze #272a2e;
@define-color theme_button_background_insensitive_breeze #272a2e;
@define-color theme_button_background_normal_breeze #292c30;
@define-color theme_button_decoration_focus_backdrop_breeze #926ee4;
@define-color theme_button_decoration_focus_backdrop_insensitive_breeze #4a406a;
@define-color theme_button_decoration_focus_breeze #926ee4;
@define-color theme_button_decoration_focus_insensitive_breeze #4a406a;
@define-color theme_button_decoration_hover_backdrop_breeze #926ee4;
@define-color theme_button_decoration_hover_backdrop_insensitive_breeze #4a406a;
@define-color theme_button_decoration_hover_breeze #926ee4;
@define-color theme_button_decoration_hover_insensitive_breeze #4a406a;
@define-color theme_button_foreground_active_backdrop_breeze #fcfcfc;
@define-color theme_button_foreground_active_backdrop_insensitive_breeze #686a6c;
@define-color theme_button_foreground_active_breeze #ffffff;
@define-color theme_button_foreground_active_insensitive_breeze #686a6c;
@define-color theme_button_foreground_backdrop_breeze #fcfcfc;
@define-color theme_button_foreground_backdrop_insensitive_breeze #6d6f72;
@define-color theme_button_foreground_insensitive_breeze #6d6f72;
@define-color theme_button_foreground_normal_breeze #fcfcfc;
@define-color theme_fg_color_breeze #fcfcfc;
@define-color theme_header_background_backdrop_breeze #202326;
@define-color theme_header_background_breeze #292c30;
@define-color theme_header_background_light_breeze #202326;
@define-color theme_header_foreground_backdrop_breeze #fcfcfc;
@define-color theme_header_foreground_breeze #fcfcfc;
@define-color theme_header_foreground_insensitive_backdrop_breeze #fcfcfc;
@define-color theme_header_foreground_insensitive_breeze #fcfcfc;
@define-color theme_hovering_selected_bg_color_breeze #926ee4;
@define-color theme_selected_bg_color_breeze #6c53a6;
@define-color theme_selected_fg_color_breeze #ffffff;
@define-color theme_text_color_breeze #fcfcfc;
@define-color theme_titlebar_background_backdrop_breeze #202326;
@define-color theme_titlebar_background_breeze #292c30;
@define-color theme_titlebar_background_light_breeze #202326;
@define-color theme_titlebar_foreground_backdrop_breeze #fcfcfc;
@define-color theme_titlebar_foreground_breeze #fcfcfc;
@define-color theme_titlebar_foreground_insensitive_backdrop_breeze #fcfcfc;
@define-color theme_titlebar_foreground_insensitive_breeze #fcfcfc;
@define-color theme_unfocused_base_color_breeze #141618;
@define-color theme_unfocused_bg_color_breeze #202326;
@define-color theme_unfocused_fg_color_breeze #fcfcfc;
@define-color theme_unfocused_selected_bg_color_alt_breeze #362c50;
@define-color theme_unfocused_selected_bg_color_breeze #362c50;
@define-color theme_unfocused_selected_fg_color_breeze #fcfcfc;
@define-color theme_unfocused_text_color_breeze #fcfcfc;
@define-color theme_unfocused_view_bg_color_breeze #131517;
@define-color theme_unfocused_view_text_color_breeze #606263;
@define-color theme_view_active_decoration_color_breeze #926ee4;
@define-color theme_view_hover_decoration_color_breeze #926ee4;
@define-color tooltip_background_breeze #292c30;
@define-color tooltip_border_breeze #535659;
@define-color tooltip_text_breeze #fcfcfc;
@define-color unfocused_borders_breeze #4c4e51;
@define-color unfocused_insensitive_borders_breeze #2d3033;
@define-color warning_color_backdrop_breeze #f67400;
@define-color warning_color_breeze #f67400;
@define-color warning_color_insensitive_backdrop_breeze #5e340f;
@define-color warning_color_insensitive_breeze #5e340f;
+1
View File
@@ -1,3 +1,4 @@
VteTerminal, vte-terminal {
padding: 13px;
}
@import 'colors.css';
+18 -9
View File
@@ -1,16 +1,25 @@
[Settings]
gtk-font-name=Liberation Sans Regular 10
gtk-theme-name=Gruvbox-Dark-BL
gtk-icon-theme-name=Gruvbox_Dark
gtk-cursor-theme-name=Gruvbox-cursors
gtk-cursor-theme-size=16
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
gtk-button-images=1
gtk-menu-images=1
gtk-application-prefer-dark-theme=true
gtk-button-images=true
gtk-cursor-blink=true
gtk-cursor-blink-time=1000
gtk-cursor-theme-name=breeze_cursors
gtk-cursor-theme-size=24
gtk-decoration-layout=icon:minimize,maximize,close
gtk-enable-animations=true
gtk-enable-event-sounds=0
gtk-enable-input-feedback-sounds=0
gtk-font-name=Noto Sans, 10
gtk-icon-theme-name=breeze-dark
gtk-menu-images=true
gtk-modules=colorreload-gtk-module
gtk-primary-button-warps-slider=true
gtk-sound-theme-name=ocean
gtk-theme-name=Gruvbox-Dark-BL
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
gtk-toolbar-style=3
gtk-xft-antialias=1
gtk-xft-dpi=122880
gtk-xft-hinting=1
gtk-xft-hintstyle=hintmedium
gtk-xft-rgba=none
+25
View File
@@ -22,6 +22,31 @@ set $ws7 "7"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10"
set $ws11 "11"
set $ws12 "12"
set $ws13 "13"
set $ws14 "14"
set $ws15 "15"
set $ws16 "16"
set $ws17 "17"
set $ws18 "18"
set $ws19 "19"
# Define colors variables:
# gruvbox colors
set $bg #282828
set $red #cc241d
set $green #98971a
set $yellow #d79921
set $blue #458588
set $purple #b16286
set $aqua #689d6a
set $gray #a89984
set $darkgray #1d2021
set $white #ebdbb2
# Include configs
include config.d/*.conf
include config.de/*.conf
include config.local/*.conf
+15 -6
View File
@@ -12,20 +12,19 @@ exec --no-startup-id numlockx on
# use arandr to setup displays and save the file as default:
exec --no-startup-id ~/.screenlayout/default.sh
# set wallpaper
exec --no-startup-id sleep 1 && feh --bg-fill --randomize ~/wallpapers
# set powersavings for display if not handled by DE:
# Usage: xset dpms {standby_time} {suspend_time} {off_time}
# exec --no-startup-id xset dpms 600 0 0
#exec --no-startup-id xset dpms 600 0 0
# disable power saving (for example if using xscreensaver)
#exec --no-startup-id xset -dpms
exec --no-startup-id xset -dpms
# use xautolock to use autosuspend rules for mobile devices
# https://wiki.archlinux.org/title/Session_lock#xautolock
#exec --no-startup-id xautolock -time 60 -locker "systemctl suspend"
# set wallpaper(s) on i3 start/restart
exec_always --no-startup-id "[ -f ~/.dotfiles-config ] && source ~/.dotfiles-config && $DOTFILES_DIR/bin/update-wallpaper"
# xscreensaver
# https://www.jwz.org/xscreensaver
@@ -45,7 +44,17 @@ exec --no-startup-id /usr/bin/dunst
# Scratchpad with notes
# `tmuxinator open notes` first for this to work
exec --no-startup-id alacritty --title notebook -e zsh -c 'tmuxinator start notes'
for_window [class="^Alacritty$" title="notebook"] move scratchpad, scratchpad hide
for_window [class="^Alacritty$" title="notebook"] move scratchpad
#, scratchpad hide
# Performance monitor
exec --no-startup-id alacritty --title monitoring -e zsh -c 'htop'
for_window [class="^Alacritty$" title="monitoring"] move scratchpad
#, scratchpad hide
# Remote connections
# exec --no-startup-id alacritty --title servers -e zsh -c 'tmuxinator start servers'
# for_window [class="^Alacritty$" title="servers"] move scratchpad, scratchpad hide
###############
# system tray #
+32 -53
View File
@@ -7,8 +7,15 @@ floating_modifier $mod
# switch/iterate between workspaces
bindsym $mod+Tab workspace next
bindsym $mod+Shift+Tab workspace prev
bindsym $mod+c exec --no-startup-id ~/.config/i3/scripts/empty_workspace
bindsym $mod+Shift+c exec --no-startup-id ~/.config/i3/scripts/move_container_empty_workspace
bindsym $mod+slash [class="^Alacritty$" title="notebook"] scratchpad show
# bindsym $mod+slash scratchpad show
bindsym $mod+m [class="^Alacritty$" title="monitoring"] scratchpad show
# bindsym $mod+Shift+colon [class="^Alacritty$" title="servers"] scratchpad show
bindsym $mod+Shift+slash move scratchpad
bindsym $mod+Control+slash scratchpad show
# switch to workspace
bindsym $mod+1 workspace $ws1
@@ -160,7 +167,8 @@ mode "$mode_gaps_outer" {
######################################
# start a terminal
bindsym $mod+Return exec --no-startup-id alacritty
bindsym $mod+Return exec --no-startup-id alacritty -e sh -c "tmux new-session"
# bindsym $mod+Return exec --no-startup-id alacritty
# kill focused window
bindsym $mod+q kill
@@ -168,22 +176,8 @@ bindsym $mod+q kill
# middle click over titlebar kills window
#bindsym --release button2 kill
# exit-menu
#bindsym $mod+Shift+e exec --no-startup-id ~/.config/i3/scripts/powermenu
# using plasma's logout screen instead of i3's
bindsym $mod+Shift+t exec --no-startup-id qdbus6 org.kde.LogoutPrompt /LogoutPrompt org.kde.LogoutPrompt.promptLogout
#bindsym $mod+Shift+t exec --no-startup-id loginctl kill-session "$USER"
bindsym $mod+Shift+e exec --no-startup-id kill -9 -1
# Lock the system
# lock with a picture:
#bindsym $mod+l exec --no-startup-id i3lock -i ~/.config/i3/i3-lock-screen.png -p default|win -t
# lock by blurring the screen:
# TODO: Update to use plasma lock
bindsym $mod+Delete exec --no-startup-id ~/.config/i3/scripts/blur-lock
# reload the configuration file
bindsym $mod+Shift+c reload
bindsym $mod+Control+r reload
# restart i3 inplace (preserves your layout/session, can be used to update i3)
bindsym $mod+Shift+r restart
@@ -194,13 +188,6 @@ bindsym F1 exec --no-startup-id ~/.config/i3/scripts/keyhint-2
# keybinding list in editor:
#bindsym $mod+F1 exec --no-startup-id xed ~/.config/i3/keybindings
# Backlight control
#bindsym XF86MonBrightnessUp exec --no-startup-id xbacklight +10 && notify-send "Brightness - $(xbacklight -get | cut -d '.' -f 1)%"
#bindsym XF86MonBrightnessDown exec --no-startup-id xbacklight -10 && notify-send "Brightness - $(xbacklight -get | cut -d '.' -f 1)%"
# Backlight setting using dunst osc
#bindsym XF86MonBrightnessUp exec --no-startup-id ~/.config/i3/scripts/volume_brightness.sh brightness_up
#bindsym XF86MonBrightnessDown exec --no-startup-id ~/.config/i3/scripts/volume_brightness.sh brightness_down
# change focus
bindsym $mod+h focus left
bindsym $mod+j focus down
@@ -225,7 +212,19 @@ bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right
# splij in vertical orientation
# move focused workspace
bindsym $mod+Control+h move workspace to output left
bindsym $mod+Control+j move workspace to output down
bindsym $mod+Control+k move workspace to output up
bindsym $mod+Control+l move workspace to output right
# alternatively, you can use the cursor keys:
bindsym $mod+Control+Left move workspace to output left
bindsym $mod+Control+Down move workspace to output down
bindsym $mod+Control+Up move workspace to output up
bindsym $mod+Control+Right move workspace to output right
# split in vertical orientation
bindsym $mod+minus split v
bindsym $mod+KP_Subtract split v
@@ -254,31 +253,6 @@ bindsym $mod+a focus parent
bindsym $mod+Shift+n exec --no-startup-id ~/.config/i3/scripts/empty_workspace
# Multimedia Keys
# TODO: These will only work if plasma is installed, update to add compatibility with bare i3
# volume
# use meta keys without showing osc
#bindsym XF86AudioRaiseVolume exec --no-startup-id amixer -D pulse sset Master 5%+ && pkill -RTMIN+1 i3blocks
#bindsym XF86AudioLowerVolume exec --no-startup-id amixer -D pulse sset Master 5%- && pkill -RTMIN+1 i3blocks
# use meta keys showing osc using dunst
#bindsym XF86AudioRaiseVolume exec --no-startup-id ~/.config/i3/scripts/volume_brightness.sh volume_up
#bindsym XF86AudioLowerVolume exec --no-startup-id ~/.config/i3/scripts/volume_brightness.sh volume_down
bindsym XF86AudioRaiseVolume exec --no-startup-id qdbus6 org.kde.kglobalaccel /component/kmix invokeShortcut "increase_volume"
bindsym XF86AudioLowerVolume exec --no-startup-id qdbus6 org.kde.kglobalaccel /component/kmix invokeShortcut "decrease_volume"
# gradular volume control
bindsym $mod+XF86AudioRaiseVolume exec --no-startup-id amixer -D pulse sset Master 1%+ && pkill -RTMIN+1 i3blocks
bindsym $mod+XF86AudioLowerVolume exec --no-startup-id amixer -D pulse sset Master 1%- && pkill -RTMIN+1 i3blocks
# mute
#bindsym XF86AudioMute exec --no-startup-id amixer sset Master toggle && killall -USR1 i3blocks
# use meta keys showing osc using dunst
#bindsym XF86AudioMute exec --no-startup-id ~/.config/i3/scripts/volume_brightness.sh volume_mute
bindsym XF86AudioMute exec --no-startup-id qdbus6 org.kde.kglobalaccel /component/kmix invokeShortcut "mute"
# mic mute toggle
#bindsym XF86AudioMicMute exec amixer sset Capture toggle
bindsym XF86AudioMicMute exec --no-startup-id qdbus6 org.kde.kglobalaccel /component/kmix invokeShortcut "mic_mute"
# audio control
# TODO: Play pause doesn't work on desktop
@@ -296,11 +270,9 @@ bindsym --whole-window $mod+button2 kill
bindsym $mod+p exec --no-startup-id /usr/local/bin/switch-audio-port
## App shortcuts
# TODO: dolphin/thunar, Spectacle/scrot
bindsym $mod+w exec /usr/bin/firefox
bindsym $mod+n exec /usr/bin/dolphin
bindsym Print exec scrot ~/Pictures/Screenshots/%Y-%m-%d-%T-screenshot.png && notify-send "Screenshot saved to ~/Pictures/Screenshots/$(date +"%Y-%m-%d-%T")-screenshot.png"
bindsym $mod+Print exec Spectacle
#bindsym Print exec spectactle --output ~/Pictures/Screenshots/%Y-%m-%d-%T-screenshot.png
# Power Profiles menu switcher (rofi)
bindsym $mod+Shift+p exec --no-startup-id ~/.config/i3/scripts/power-profiles
@@ -319,5 +291,12 @@ bindsym $mod+t exec --no-startup-id rofi -show window \
## rofi bindings to manage clipboard (install rofi-greenclip from the AUR)
exec --no-startup-id greenclip daemon>/dev/null
bindsym $mod+c exec --no-startup-id rofi -modi "clipboard:greenclip print" -show clipboard \
bindsym $mod+b exec --no-startup-id rofi -modi "clipboard:greenclip print" -show clipboard \
-config ~/.config/rofi/rofidmenu.rasi
## autoclicker x 100
bindsym $mod+Shift+o exec --no-startup-id xdotool click --repeat 1000 --delay 10 1
bindsym $mod+Shift+i exec --no-startup-id xdotool click --repeat 10000 --delay 10 1
# calculator
bindsym XF86Calculator exec --no-startup-id galculator
+1 -78
View File
@@ -8,7 +8,7 @@ font pango: Liberation Sans Regular 10
default_border pixel 5
# thin borders
# hide_edge_borders both
hide_edge_borders smart
# Set inner/outer gaps
gaps inner 10
@@ -73,86 +73,9 @@ for_window [title="Desktop @ QRect.*"] kill; floating enable; border none
# color settings for bar and windows #
######################################
# Define colors variables:
# gruvbox colors
set $bg #282828
set $red #cc241d
set $green #98971a
set $yellow #d79921
set $blue #458588
set $purple #b16286
set $aqua #689d6a
set $gray #a89984
set $darkgray #1d2021
set $white #ebdbb2
# gruvbox
# class border backgr text indicator child_border
client.focused $blue $blue $darkgray $aqua $darkgray
client.unfocused $darkgray $darkgray $yellow $aqua $darkgray
client.focused_inactive $darkgray $darkgray $yellow $aqua $darkgray
client.urgent $red $red $white $red $red
############################################
# bar settings (input comes from i3blocks) #
############################################
# Start i3bar to display a workspace bar
# (plus the system information i3status finds out, if available)
bar {
# Don't show the bar since we're using plasma bar, comment if using i3 on its own
mode invisible
#mode hide
hidden_state hide
modifier Mod4
# TODO: Figure out how to add an applications menu button on the left of bar
# font pango: Source Code Pro (monospace) 10 #Noto Sans Regular 10
font pango: Source Code Pro for Powerline 10
status_command i3blocks -c ~/.config/i3/i3blocks.conf
position bottom
#tray_padding 0
# When strip_workspace_numbers is set to yes,
# any workspace that has a name of the form
# “[n][:][NAME]” will display only the name.
strip_workspace_numbers yes
##strip_workspace_name no
colors {
# gruvbox colors
background $bg
statusline $yellow
# workspaces section
# border bg txt
focused_workspace $aqua $aqua $darkgray
inactive_workspace $darkgray $darkgray $yellow
active_workspace $darkgray $darkgray $yellow
urgent_workspace $red $red $bg
}
}
# you can add different bars for multidisplay setups on each display:
# set output HDMI-0 to the display you want the bar, --transparency can be set.
# Transparency needs rgba color codes to be used where the last two letters are the transparency factor see here:
# https://gist.github.com/lopspower/03fb1cc0ac9f32ef38f4
# #08052be6 --> e6=90%
# bar {
# font pango: Noto Sans Regular 10
# status_command i3blocks -c ~/.config/i3/i3blocks-2.conf
# i3bar_command i3bar --transparency
# output HDMI-0
# position bottom
#
# colors {
# separator $purple
# background $darkbluetrans
# statusline $white
# border bg txt indicator
# focused_workspace $lighterblue $lighterblue $darkblue $purple
# active_workspace $lightdblue $lightdblue $darkblue $purple
# inactive_workspace $darkblue $darkblue $lightdblue $purple
# urgent_workspace $urgentred $urgentred $white $purple
# }
#}
-13
View File
@@ -13,16 +13,3 @@ workspace_layout default
# Each new window will open fullscreen as a tab (left to right)
#workspace_layout tabbed
##########################################
# configuration for workspace behaviour: #
##########################################
# use workspaces on different displays:
# where you have to replace VGA-0/HDMI-0 with the names for your displays
# you can get from xrandr command
#workspace $ws1 output DP-2
#workspace $ws3 output DP-2
#workspace $ws5 output DP-2
#workspace $ws2 output DP-4
#workspace $ws4 output DP-4
#workspace $ws6 output DP-4
+102
View File
@@ -0,0 +1,102 @@
# i3blocks config file changed for EndeavourOS-i3 setup
# source is available here:
# https://raw.githubusercontent.com/endeavouros-team/endeavouros-i3wm-setup/main/.config/i3/i3blocks.conf
# Maintainer: joekamprad [joekamprad //a_t// endeavouros.com]
# Former Visual Designer: Florent Valetti [@FLVAL EndeavourOS]
# created for i3wm setup on EndeavourOS
# https://endeavouros.com
# cheatsheet for icon fonts used on the block-bar:
# https://fontawesome.com/v4.7/cheatsheet/
# --> to update this run the following command:
# wget --backups=1 https://raw.githubusercontent.com/endeavouros-team/endeavouros-i3wm-setup/main/.config/i3/i3blocks.conf -P ~/.config/i3/
# Please see man i3blocks for a complete reference!
# The man page is also hosted at http://vivien.github.io/i3blocks
# List of valid properties:
#
# align
# color
# command
# full_text
# instance
# interval
# label
# min_width
# name
# separator
# separator_block_width
# short_text
# signal
# urgent
# Global properties
#
# The top properties below are applied to every block, but can be overridden.
separator=false
markup=pango
separator_block_width=15
#[Weather]
#command=~/.config/i3/scripts/openweather
# or:
#command=~/.config/i3/scripts/openweather-city
#interval=1800
#color=#7275b3
separator_block_width=10
[spacer]
separator_block_width=10
full_text=
color=#b16286
[pavucontrol]
separator_block_width=10
full_text=
command=pavucontrol
color=#689d6a
[volume-pulseaudio]
command=~/.config/i3/scripts/volume
instance=Master
color=#689d6a
interval=1
separator_block_width=10
[spacer]
separator_block_width=10
full_text=
color=#b16286
[time]
label=
command=date '+%a %b %d %I:%M:%S %p'
color=#98971a
interval=1
separator_block_width=10
[spacer]
separator_block_width=10
full_text=
color=#b16286
[keybindings]
full_text=
command=~/.config/i3/scripts/keyhint
[sleep_screen]
full_text=🖵
command=~/.config/i3/scripts/blur-lock
[shutdown_menu]
full_text=
command=~/.config/i3/scripts/powermenu
separator_block_width=15
[simple-2]
full_text=
color=#b16286
+1
View File
@@ -1,3 +1,4 @@
# TODO: Doesn't include keybindings in i3-keybindings.conf
I3_CONFIG=$HOME/.config/i3/config.d/keybindings.conf
mod_key=$(sed -nre 's/^set \$mod (.*)/\1/p' ${I3_CONFIG})
grep "^bindsym" ${I3_CONFIG} \
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
MAX_DESKTOPS=20
WORKSPACES=$(seq -s '\n' 1 1 ${MAX_DESKTOPS})
EMPTY_WORKSPACE=$( (i3-msg -t get_workspaces | tr ',' '\n' | grep num | awk -F: '{print int($2)}' ; \
echo -e ${WORKSPACES} ) | sort -n | uniq -u | head -n 1)
i3-msg move container to workspace ${EMPTY_WORKSPACE}
+63
View File
@@ -0,0 +1,63 @@
" .ideavimrc is a configuration file for IdeaVim plugin. It uses
" the same commands as the original .vimrc configuration.
" You can find a list of commands here: https://jb.gg/h38q75
" Find more examples here: https://jb.gg/share-ideavimrc
"" -- Suggested options --
" Show a few lines of context around the cursor. Note that this makes the
" text scroll if you mouse-click near the start or end of the window.
set scrolloff=5
" Do incremental searching.
set incsearch
" Don't use Ex mode, use Q for formatting.
map Q gq
" --- Enable IdeaVim plugins https://jb.gg/ideavim-plugins
" Highlight copied text
Plug 'machakann/vim-highlightedyank'
" Commentary plugin
Plug 'tpope/vim-commentary'
"" -- Map IDE actions to IdeaVim -- https://jb.gg/abva4t
"" Map \r to the Reformat Code action
"map \r <Action>(ReformatCode)
"" Map <leader>d to start debug
"map <leader>d <Action>(Debug)
"" Map \b to toggle the breakpoint on the current line
"map \b <Action>(ToggleLineBreakpoint)
inoremap ,, <ESC>
cnoremap ,, <ESC><ESC>
nmap j gj
nmap k gk
" Only set on first run or it overwrites YCM behavior
" if has('vim_starting')
" imap <tab> <C-X><C-O>
" endif
let mapleader=","
let maplocalleader="\\"
" Close buffer
map <leader><leader>c :Bclose<CR>
" Prev/next buffer
map <leader>q :bp<CR>
map <leader>w :bn<CR>
" System clipboard cut copy paste
map <leader>y "+y
map <leader>Y "+Y
map <leader>p "+p
map <leader>P "+P
map <leader>x "+x
map <leader>dd "+dd
" Update ideavimrc
nnoremap <leader>v :e ~/.ideavimrc<CR>;
nnoremap <leader>rr :action IdeaVim.ReloadVimRc.reload<CR>;
+4
View File
@@ -0,0 +1,4 @@
NO_NEOFETCH=1
NO_GIT_CHECK=1
NO_ZSH_COWSAY=1
LOAD_SSH_KEYS=0
+143
View File
@@ -0,0 +1,143 @@
# nvim config map
Lua config managed by [lazy.nvim](https://github.com/folke/lazy.nvim). Leader is `,`, local leader is `\`.
## Layout
- `init.lua` — bootstraps lazy.nvim, loads `config/` then `plugins/`
- `lua/config/options.lua` — `vim.opt` settings
- `lua/config/keymaps.lua` — keymaps not tied to a specific plugin
- `lua/config/autocmds.lua` — autocommands
- `lua/plugins/*.lua` — one lazy.nvim spec file per topic (each file returns a plugin spec table; lazy.nvim loads every file in the directory automatically)
- `ftplugin/*.lua` — filetype-specific settings (Python, vimwiki)
- `lua/util.lua` — small helper functions (`ranger()`, `delete_trailing_ws()`) used from keymaps
## Plugins
### Navigation & editing (`plugins/editor.lua`)
- **[neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim)** — file explorer sidebar
- `<leader>t` — toggle
- `<leader>cd` — cd to current file's directory and open
- **[telescope.nvim](https://github.com/nvim-telescope/telescope.nvim)** — fuzzy finder for files/buffers/grep/LSP symbols
- `<leader>.` — jump to symbol
- `<leader>;` — jump to buffer
- `<leader>be` — jump to buffer, sorted by most recently used
- `<leader>ag` — live grep
- `<leader>?` — fuzzy-search all keybindings
- **[flash.nvim](https://github.com/folke/flash.nvim)** — jump to any visible location via search-like labels
- `<leader>/` — jump
- `<leader>s` — search jump
- `<leader><leader>s` — treesitter jump
- `<leader>f` — forward jump
- **[nvim-surround](https://github.com/kylechui/nvim-surround)** — add/change/delete surrounding pairs (quotes, tags, brackets)
- `ys`, `cs`, `ds` — plugin defaults
- **[nvim-autopairs](https://github.com/windwp/nvim-autopairs)** — auto-close brackets/quotes, automatic
- **[nvim-treesitter-context](https://github.com/nvim-treesitter/nvim-treesitter-context)** — sticky header showing enclosing function/class while scrolling, automatic
- **[mini.align](https://github.com/echasnovski/mini.nvim)** — align text on a character
- `ga=`, `ga:`
- **[mini.bufremove](https://github.com/echasnovski/mini.nvim)** — close a buffer without closing its window/split
- `<leader><leader>c`
- **[vim-visual-multi](https://github.com/mg979/vim-visual-multi)** — multiple cursors
- `<C-n>` — add cursor on word
- **[vim-tmux-navigator](https://github.com/christoomey/vim-tmux-navigator)** — move between nvim splits and tmux panes; also works from inside `:terminal` buffers (e.g. the Claude Code terminal)
- `<C-h/j/k/l>` — move left/down/up/right
- **[emmet-vim](https://github.com/mattn/emmet-vim)** — Emmet expansion, HTML/CSS files only
### UI (`plugins/ui.lua`)
- **[gruvbox.nvim](https://github.com/ellisonleao/gruvbox.nvim)** — colorscheme
- **[lualine.nvim](https://github.com/nvim-lualine/lualine.nvim)** — statusline
- **[bufferline.nvim](https://github.com/akinsho/bufferline.nvim)** — buffer tabs along the top
- **[indent-blankline.nvim](https://github.com/lukas-reineke/indent-blankline.nvim)** — indent guides
- **[rainbow-delimiters.nvim](https://github.com/HiPhish/rainbow-delimiters.nvim)** — rainbow-colored matching brackets
- **[nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons)** — filetype icons (dependency for several plugins above)
- **[alpha-nvim](https://github.com/goolord/alpha-nvim)** — start screen shown on launch, see [Dashboard](#dashboard) below
- `<leader><leader>o` — reopen
### Completion & LSP
- **[blink.cmp](https://github.com/Saghen/blink.cmp)** — completion engine (LSP, path, buffer sources) — `plugins/completion.lua`
- **[mason.nvim](https://github.com/mason-org/mason.nvim)** / **[mason-lspconfig.nvim](https://github.com/mason-org/mason-lspconfig.nvim)** — installs/manages LSP servers — `plugins/lsp.lua`
- **[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)** — LSP client config for `ts_ls`, `svelte`, `html`, `cssls`, `basedpyright`, `ruff`, `bashls` — `plugins/lsp.lua`
- **[rustaceanvim](https://github.com/mrcjkb/rustaceanvim)** — Rust LSP setup (`rust_analyzer`), replaces the standard lspconfig flow for Rust — `plugins/rust.lua`
- `<localleader>rr` — cargo run
LSP buffer keymaps (set on `LspAttach`, see `plugins/lsp.lua`):
- `K` — hover
- `gd` — definition
- `gy` — type definition
- `gi` — implementation
- `gr` — references
- `rn` — rename
- `ff` (visual) — format selection
### Debugging (`plugins/dap.lua`)
- **[nvim-dap](https://github.com/mfussenegger/nvim-dap)** — Debug Adapter Protocol client
- `<leader>db` — toggle breakpoint
- `<leader>dc` — continue / start debugging
- `<leader>di` / `<leader>do` / `<leader>dO` — step into / over / out
- `<leader>dr` — toggle REPL
- `<leader>dq` — terminate session
- **[nvim-dap-python](https://github.com/mfussenegger/nvim-dap-python)** — configures nvim-dap for Python using `debugpy`. Requires `:MasonInstall debugpy`; without it, debugging is skipped with a warning.
### Formatting & linting (`plugins/format.lua`)
- **[conform.nvim](https://github.com/stevearc/conform.nvim)** — format-on-save (prettier, ruff_format, rustfmt, stylua per filetype)
- **[nvim-lint](https://github.com/mfussenegger/nvim-lint)** — async linting on save/insert-leave (eslint_d, shellcheck)
### Treesitter (`plugins/treesitter.lua`)
**[nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter)** — syntax highlighting, folding, and indentation for the installed parser list. Uses core Neovim's built-in `vim.treesitter.start()`/foldexpr rather than the old treesitter modules.
### Git (`plugins/git.lua`)
- **[gitsigns.nvim](https://github.com/lewis6991/gitsigns.nvim)** — git change signs in the gutter, hunk stage/preview/blame
- **[vim-fugitive](https://github.com/tpope/vim-fugitive)** — Git commands
- `:Git`, `:Gdiffsplit`, `:Gvdiffsplit`, `:Gread`, `:Gwrite`, `:Gclog`
### AI (`plugins/ai.lua`)
- **[snacks.nvim](https://github.com/folke/snacks.nvim)** — utility library (terminal provider etc.), dependency for claudecode.nvim
- **[claudecode.nvim](https://github.com/coder/claudecode.nvim)** — Claude Code terminal integration. Diffs render as a single unified (VS Code-style, red/green interleaved) buffer in one new split next to your active pane, and keyboard focus stays in the Claude terminal instead of jumping to the diff.
- `<leader>ac` — toggle
- `<leader>af` — focus
- `<leader>ab` — add current buffer
- `<leader>as` (visual) — send selection
- `<leader>aa` / `<leader>ad` — accept/deny diff
### Wiki / notes (`plugins/vimwiki.lua`)
- **[vimwiki](https://github.com/vimwiki/vimwiki)** — personal wiki across 4 notebooks (bradwiki, work, private, shared under `~/synced-notebooks/`)
- `<leader>m...` — wiki keymaps (`vim.g.vimwiki_map_prefix`)
- **[vim-zettel](https://github.com/michal-h21/vim-zettel)** — Zettelkasten-style note linking on top of vimwiki
- **[vim-table-mode](https://github.com/dhruvasagar/vim-table-mode)** — markdown/wiki table formatting
- `:TableModeToggle`, or `<leader><leader>t...` prefix
- **[markdown-preview.nvim](https://github.com/iamcco/markdown-preview.nvim)** — live browser preview for markdown/vimwiki
- `<localleader>v` — toggle preview
### Misc (`plugins/misc.lua`)
- **[aerial.nvim](https://github.com/stevearc/aerial.nvim)** — code outline/symbol sidebar
- `<leader>ct` — toggle
- **[undotree](https://github.com/jiaoshijie/undotree)** — visual undo history tree
- `<leader>u` — toggle
- **[persistence.nvim](https://github.com/folke/persistence.nvim)** — session save/restore per project
- restore from the dashboard's `s` button
- **[which-key.nvim](https://github.com/folke/which-key.nvim)** — shows available keybindings as you type a prefix (e.g. pause after `<leader>`), automatic
## Dashboard
The start screen (shown on launch, reopen with `<leader><leader>o`) is [alpha-nvim](https://github.com/goolord/alpha-nvim), configured in `plugins/ui.lua`. It shows a random `fortune | cowthink` header plus buttons:
- `e` — new file
- `f` — find file (Telescope)
- `g` — live grep (Telescope)
- `s` — restore last session (persistence.nvim)
- `q` — quit
## Buffer navigation
`<leader>be` fuzzy-searches open buffers via Telescope, sorted by most recently used, excluding the current buffer. `<leader>;` does the same but in default Telescope order. Both are fuzzy-filterable as you type.
@@ -7,8 +7,12 @@ source $HOME/.config/nvim/config/bindings.vimrc
source $HOME/.config/nvim/config/functions.vimrc
" Python dependencies
let g:python_host_prog=expand('$HOME/.pyenv/versions/neovim2/bin/python')
let g:python3_host_prog=expand('$HOME/.pyenv/versions/neovim3/bin/python')
if isdirectory(expand($HOME.'/.pyenv/versions/neovim2'))
let g:python_host_prog=expand($HOME.'/.pyenv/versions/neovim2/bin/python')
endif
if isdirectory(expand($HOME.'/.pyenv/versions/neovim3'))
let g:python3_host_prog=expand($HOME.'/.pyenv/versions/neovim3/bin/python')
endif
" Local overrides
let $LOCALFILE=expand("$HOME/.nvim_local.vimrc")
+12 -1
View File
@@ -161,6 +161,16 @@ function! MapPlugins()
nnoremap <leader>u :GundoToggle<CR>
endif
if exists('g:loaded_claudecode')
" Claude Code
nnoremap <leader>ac :ClaudeCode<CR>
nnoremap <leader>af :ClaudeCodeFocus<CR>
nnoremap <leader>ab :ClaudeCodeAdd %<CR>
vnoremap <leader>as :ClaudeCodeSend<CR>
nnoremap <leader>aa :ClaudeCodeDiffAccept<CR>
nnoremap <leader>ad :ClaudeCodeDiffDeny<CR>
endif
" --- Language Specific ---
" - General
" COC
@@ -178,7 +188,8 @@ function! MapPlugins()
map <localleader>rr :RustRun<CR>
" - Markdown -
map <localleader>v :LivedownToggle<CR>
" map <localleader>v :LivedownToggle<CR>
nmap <localleader>v <Plug>MarkdownPreviewToggle
endfunction
augroup Plugin_Mappings
+10 -2
View File
@@ -1,5 +1,5 @@
let g:vim_plug_install_dir = "~/.local/share/nvim/site/autoload"
let g:plugin_install_dir = "~/.local/share/nvim/plugged"
let g:plugin_install_dir = "~/.vim/plugged"
" Install vim-plug if not present
if empty(glob(g:vim_plug_install_dir . "/plug.vim"))
@@ -116,7 +116,7 @@ Plug 'xolox/vim-reload'
" Note taking and wiki managment
Plug 'vimwiki/vimwiki'
" TODO Why can't these go in Search?
Plug 'junegunn/fzf'
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
Plug 'michal-h21/vim-zettel'
" TODO Make this pull on buffer open / load
@@ -173,6 +173,14 @@ Plug 'sophacles/vim-processing'
" - Markdown -
" Plug 'shime/vim-livedown'
" Plug 'iamcco/markdown-preview.nvim', { 'do': 'cd app && npx --yes yarn install' }
Plug 'iamcco/markdown-preview.nvim', { 'do': { -> mkdp#util#install() }, 'for': ['markdown', 'vim-plug']}
" --- AI ---
" Floating/split terminal windows used by claudecode.nvim
Plug 'folke/snacks.nvim'
" Claude Code integration
Plug 'coder/claudecode.nvim'
" --- Icons ---
+19
View File
@@ -173,6 +173,7 @@ let g:table_mode_map_prefix = '<Leader><Leader>t'
" COC
" let g:coc_node_path = '$HOME/.nvm/versions/node/v12.16.3/bin/node'
let g:coc_disable_startup_warning = 1
set updatetime=300
set shortmess+=c " don't give |ins-completion-menu| messages.
@@ -321,4 +322,22 @@ let g:rust_fold = 2
let g:processing_fold = 1
" - Markdown -
" Livedown
let g:livedown_open = 1
" Markdown Preview
" --- AI ---
" Claude Code
" plugin/claudecode.lua auto-calls require('claudecode').setup(g:claudecode_auto_setup)
" once the plugin loads (during plug#end() below), so this must be a plain
" vimscript dict rather than a lua block -- see the guarded keymaps in
" bindings.vimrc for the commands this enables.
" Full option list: https://github.com/coder/claudecode.nvim#configuration-options
let g:claudecode_auto_setup = {
\ 'terminal': {
\ 'provider': 'snacks',
\ 'split_side': 'right',
\ 'split_width_percentage': 0.30,
\ },
\ }
+4
View File
@@ -0,0 +1,4 @@
vim.bo.textwidth = 79
if vim.bo.modifiable then
vim.bo.fileformat = "unix"
end
+36
View File
@@ -0,0 +1,36 @@
local map = function(mode, lhs, rhs)
vim.keymap.set(mode, lhs, rhs, { buffer = true })
end
map("n", "<leader>mm", "<Plug>VimwikiIndex")
map("n", "<leader>mw", "<Plug>VimwikiUISelect")
map("n", "<leader>mhelp", ":verbose map ,m<CR>")
map("n", "<leader>mg", "<Plug>VimwikiGoto")
map("n", "<leader>mf", "<Plug>VimwikiUISelect1<CR>")
map("n", "<leader>m<Space>", "<Plug>VimwikiUISelect2<CR>")
map("n", "<leader>mp", "<Plug>VimwikiUISelect3<CR>")
map("n", "<leader>ms", "<Plug>VimwikiUISelect4<CR>")
map("n", "<leader>m-", "<Plug>VimwikiSplitLink")
map("n", "<leader>m<Bar>", "<Plug>VimwikiVSplitLink")
map("n", "<leader>mnt", "<Plug>VimwikiNextTask")
map("n", "<leader>mnl", "<Plug>VimwikiNextLink")
map("n", "<leader>mNl", "<Plug>VimwikiPrevLink")
map({ "n", "i", "v" }, "<Tab>", "<Plug>VimwikiIncreaseLvlSingleItem")
map({ "n", "i", "v" }, "<S-Tab>", "<Plug>VimwikiDecreaseLvlSingleItem")
map("i", "<C-Space>", "<Esc><Plug>VimwikiToggleListItemA")
map("n", "<C-d><C-Space>", "<Plug>VimwikiRemoveSingleCB")
map("i", "<C-d><C-Space>", "<Esc><Plug>VimwikiRemoveSingleCBa")
map("n", "<leader>mb", "<Plug>VimwikiBackLinks")
map("n", "<leader>mqtoc", "<Plug>VimwikiTOC")
map("n", "<leader>mqgtl", "<Plug>VimwikiRebuildTags<CR><Plug>VimwikiGenerateTagLinks<CR>")
map("v", "<leader>mk", 'c[]<Esc>Pea()<Esc>"+P')
map("i", "<leader>mk", '<Esc>viW<C-k>ea')
map("n", "<leader>mk", 'ciw[]<Esc>Pea()<Esc>"+P')
map("n", "<leader>mag", ":ZettelOpen<CR>")
map("n", "<leader>mat", ":ZettelOpen<CR>title:")
+91
View File
@@ -0,0 +1,91 @@
-- Version guard: native LSP config (vim.lsp.config/vim.lsp.enable, added in
-- 0.11) and the pinned nvim-treesitter (hard-requires 0.12 in its own health
-- check) both need a current Neovim. Older versions -- e.g. Debian's apt
-- package, which lags upstream by a long way even fully updated -- don't
-- fail here; they fail later with a confusing cascade of lspconfig and
-- mason-lspconfig errors. Check up front instead, before anything else in
-- this file runs (some of it, like vim.uv below, doesn't exist pre-0.10).
if vim.fn.has("nvim-0.12") == 0 then
local ok, v = pcall(vim.version)
local current = ok and string.format("%d.%d.%d", v.major, v.minor, v.patch) or "an older version"
-- vim.loop (not vim.uv -- that alias doesn't exist pre-0.10) to detect the
-- machine's arch, since Neovim ships separate release assets per arch and
-- the install command below needs to name the right one.
local machine = (vim.loop.os_uname() or {}).machine or ""
local asset_arch = ({ x86_64 = "x86_64", amd64 = "x86_64", aarch64 = "arm64", arm64 = "arm64" })[machine]
if not asset_arch then
vim.api.nvim_echo({
{
"This config requires Neovim 0.12.0 or newer (found "
.. current
.. "). No prebuilt Neovim release is published for this machine's architecture ("
.. (machine ~= "" and machine or "unknown")
.. "); check https://github.com/neovim/neovim/releases/latest for a build, or install from source.\n",
"ErrorMsg",
},
}, true, {})
vim.fn.getchar()
os.exit(1)
end
local sysname = ((vim.loop.os_uname() or {}).sysname or ""):lower()
local is_mac = sysname == "darwin"
local asset = (is_mac and "nvim-macos-" or "nvim-linux-") .. asset_arch
local lines = {
{ "This config requires Neovim 0.12.0 or newer (found " .. current .. ", " .. machine .. ").\n\n", "ErrorMsg" },
{ "Install a current build into ~/.local (no root needed):\n", "None" },
{ " curl -LO https://github.com/neovim/neovim/releases/latest/download/" .. asset .. ".tar.gz\n", "None" },
{ " mkdir -p ~/.local && tar xzf " .. asset .. ".tar.gz --strip-components=1 -C ~/.local\n", "None" },
{ " rm " .. asset .. ".tar.gz\n", "None" },
{ " # then make sure ~/.local/bin is on your PATH\n\n", "Comment" },
}
if not is_mac then
vim.list_extend(lines, {
{ "Or system-wide (needs root):\n", "None" },
{ " curl -LO https://github.com/neovim/neovim/releases/latest/download/" .. asset .. ".tar.gz\n", "None" },
{ " sudo mkdir -p /opt/nvim && sudo tar xzf " .. asset .. ".tar.gz --strip-components=1 -C /opt/nvim\n", "None" },
{ " sudo ln -sf /opt/nvim/bin/nvim /usr/local/bin/nvim\n", "None" },
{ " rm " .. asset .. ".tar.gz\n", "None" },
})
end
vim.api.nvim_echo(lines, true, {})
vim.fn.getchar()
os.exit(1)
end
-- Leader keys MUST be set before lazy.setup() so lazy-loaded `keys = {...}`
-- specs resolve <leader> correctly when they register their keymaps.
vim.g.mapleader = ","
vim.g.maplocalleader = "\\"
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.uv.fs_stat(lazypath) then
local out = vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable",
lazypath,
})
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
require("config.options")
require("config.keymaps")
require("config.autocmds")
require("lazy").setup("plugins", {
change_detection = { notify = false },
})
+47
View File
@@ -0,0 +1,47 @@
{
"aerial.nvim": { "branch": "master", "commit": "28fe6e822ae344544c379d60fcb13c9519a1f08a" },
"alpha-nvim": { "branch": "main", "commit": "6c6a89d5b068b5251c8bdf0dd57bb921bcfeeb09" },
"blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" },
"blink.lib": { "branch": "main", "commit": "5876dd95deeb70aadbe9f1c0b7117a135061cdac" },
"bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
"claudecode.nvim": { "branch": "main", "commit": "2390c6e45c4789072c293ac69de051d169668b29" },
"conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" },
"emmet-vim": { "branch": "master", "commit": "92ef2f74f4093edc99db5e9e4cf7e40116a85bd6" },
"flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" },
"gitsigns.nvim": { "branch": "main", "commit": "eb60cc7b94c46005237fd34170d76f3a089a90aa" },
"gruvbox.nvim": { "branch": "main", "commit": "154eb5ff5b96d0641307113fa385eaf0d36d9796" },
"indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" },
"lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" },
"lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" },
"markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" },
"mason-lspconfig.nvim": { "branch": "main", "commit": "47059d71b42d74b0a1e9f61c1d99d301039c3b5b" },
"mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" },
"mini.align": { "branch": "main", "commit": "8cebe89d82f20e6d21b27346bcde4b4b6244a9f1" },
"mini.bufremove": { "branch": "main", "commit": "4cfbb201b2760da79ca6e1a00e9f67cbc99cbb8f" },
"neo-tree.nvim": { "branch": "v3.x", "commit": "ebd66767191714e008ce73b769518a763ff31bdc" },
"nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" },
"nvim-autopairs": { "branch": "master", "commit": "7b9923abad60b903ece7c52940e1321d39eccc79" },
"nvim-dap": { "branch": "master", "commit": "9e848e09a697ee95302a3ef2dd43fd6eb709e570" },
"nvim-dap-python": { "branch": "master", "commit": "1808458eba2b18f178f990e01376941a42c7f93b" },
"nvim-lint": { "branch": "master", "commit": "a219b2c9e5b4765e5c845aba119dad55806fcaf1" },
"nvim-lspconfig": { "branch": "master", "commit": "d224a1920728ba129880efc700d4a0180ac4ecbb" },
"nvim-surround": { "branch": "main", "commit": "8b47db616ef658b8fc27e61db2896aa2f40134de" },
"nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" },
"nvim-treesitter-context": { "branch": "master", "commit": "b311b30818951d01f7b4bf650521b868b3fece16" },
"nvim-web-devicons": { "branch": "master", "commit": "dad71387de386a946b123079d0e53f23028f3abd" },
"persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" },
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
"rainbow-delimiters.nvim": { "branch": "master", "commit": "a798325b7f36acc62741d1029930a7b96d4dd4bf" },
"rustaceanvim": { "branch": "main", "commit": "88575b98bb9937fb9983ddec5e532b67e75ce677" },
"snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" },
"telescope-fzf-native.nvim": { "branch": "main", "commit": "b25b749b9db64d375d782094e2b9dce53ad53a40" },
"telescope.nvim": { "branch": "master", "commit": "427b576c16792edad01a92b89721d923c19ad60f" },
"undotree": { "branch": "main", "commit": "02b69aed427b848c4dca483fc5e9524b6019c296" },
"vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" },
"vim-table-mode": { "branch": "master", "commit": "bb025308a45c67c7c8f0763ba37bc2ee3f534df0" },
"vim-tmux-navigator": { "branch": "master", "commit": "e41c431a0c7b7388ae7ba341f01a0d217eb3a432" },
"vim-visual-multi": { "branch": "master", "commit": "a6975e7c1ee157615bbc80fc25e4392f71c344d4" },
"vim-zettel": { "branch": "master", "commit": "554d16bf65b04ae86b92db08a44b4fbcbc31023f" },
"vimwiki": { "branch": "dev", "commit": "a54a3002e229c4b43d69ced170ff77663a5b2c40" },
"which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }
}
+63
View File
@@ -0,0 +1,63 @@
-- autoread (options.lua) only reloads a buffer once Vim checks the file's
-- timestamp, which by default only happens on a handful of internal
-- triggers. Force that check on focus/buffer-switch/idle so external edits
-- (e.g. from claudecode.nvim) show up immediately instead of surfacing the
-- stale-buffer prompt later.
vim.api.nvim_create_autocmd({ "FocusGained", "BufEnter", "CursorHold", "CursorHoldI" }, {
group = vim.api.nvim_create_augroup("CheckTimeOnFocus", { clear = true }),
callback = function()
if vim.fn.getcmdwintype() == "" then
vim.cmd("checktime")
end
end,
})
local augroup = vim.api.nvim_create_augroup("EnterBuffer", { clear = true })
vim.api.nvim_create_autocmd({ "BufNewFile", "BufReadPre", "FileReadPre", "BufEnter" }, {
group = augroup,
pattern = "Makefile",
callback = function()
vim.bo.expandtab = false
vim.bo.softtabstop = 0
vim.bo.shiftwidth = 8
end,
})
vim.api.nvim_create_autocmd({ "BufNewFile", "BufReadPre", "FileReadPre", "BufEnter" }, {
group = augroup,
pattern = { "*.asm", "*.S" },
callback = function()
vim.bo.softtabstop = 8
vim.bo.shiftwidth = 8
end,
})
-- dejima sets DEJIMA, never present on a normal host session, so this only
-- fires inside the sandbox: open claudecode.nvim's terminal on startup
-- rather than requiring <leader>ac, since starting a Claude session is the
-- entire point of being in there.
-- :ClaudeCode is defined by the plugin itself, so it doesn't exist until
-- claudecode.nvim has actually loaded - it's lazy-loaded on the <leader>ac
-- keymap only (no `cmd` in its lazy.nvim spec), so force that load first.
if vim.env.DEJIMA then
vim.api.nvim_create_autocmd("VimEnter", {
once = true,
callback = function()
vim.schedule(function()
require("lazy").load({ plugins = { "claudecode.nvim" } })
vim.cmd("ClaudeCode")
-- :ClaudeCode leaves the terminal window focused, so `tab split` gives
-- the same terminal buffer a full-screen window in its own tab while
-- the original tab keeps the narrow split next to the editor - one tab
-- to work in Claude, one to work side-by-side. Window-local options are
-- inherited by the split, and snacks' auto_insert (buffer-local) puts
-- the new window back into terminal mode on entry.
local claude_buf = require("claudecode.terminal").get_active_terminal_bufnr()
if claude_buf and vim.api.nvim_get_current_buf() == claude_buf then
vim.cmd("tab split")
end
end)
end,
})
end
+59
View File
@@ -0,0 +1,59 @@
local map = vim.keymap.set
-- Insert/command-mode escape via ,,
map("i", ",,", "<Esc>", { desc = "Escape insert mode" })
map("c", ",,", "<Esc><Esc>", { desc = "Escape command mode" })
-- Terminal mode is a separate mode from Insert, so the above doesn't cover
-- it (e.g. the Claude Code terminal). <C-\><C-n> is the real escape back to
-- Normal mode there.
map("t", ",,", "<C-\\><C-n>", { desc = "Escape terminal mode" })
-- Move by display line, not physical line
map("n", "j", "gj", { desc = "Move down by display line" })
map("n", "k", "gk", { desc = "Move up by display line" })
-- Clear search highlight
map("n", "<leader><leader><Esc>", ":nohl<CR>", { desc = "Clear search highlight" })
-- Hex mode
map("n", "<leader>\\he", ":%!xxd<CR>", { desc = "Hex dump buffer" })
map("n", "<leader>\\hd", ":%!xxd -r<CR>", { desc = "Undo hex dump" })
-- Toggle whitespace display
map("n", "<leader><leader>lw", ":set list!<CR>", { desc = "Toggle whitespace display" })
-- List registers / marks
map("n", "<leader><leader>lr", ":reg<CR>", { desc = "List registers" })
map("n", "<leader><leader>lm", ":marks<CR>", { desc = "List marks" })
-- Prev/next buffer
map("n", "<leader>q", ":bp<CR>", { desc = "Previous buffer" })
map("n", "<leader>w", ":bn<CR>", { desc = "Next buffer" })
-- System clipboard
map({ "n", "v" }, "<leader>y", '"+y', { desc = "Yank to system clipboard" })
map({ "n", "v" }, "<leader>Y", '"+Y', { desc = "Yank line to system clipboard" })
map({ "n", "v" }, "<leader>p", '"+p', { desc = "Paste from system clipboard" })
map({ "n", "v" }, "<leader>P", '"+P', { desc = "Paste before from system clipboard" })
map({ "n", "v" }, "<leader>x", '"+x', { desc = "Cut to system clipboard" })
map("n", "<leader>dd", '"+dd', { desc = "Delete line to system clipboard" })
-- Make split
map("n", "<leader>-", ":sp<Space>", { desc = "Horizontal split" })
map("n", "<leader><Bar>", ":vsp<Space>", { desc = "Vertical split" })
-- Open init.lua
map("n", "<leader>v", ":e $MYVIMRC<CR>", { desc = "Edit init.lua" })
-- Low-light / daylight mode
map("n", "<leader><leader>ll", ":set background=dark<CR>", { desc = "Dark background" })
map("n", "<leader><leader>LL", ":set background=light<CR>", { desc = "Light background" })
-- Ranger / trailing whitespace utilities
map("n", "<leader>ra", function() require("util").ranger() end, { desc = "Open ranger" })
map("n", "<leader>rw", function() require("util").delete_trailing_ws() end, { desc = "Delete trailing whitespace" })
-- Terminal-mode Ctrl-Z otherwise goes straight to the embedded process (e.g.
-- suspending the claude CLI inside claudecode.nvim's terminal with no way to
-- fg it back) instead of suspending Neovim itself, like Ctrl-Z does by
-- default in Normal mode.
map("t", "<C-z>", "<C-\\><C-n><C-z>", { desc = "Suspend Neovim" })
+94
View File
@@ -0,0 +1,94 @@
local opt = vim.opt
-- Completion / buffers
opt.omnifunc = "syntaxcomplete#Complete"
opt.hidden = true
opt.autoread = true
-- No swap/backup files
opt.swapfile = false
opt.backup = false
opt.number = true
-- matchit is built into Neovim's runtime already; no `runtime macros/matchit.vim` needed
opt.encoding = "utf-8"
opt.lazyredraw = true
opt.backspace = { "indent", "eol", "start" }
opt.history = 700
opt.incsearch = true
opt.ignorecase = true
opt.smartcase = true
opt.scrolloff = 15
opt.wildmode = { "longest", "list", "full" }
opt.wildmenu = true
opt.wildcharm = vim.api.nvim_replace_termcodes("<C-Z>", true, true, true):byte()
opt.mouse = "a"
-- Tabs
opt.tabstop = 4
opt.softtabstop = 4
opt.expandtab = true
opt.shiftwidth = 4
opt.wrap = true
opt.linebreak = true
opt.list = false
opt.ruler = true
opt.showmatch = true
opt.viewoptions:remove("options")
opt.shortmess:append("I")
opt.laststatus = 2
opt.showmode = false
opt.termguicolors = true
vim.g.enable_bold_font = 1
-- Have vrm extend background color to full terminal screen
vim.cmd("set t_ut=")
opt.splitbelow = true
opt.splitright = true
opt.updatetime = 300
opt.shortmess:append("c")
-- Clipboard: copy-only, via dotfiles/bin/clipboard-copy. This is a small
-- script (rather than nvim's built-in raw-OSC-52-only provider) because
-- reaching the real clipboard needs more than a raw OSC 52 write: it picks
-- pbcopy/xclip/wl-copy when nvim is running locally, and when none of those
-- are available (nvim on a remote host with no local display) sends a
-- single plain OSC 52 write. Any tmux hops between here and the real
-- terminal relay that onward themselves via the pane-set-clipboard hook in
-- tmux.conf, so this works whether nvim is local or several ssh/tmux hops
-- deep, on any machine sharing this dotfiles repo, without needing to know
-- how many hops there are. Paste is intentionally left as a no-op: OSC 52
-- read support is inconsistent across terminals and can hang waiting for a
-- reply, so use the terminal's own native paste (e.g. Ctrl-Shift-V)
-- instead. Guarded on executable() rather than assumed present - not every
-- machine this config runs on has the rest of dotfiles checked out too
-- (e.g. dejima mounts in only this nvim config directory), and
-- without the guard vim.g.clipboard would point at a script that isn't
-- there, erroring on every yank instead of just falling back to nvim's
-- default clipboard handling.
local clipboard_copy = vim.fn.expand("~/dotfiles/bin/clipboard-copy")
if vim.fn.executable(clipboard_copy) == 1 then
vim.g.clipboard = {
name = "clipboard-copy (copy-only)",
copy = {
["+"] = { clipboard_copy },
["*"] = { clipboard_copy },
},
paste = {
["+"] = function() return {} end,
["*"] = function() return {} end,
},
}
end
+104
View File
@@ -0,0 +1,104 @@
return {
{ "folke/snacks.nvim", lazy = false },
{
"coder/claudecode.nvim",
dependencies = { "folke/snacks.nvim" },
opts = {
terminal = {
provider = "snacks",
split_side = "right",
split_width_percentage = 0.30,
-- snacks.nvim's terminal style binds a double-<Esc>-within-200ms
-- shortcut (term_normal) that silently drops the buffer out of
-- terminal-mode into Neovim's own Normal mode -- swallowing the
-- second Esc instead of forwarding it to the claude CLI, which uses
-- double-Esc itself (e.g. to rewind/interrupt). Once stuck in Normal
-- mode there (invisible, since showmode is off), the next keystroke
-- meant for the CLI -- e.g. Ctrl-O to toggle expanded tool output --
-- is instead consumed by Neovim's built-in Normal-mode <C-o> (jump
-- to older jumplist position), yanking focus to a different window.
-- Disabling this shortcut makes every Esc pass through raw to the
-- CLI; ,, (config/keymaps.lua) remains the deliberate way to reach
-- Normal mode in this terminal.
snacks_win_opts = {
keys = {
term_normal = false,
-- Per :help terminal-mode, when the running program hasn't enabled
-- its own mouse reporting (the claude CLI doesn't), any mouse event
-- over the terminal -- including the scroll wheel -- drops terminal
-- focus to Neovim's Normal mode instead of being forwarded, leaving
-- you stuck there (invisibly, since showmode is off) until you press
-- 'i' again -- and clicks meant for the CLI (e.g. approval prompts)
-- land as buffer-cursor movement in the meantime. Intercept the
-- wheel so it scrolls the window and silently returns to terminal
-- mode, instead of leaving that to the default behavior.
scroll_up = {
"<ScrollWheelUp>",
"<C-\\><C-n><ScrollWheelUp>i",
mode = "t",
desc = "Scroll up without leaving terminal mode",
},
scroll_down = {
"<ScrollWheelDown>",
"<C-\\><C-n><ScrollWheelDown>i",
mode = "t",
desc = "Scroll down without leaving terminal mode",
},
},
},
},
diff_opts = {
keep_terminal_focus = true,
-- Unified (single-buffer, VS Code-style) diff instead of side-by-side
-- splits: it only ever opens one new window, so it can't add a second
-- split and squish the rest of the layout the way the side-by-side
-- diff sometimes did.
layout = "unified",
},
},
config = function(_, opts)
require("claudecode").setup(opts)
-- claudecode picks a window for the diff by scanning all windows for the
-- first non-sidebar/non-terminal one, not the one you're actually
-- focused on, so the diff could land away from your active pane. Prefer
-- the current window when it's a normal editing window.
local diff = require("claudecode.diff")
local default_find_main_editor_window = diff._find_main_editor_window
diff._find_main_editor_window = function()
local win = vim.api.nvim_get_current_win()
local buf = vim.api.nvim_win_get_buf(win)
local buftype = vim.api.nvim_buf_get_option(buf, "buftype")
local win_config = vim.api.nvim_win_get_config(win)
local is_floating = win_config.relative and win_config.relative ~= ""
local is_diff_win = vim.api.nvim_win_get_option(win, "diff")
if not is_floating and not is_diff_win and buftype ~= "terminal" and buftype ~= "prompt" then
return win
end
return default_find_main_editor_window()
end
-- claudecode's unified diff buffers pick up treesitter's foldexpr via
-- the normal FileType autocmd, so they otherwise inherit the global
-- foldlevelstart and open partially collapsed. Fully expand folds in
-- these specifically instead of changing the default for all buffers.
vim.api.nvim_create_autocmd("BufWinEnter", {
group = vim.api.nvim_create_augroup("ClaudeCodeDiffUnfold", { clear = true }),
callback = function(args)
if vim.b[args.buf].claudecode_inline_diff then
vim.wo.foldlevel = 99
end
end,
})
end,
keys = {
{ "<leader>ac", "<cmd>ClaudeCode<CR>", desc = "Toggle Claude Code" },
{ "<leader>af", "<cmd>ClaudeCodeFocus<CR>", desc = "Focus Claude Code" },
{ "<leader>ab", "<cmd>ClaudeCodeAdd %<CR>", desc = "Add buffer to Claude Code" },
{ "<leader>as", "<cmd>ClaudeCodeSend<CR>", mode = "v", desc = "Send selection to Claude Code" },
{ "<leader>aa", "<cmd>ClaudeCodeDiffAccept<CR>", desc = "Accept Claude Code diff" },
{ "<leader>ad", "<cmd>ClaudeCodeDiffDeny<CR>", desc = "Deny Claude Code diff" },
},
},
}
+10
View File
@@ -0,0 +1,10 @@
return {
"saghen/blink.cmp",
version = "*",
opts = {
keymap = { preset = "default" },
appearance = { nerd_font_variant = "mono" },
completion = { documentation = { auto_show = true } },
sources = { default = { "lsp", "path", "buffer" } },
},
}
+33
View File
@@ -0,0 +1,33 @@
return {
{
"mfussenegger/nvim-dap",
keys = {
{ "<leader>db", function() require("dap").toggle_breakpoint() end, desc = "Toggle breakpoint" },
{ "<leader>dc", function() require("dap").continue() end, desc = "Debug: continue" },
{ "<leader>di", function() require("dap").step_into() end, desc = "Debug: step into" },
{ "<leader>do", function() require("dap").step_over() end, desc = "Debug: step over" },
{ "<leader>dO", function() require("dap").step_out() end, desc = "Debug: step out" },
{ "<leader>dr", function() require("dap").repl.toggle() end, desc = "Debug: toggle REPL" },
{ "<leader>dq", function() require("dap").terminate() end, desc = "Debug: terminate" },
},
},
{
-- Configures nvim-dap for Python using debugpy, installed via Mason
-- (:MasonInstall debugpy) so it lives in an isolated venv rather than
-- needing debugpy in every project's own environment.
"mfussenegger/nvim-dap-python",
dependencies = { "mfussenegger/nvim-dap" },
ft = "python",
config = function()
local python = vim.fn.stdpath("data") .. "/mason/packages/debugpy/venv/bin/python"
if vim.fn.executable(python) == 0 then
vim.notify(
"debugpy not installed: run :MasonInstall debugpy to enable Python debugging",
vim.log.levels.WARN
)
return
end
require("dap-python").setup(python)
end,
},
}
+137
View File
@@ -0,0 +1,137 @@
return {
{
"nvim-neo-tree/neo-tree.nvim",
branch = "v3.x",
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-tree/nvim-web-devicons",
"MunifTanjim/nui.nvim",
},
keys = {
{ "<leader>t", ":Neotree toggle<CR>", desc = "Toggle file explorer" },
{
"<leader>cd",
function()
vim.cmd("cd " .. vim.fn.fnameescape(vim.fn.expand("%:p:h")))
vim.cmd("pwd")
vim.cmd("Neotree dir=" .. vim.fn.fnameescape(vim.fn.getcwd()))
end,
desc = "cd to current file's directory and open explorer",
},
},
opts = {},
},
{
"nvim-telescope/telescope.nvim",
dependencies = {
"nvim-lua/plenary.nvim",
{ "nvim-telescope/telescope-fzf-native.nvim", build = "make" },
},
cmd = "Telescope",
keys = {
{ "<leader>.", "<cmd>Telescope lsp_document_symbols<CR>", desc = "Jump to symbol" },
{ "<leader>;", "<cmd>Telescope buffers<CR>", desc = "Jump to buffer" },
{
"<leader>be",
"<cmd>Telescope buffers sort_mru=true ignore_current_buffer=true<CR>",
desc = "Jump to buffer (MRU)",
},
{ "<leader>ag", "<cmd>Telescope live_grep<CR>", desc = "Grep" },
{ "<leader>?", "<cmd>Telescope keymaps<CR>", desc = "Search keybindings" },
},
config = function()
local telescope = require("telescope")
telescope.setup({})
telescope.load_extension("fzf")
end,
},
{
"folke/flash.nvim",
event = "VeryLazy",
opts = {},
keys = {
{ "<leader>/", function() require("flash").jump() end, mode = { "n", "x", "o" }, desc = "Flash jump" },
{ "<leader>s", function() require("flash").jump({ search = { mode = "search" } }) end, mode = { "n", "x", "o" }, desc = "Flash search jump" },
{ "<leader><leader>s", function() require("flash").treesitter() end, mode = { "n", "x", "o" }, desc = "Flash treesitter" },
{ "<leader>f", function() require("flash").jump({ search = { forward = true, wrap = false } }) end, mode = { "n", "x", "o" }, desc = "Flash forward" },
},
},
{ "kylechui/nvim-surround", event = { "BufReadPost", "BufNewFile" }, opts = {} },
{ "windwp/nvim-autopairs", event = "InsertEnter", opts = {} },
{
"nvim-treesitter/nvim-treesitter-context",
event = { "BufReadPost", "BufNewFile" },
dependencies = { "nvim-treesitter/nvim-treesitter" },
opts = {},
},
{
"echasnovski/mini.align",
version = "*",
keys = {
{ "ga=", mode = { "n", "x" }, desc = "Align on =" },
{ "ga:", mode = { "n", "x" }, desc = "Align on :" },
},
config = function()
require("mini.align").setup({
mappings = { start = "ga", start_with_preview = "" },
})
end,
},
{ "echasnovski/mini.bufremove", version = "*", keys = {
{ "<leader><leader>c", function() require("mini.bufremove").delete(0, false) end, desc = "Close buffer" },
} },
{
"mg979/vim-visual-multi",
branch = "master",
keys = { "<C-n>" },
init = function()
vim.g.VM_maps = {
["Find Under"] = "<C-n>",
["Find Subword Under"] = "<C-n>",
}
end,
},
{
"christoomey/vim-tmux-navigator",
lazy = false,
-- Plugin's own default mappings rely on a Vim-only <C-w> terminal escape
-- that Neovim doesn't support, so :terminal buffers (e.g. claudecode.nvim)
-- leak the raw keystrokes to the embedded process. Disable them and
-- define our own, using Neovim's actual terminal-mode escape.
init = function()
vim.g.tmux_navigator_no_mappings = 1
end,
keys = {
{ "<C-h>", "<cmd>TmuxNavigateLeft<CR>" },
{ "<C-j>", "<cmd>TmuxNavigateDown<CR>" },
{ "<C-k>", "<cmd>TmuxNavigateUp<CR>" },
{ "<C-l>", "<cmd>TmuxNavigateRight<CR>" },
{ "<C-h>", "<C-\\><C-n><cmd>TmuxNavigateLeft<CR>", mode = "t" },
{ "<C-j>", "<C-\\><C-n><cmd>TmuxNavigateDown<CR>", mode = "t" },
{ "<C-k>", "<C-\\><C-n><cmd>TmuxNavigateUp<CR>", mode = "t" },
{ "<C-l>", "<C-\\><C-n><cmd>TmuxNavigateRight<CR>", mode = "t" },
},
},
{
"mattn/emmet-vim",
ft = { "html", "css" },
init = function()
vim.g.user_emmet_install_global = 0
end,
config = function()
vim.api.nvim_create_autocmd("FileType", {
pattern = { "html", "css" },
callback = function() vim.cmd("EmmetInstall") end,
})
end,
},
}
+55
View File
@@ -0,0 +1,55 @@
return {
{
"stevearc/conform.nvim",
event = { "BufWritePre" },
cmd = { "ConformInfo" },
opts = {
formatters_by_ft = {
css = { "prettier" },
svelte = { "prettier" },
pcss = { "prettier" },
html = { "prettier" },
typescript = { "prettier" },
typescriptreact = { "prettier" },
javascript = { "prettier" },
javascriptreact = { "prettier" },
json = { "prettier" },
yaml = { "prettier" },
markdown = { "prettier" },
python = { "ruff_format" },
rust = { "rustfmt" },
lua = { "stylua" },
},
format_on_save = {
lsp_format = "fallback",
timeout_ms = 2000,
},
},
},
{
"mfussenegger/nvim-lint",
event = { "BufWritePost", "BufReadPost", "InsertLeave" },
config = function()
require("lint").linters_by_ft = {
javascript = { "eslint_d" },
typescript = { "eslint_d" },
javascriptreact = { "eslint_d" },
typescriptreact = { "eslint_d" },
svelte = { "eslint_d" },
}
if vim.fn.executable("shellcheck") == 1 then
require("lint").linters_by_ft.sh = { "shellcheck" }
else
vim.notify("shellcheck not found: skipping shell linting", vim.log.levels.WARN)
end
vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost", "InsertLeave" }, {
callback = function()
require("lint").try_lint()
end,
})
end,
},
}
+4
View File
@@ -0,0 +1,4 @@
return {
{ "lewis6991/gitsigns.nvim", event = { "BufReadPre", "BufNewFile" }, opts = {} },
{ "tpope/vim-fugitive", cmd = { "Git", "Gdiffsplit", "Gvdiffsplit", "Gread", "Gwrite", "Gclog" } },
}
+76
View File
@@ -0,0 +1,76 @@
-- ruff is a prebuilt GitHub release binary, but mason installs basedpyright
-- from PyPI into a venv. Debian ships venv's ensurepip separately
-- (python3-venv), and without it every startup fails the install.
local servers = { "ruff" }
local function has_python_venv()
if vim.fn.executable("python3") ~= 1 then
return false
end
vim.fn.system({ "python3", "-c", "import ensurepip" })
return vim.v.shell_error == 0
end
if has_python_venv() then
table.insert(servers, "basedpyright")
else
vim.notify("python3 venv unavailable (install python3-venv): skipping LSP server basedpyright", vim.log.levels.WARN)
end
local npm_servers = { "ts_ls", "svelte", "html", "cssls", "bashls" }
local function has_public_npm()
if vim.fn.executable("npm") ~= 1 then
return false
end
local result = vim.fn.system("npm config get registry")
return result:find("registry.npmjs.org") ~= nil
end
if has_public_npm() then
vim.list_extend(servers, npm_servers)
else
vim.notify(
"public npm registry unavailable: skipping LSP servers " .. table.concat(npm_servers, ", "),
vim.log.levels.WARN
)
end
return {
{
"mason-org/mason.nvim",
opts = {},
},
{
"mason-org/mason-lspconfig.nvim",
dependencies = { "mason-org/mason.nvim" },
opts = {
ensure_installed = servers,
},
},
{
"neovim/nvim-lspconfig",
dependencies = { "mason-org/mason-lspconfig.nvim", "saghen/blink.cmp", "saghen/blink.lib" },
config = function()
local capabilities = require("blink.cmp").get_lsp_capabilities()
vim.api.nvim_create_autocmd("LspAttach", {
group = vim.api.nvim_create_augroup("LspKeymaps", { clear = true }),
callback = function(args)
local opts = { buffer = args.buf }
vim.keymap.set("n", "K", vim.lsp.buf.hover, opts)
vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts)
vim.keymap.set("n", "gy", vim.lsp.buf.type_definition, opts)
vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts)
vim.keymap.set("n", "gr", vim.lsp.buf.references, opts)
vim.keymap.set("n", "rn", vim.lsp.buf.rename, opts)
vim.keymap.set("v", "ff", function() vim.lsp.buf.format({ async = true }) end, opts)
end,
})
for _, server in ipairs(servers) do
vim.lsp.config(server, { capabilities = capabilities })
vim.lsp.enable(server)
end
end,
},
}
+31
View File
@@ -0,0 +1,31 @@
return {
{
"stevearc/aerial.nvim",
dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-tree/nvim-web-devicons" },
keys = {
{ "<leader>ct", "<cmd>AerialToggle<CR>", desc = "Toggle symbol outline" },
},
opts = {},
},
{
"jiaoshijie/undotree",
dependencies = { "nvim-lua/plenary.nvim" },
keys = {
{ "<leader>u", function() require("undotree").toggle() end, desc = "Toggle undo tree" },
},
opts = {},
},
{
"folke/persistence.nvim",
event = "BufReadPre",
opts = {},
},
{
"folke/which-key.nvim",
event = "VeryLazy",
opts = {},
},
}
+25
View File
@@ -0,0 +1,25 @@
return {
{
"mrcjkb/rustaceanvim",
version = "^6",
lazy = false,
init = function()
vim.g.rustaceanvim = {
tools = {},
server = {
on_attach = function(_, bufnr)
vim.keymap.set("n", "<localleader>rr", function()
vim.cmd.RustLsp("run")
end, { buffer = bufnr })
end,
},
}
end,
},
{
"mason-org/mason-lspconfig.nvim",
opts = {
automatic_enable = { exclude = { "rust_analyzer" } },
},
},
}
+100
View File
@@ -0,0 +1,100 @@
return {
"nvim-treesitter/nvim-treesitter",
lazy = false,
build = ":TSUpdate",
config = function()
local parsers = {
"javascript",
"typescript",
"tsx",
"svelte",
"html",
"css",
"scss",
"json",
"yaml",
"python",
"rust",
"bash",
"lua",
"vim",
"vimdoc",
"query",
"markdown",
"markdown_inline",
"regex",
}
-- Install parsers (skip if the tree-sitter CLI isn't available; parsers
-- already cached from a previous run on this machine still work fine)
if vim.fn.executable("tree-sitter") == 1 then
require("nvim-treesitter").install(parsers)
else
local uname = vim.uv.os_uname()
local sysname = (uname.sysname or ""):lower()
local machine = uname.machine or ""
local is_mac = sysname == "darwin"
local install_cmd
if is_mac then
local arch_part = ({ x86_64 = "x64", amd64 = "x64", aarch64 = "arm64", arm64 = "arm64" })[machine] or "x64"
local asset = "tree-sitter-macos-" .. arch_part
install_cmd = " curl -L https://github.com/tree-sitter/tree-sitter/releases/latest/download/"
.. asset
.. ".gz | gunzip > ~/.local/bin/tree-sitter && chmod +x ~/.local/bin/tree-sitter"
else
install_cmd = " cargo install --root ~/.local tree-sitter-cli"
end
vim.notify(
"tree-sitter CLI not found: skipping install of missing parsers.\n"
.. "Install into ~/.local/bin:\n"
.. install_cmd,
vim.log.levels.WARN
)
end
-- Enable treesitter highlighting, folding, and indentation for
-- filetypes with an installed parser. Note some filetype names differ
-- from their parser names (e.g. "bash" parser -> "sh" filetype).
vim.api.nvim_create_autocmd("FileType", {
pattern = {
"javascript",
"typescript",
"typescriptreact",
"javascriptreact",
"svelte",
"html",
"css",
"scss",
"json",
"yaml",
"python",
"rust",
"sh",
"lua",
"vim",
"help",
"query",
"markdown",
},
callback = function()
-- Highlighting, provided by Neovim. Falls back to Vim's legacy
-- syntax/indent if no parser is installed for this filetype.
if not pcall(vim.treesitter.start) then
return
end
-- Folding, provided by Neovim
vim.wo.foldexpr = "v:lua.vim.treesitter.foldexpr()"
vim.wo.foldmethod = "expr"
-- Indentation, provided by nvim-treesitter
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
end,
})
-- General fold display settings (not treesitter-specific)
vim.opt.foldlevel = 2
vim.opt.foldlevelstart = 2
vim.opt.foldcolumn = "5"
end,
}
+101
View File
@@ -0,0 +1,101 @@
return {
{
"ellisonleao/gruvbox.nvim",
priority = 1000,
opts = {
italic = { strings = true, comments = true, operators = false, folds = true },
invert_selection = true,
invert_signs = false,
},
config = function(_, opts)
require("gruvbox").setup(opts)
vim.o.background = "dark"
local ok = pcall(vim.cmd.colorscheme, "gruvbox")
if not ok then
vim.cmd.colorscheme("desert")
end
end,
},
{
"nvim-lualine/lualine.nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
event = "VeryLazy",
opts = {
options = { theme = "gruvbox" },
},
},
{
"akinsho/bufferline.nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
event = "VeryLazy",
opts = {},
},
{
"lukas-reineke/indent-blankline.nvim",
main = "ibl",
event = { "BufReadPost", "BufNewFile" },
opts = {},
},
{
"HiPhish/rainbow-delimiters.nvim",
event = { "BufReadPost", "BufNewFile" },
},
{ "nvim-tree/nvim-web-devicons", opts = {} },
{
"goolord/alpha-nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
event = "VimEnter",
config = function()
local alpha = require("alpha")
local dashboard = require("alpha.themes.dashboard")
local function fortune_header()
-- cowsay -l prints a header line, then wraps every cow name across
-- several space-separated lines (not one name per line), so a name
-- has to be picked from all of them split on whitespace, not by
-- treating a whole (possibly multi-name) line as one name.
local raw = vim.fn.systemlist("cowsay -l")
local cow = "default"
local names = {}
for i = 2, #raw do
for name in raw[i]:gmatch("%S+") do
table.insert(names, name)
end
end
if #names > 0 then
cow = names[math.random(#names)]
end
local moods = { "b", "d", "g", "p", "s", "t", "w", "y" }
local mood = moods[math.random(#moods)]
local cmd = string.format(
"fortune -a -s | fmt -80 -s | cowthink -%s -f %s -n",
mood,
cow
)
local ok, lines = pcall(vim.fn.systemlist, cmd)
if not ok or #lines == 0 then
return { "Welcome to Neovim" }
end
return lines
end
dashboard.section.header.val = fortune_header()
dashboard.section.buttons.val = {
dashboard.button("e", " New file", ":enew<CR>"),
dashboard.button("f", " Find file", ":Telescope find_files<CR>"),
dashboard.button("g", " Live grep", ":Telescope live_grep<CR>"),
dashboard.button("s", " Restore session", ":lua require('persistence').load()<CR>"),
dashboard.button("q", " Quit", ":qa<CR>"),
}
alpha.setup(dashboard.opts)
vim.keymap.set("n", "<leader><leader>o", ":Alpha<CR>")
end,
},
}
+64
View File
@@ -0,0 +1,64 @@
vim.g.vimwiki_list = {
{
path = "~/synced-notebooks/bradwiki/",
syntax = "markdown",
ext = ".md",
diary_rel_path = "daily_notes/",
diary_index = "index",
diary_header = "Daily Notes",
auto_tags = 1,
auto_diary_index = 1,
auto_generate_links = 1,
auto_generate_tags = 1,
},
{
path = "~/synced-notebooks/work_notebook/",
syntax = "markdown",
ext = ".md",
diary_rel_path = "daily_notes/",
diary_index = "index",
diary_header = "Daily Notes",
auto_tags = 1,
auto_diary_index = 1,
auto_generate_links = 1,
auto_generate_tags = 1,
},
{ path = "~/synced-notebooks/privatewiki/", syntax = "markdown", ext = ".md" },
{ path = "~/synced-notebooks/sharedwiki/", syntax = "markdown", ext = ".md" },
}
vim.g.vimwiki_map_prefix = "<Leader>m"
vim.g.vimwiki_folding = "list"
vim.g.markdown_folding = 1
vim.g.zettel_options = {
{},
{
front_matter = { { "tags", "" }, { "type", "note" } },
template = "~/work_notebook/templates/daily_note.tpl",
},
}
vim.g.table_mode_map_prefix = "<Leader><Leader>t"
vim.api.nvim_create_autocmd("FileType", {
group = vim.api.nvim_create_augroup("VimwikiFiletype", { clear = true }),
pattern = "vimwiki",
callback = function()
vim.opt_local.breakindent = true
vim.opt_local.breakindentopt = "shift:2"
end,
})
return {
{ "vimwiki/vimwiki", lazy = false },
{ "michal-h21/vim-zettel", dependencies = { "vimwiki/vimwiki" }, lazy = false },
{ "dhruvasagar/vim-table-mode", cmd = "TableModeToggle" },
{
"iamcco/markdown-preview.nvim",
build = function() vim.fn["mkdp#util#install"]() end,
ft = { "markdown", "vimwiki" },
keys = {
{ "<localleader>v", "<Plug>MarkdownPreviewToggle", ft = { "markdown", "vimwiki" }, desc = "Toggle markdown preview" },
},
},
}
+28
View File
@@ -0,0 +1,28 @@
local M = {}
-- Open ranger from within nvim; if it writes a chosen path to its return
-- file, open that file. Mirrors the old vimscript Ranger() function.
function M.ranger()
if vim.fn.executable("ranger") == 0 then
vim.notify("ranger is not installed", vim.log.levels.WARN)
return
end
local tmpfile = vim.fn.system("mktemp -u"):gsub("\n", "")
vim.cmd(("silent !RANGER_RETURN_FILE=%s ranger"):format(tmpfile))
if vim.fn.filereadable(tmpfile) == 1 then
local filetoedit = vim.fn.system("cat " .. tmpfile)
vim.cmd("edit " .. filetoedit)
vim.fn.delete(tmpfile)
end
vim.cmd("redraw!")
end
-- Delete trailing whitespace on the current buffer, preserving cursor
-- position. Mirrors the old vimscript DeleteTrailingWS() function.
function M.delete_trailing_ws()
local view = vim.fn.winsaveview()
vim.cmd([[silent! %s/\s\+$//ge]])
vim.fn.winrestview(view)
end
return M
+4 -3
View File
@@ -22,7 +22,6 @@ shadow-exclude = [
"class_g = 'lattedock'",
"_GTK_FRAME_EXTENTS@:c"
]
xinerama-shadow-crop = true;
### Blur
blur:{
@@ -52,8 +51,6 @@ backend = "glx";
#backend = "xrender";
vsync = true;
glx-no-stencil = true;
glx-no-rebind-pixmap = true;
xrender-sync-fence = true;
dbus=true;
@@ -74,3 +71,7 @@ mark-wmwin-focused = true;
mark-ovredir-focused = true;
use-ewmh-active-win = true;
detect-client-leader = true;
## Fixes graphical issues (jitter/flickering) in Jetbrains IDEs
## TODO: This doesn't fully fix the issue
unredir-if-possible = false;
+13
View File
@@ -0,0 +1,13 @@
############################################
# bar settings (input comes from i3blocks) #
############################################
# Start i3bar to display a workspace bar
# (plus the system information i3status finds out, if available)
bar {
# Don't show the bar since we're using plasma bar, comment if using i3 on its own
mode invisible
#mode hide
hidden_state hide
modifier Mod4
}
+22
View File
@@ -0,0 +1,22 @@
# volume
bindsym XF86AudioRaiseVolume exec --no-startup-id qdbus6 org.kde.kglobalaccel /component/kmix invokeShortcut "increase_volume"
bindsym XF86AudioLowerVolume exec --no-startup-id qdbus6 org.kde.kglobalaccel /component/kmix invokeShortcut "decrease_volume"
bindsym XF86AudioMute exec --no-startup-id qdbus6 org.kde.kglobalaccel /component/kmix invokeShortcut "mute"
# mic mute toggle
bindsym XF86AudioMicMute exec --no-startup-id qdbus6 org.kde.kglobalaccel /component/kmix invokeShortcut "mic_mute"
# exit-menu
# using plasma's logout screen instead of i3's
#bindsym $mod+Shift+t exec --no-startup-id qdbus6 org.kde.LogoutPrompt /LogoutPrompt org.kde.LogoutPrompt.promptLogout
#bindsym $mod+Shift+t exec --no-startup-id loginctl kill-session "$USER"
bindsym $mod+Shift+e exec --no-startup-id kill -9 -1
# Lock the system
# lock by blurring the screen:
# TODO: Update to use plasma lock
bindsym $mod+Delete exec --no-startup-id ~/.config/i3/scripts/blur-lock
# applications
bindsym $mod+n exec /usr/bin/dolphin
bindsym $mod+Print exec Spectacle
+169
View File
@@ -0,0 +1,169 @@
{
"colors": {
"black": 16,
"white": 231,
"green": 2,
"darkestgreen": 22,
"darkgreen": 28,
"mediumgreen": 70,
"brightgreen": 148,
"darkestcyan": 23,
"darkcyan": 74,
"mediumcyan": 117,
"brightcyan": 159,
"darkestblue": 24,
"darkblue": 31,
"red": 1,
"darkestred": 52,
"darkred": 88,
"mediumred": 124,
"brightred": 160,
"brightestred": 196,
"darkestpurple": 55,
"mediumpurple": 98,
"brightpurple": 189,
"darkorange": 94,
"mediumorange": 166,
"brightorange": 208,
"brightestorange": 214,
"yellow": 11,
"brightyellow": 220,
"gray0": 233,
"gray1": 235,
"gray2": 236,
"gray3": 239,
"gray4": 240,
"gray5": 241,
"gray6": 244,
"gray7": 245,
"gray8": 247,
"gray9": 250,
"gray10": 252,
"gray11": 234,
"gray90": 254,
"gray70": [249, "b3b3b3"],
"lightyellowgreen": 106,
"gold3": 178,
"orangered": 202,
"steelblue": 67,
"darkorange3": 166,
"skyblue1": 117,
"khaki1": 228,
"solarized:base03": [8, "002b36"],
"solarized:base02": [0, "073642"],
"solarized:base01": [10, "586e75"],
"solarized:base00": [11, "657b83"],
"solarized:base0": [12, "839496"],
"solarized:base1": [14, "93a1a1"],
"solarized:base2": [7, "eee8d5"],
"solarized:base3": [15, "fdf6e3"],
"solarized:yellow": [3, "b58900"],
"solarized:orange": [9, "cb4b16"],
"solarized:red": [1, "dc322f"],
"solarized:magenta": [5, "d33682"],
"solarized:violet": [13, "6c71c4"],
"solarized:blue": [4, "268bd2"],
"solarized:cyan": [6, "2aa198"],
"solarized:green": [2, "859900"],
"gb:dark0_hard": [234, "1d2021"],
"gb:dark0": [235, "282828"],
"gb:dark0_soft": [236, "32302f"],
"gb:dark1": [237, "3c3836"],
"gb:dark2": [239, "504945"],
"gb:dark3": [241, "665c54"],
"gb:dark4": [243, "7c6f64"],
"gb:dark4_256": [243, "7c6f64"],
"gb:gray_245": [245, "928374"],
"gb:gray_244": [244, "928374"],
"gb:light0_hard": [230, "f9f5d7"],
"gb:light0": [229, "fbf1c7"],
"gb:light0_soft": [228, "f2e5bc"],
"gb:light1": [223, "ebdbb2"],
"gb:light2": [250, "d5c4a1"],
"gb:light3": [248, "bdae93"],
"gb:light4": [246, "a89984"],
"gb:light4_256": [246, "a89984"],
"gb:bright_red": [167, "fb4934"],
"gb:bright_green": [142, "b8bb26"],
"gb:bright_yellow": [214, "fabd2f"],
"gb:bright_blue": [109, "83a598"],
"gb:bright_purple": [175, "d3869b"],
"gb:bright_aqua": [108, "8ec07c"],
"gb:bright_orange": [208, "fe8019"],
"gb:neutral_red": [124, "cc241d"],
"gb:neutral_green": [106, "98971a"],
"gb:neutral_yellow": [172, "d79921"],
"gb:neutral_blue": [66, "458588"],
"gb:neutral_purple": [132, "b16286"],
"gb:neutral_aqua": [72, "689d6a"],
"gb:neutral_orange": [166, "d65d0e"],
"gb:faded_red": [88, "9d0006"],
"gb:faded_green": [100, "79740e"],
"gb:faded_yellow": [136, "b57614"],
"gb:faded_blue": [24, "076678"],
"gb:faded_purple": [96, "8f3f71"],
"gb:faded_aqua": [66, "427b58"],
"gb:faded_orange": [130, "af3a03"]
},
"gradients": {
"dark_GREEN_Orange_red": [
[22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 94, 94, 94, 94, 94, 94, 94, 88, 52],
["006000", "006000", "006000", "006000", "006000", "006000", "006000", "006000", "006000", "036000", "076000", "0a6000", "0d6000", "106000", "126000", "146000", "166000", "186000", "1a6000", "1b6000", "1d6000", "1e6000", "206000", "216000", "236000", "246000", "256000", "266000", "286000", "296000", "2a6000", "2b6000", "2c6100", "2d6100", "2f6100", "306100", "316100", "326100", "336100", "346100", "356100", "366100", "376100", "386100", "386100", "396100", "3a6100", "3b6100", "3c6100", "3d6100", "3e6100", "3f6100", "406100", "406100", "416100", "426000", "436000", "446000", "456000", "456000", "466000", "476000", "486000", "496000", "496000", "4a6000", "4b6000", "4c6000", "4d6000", "4d6000", "4e6000", "4f6000", "506000", "506000", "516000", "526000", "536000", "536000", "546000", "556000", "566000", "566000", "576000", "586000", "596000", "596000", "5a6000", "5d6000", "616000", "646000", "686000", "6b6000", "6f6000", "726000", "766000", "796000", "7d6000", "806000", "7e5500", "6f3105", "5d0001"]
],
"GREEN_Orange_red": [
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1],
["005f00", "015f00", "025f00", "035f00", "045f00", "055f00", "065f00", "075f00", "085f00", "095f00", "0b5f00", "0c5f00", "0d5f00", "0e5f00", "0f5f00", "105f00", "115f00", "125f00", "135f00", "145f00", "165f00", "175f00", "185f00", "195f00", "1a5f00", "1b5f00", "1c5f00", "1d5f00", "1e5f00", "1f5f00", "215f00", "225f00", "235f00", "245f00", "255f00", "265f00", "275f00", "285f00", "295f00", "2a5f00", "2c5f00", "2d5f00", "2e5f00", "2f5f00", "305f00", "315f00", "325f00", "335f00", "345f00", "355f00", "375f00", "385f00", "395f00", "3a5f00", "3b5f00", "3c5f00", "3d5f00", "3e5f00", "3f5f00", "415f00", "425f00", "435f00", "445f00", "455f00", "465f00", "475f00", "485f00", "495f00", "4a5f00", "4c5f00", "4d5f00", "4e5f00", "4f5f00", "505f00", "515f00", "525f00", "535f00", "545f00", "555f00", "575f00", "585f00", "595f00", "5a5f00", "5b5f00", "5c5f00", "5d5f00", "5e5f00", "615f00", "655f00", "685f00", "6c5f00", "6f5f00", "735f00", "765f00", "7a5f00", "7d5f00", "815f00", "845f00", "815200", "702900"]
],
"green_yellow_red": [
[190, 184, 178, 172, 166, 160],
["8ae71c", "8ce71c", "8fe71c", "92e71c", "95e71d", "98e71d", "9ae71d", "9de71d", "a0e71e", "a3e71e", "a6e71e", "a8e71e", "abe71f", "aee71f", "b1e71f", "b4e71f", "b6e720", "b9e720", "bce720", "bfe720", "c2e821", "c3e721", "c5e621", "c7e521", "c9e522", "cbe422", "cde322", "cfe222", "d1e223", "d3e123", "d5e023", "d7df23", "d9df24", "dbde24", "dddd24", "dfdc24", "e1dc25", "e3db25", "e5da25", "e7d925", "e9d926", "e9d626", "e9d426", "e9d126", "e9cf27", "e9cc27", "e9ca27", "e9c727", "e9c528", "e9c228", "e9c028", "e9bd28", "e9bb29", "e9b829", "e9b629", "e9b329", "e9b12a", "e9ae2a", "e9ac2a", "e9a92a", "eaa72b", "eaa42b", "eaa22b", "ea9f2b", "ea9d2c", "ea9b2c", "ea982c", "ea962c", "ea942d", "ea912d", "ea8f2d", "ea8d2d", "ea8a2e", "ea882e", "ea862e", "ea832e", "ea812f", "ea7f2f", "ea7c2f", "ea7a2f", "eb7830", "eb7530", "eb7330", "eb7130", "eb6f31", "eb6c31", "eb6a31", "eb6831", "eb6632", "eb6332", "eb6132", "eb5f32", "eb5d33", "eb5a33", "eb5833", "eb5633", "eb5434", "eb5134", "eb4f34", "eb4d34", "ec4b35"]
],
"green_yellow_orange_red": [
[2, 3, 9, 1],
["719e07", "739d06", "759c06", "779c06", "799b06", "7b9a05", "7d9a05", "7f9905", "819805", "839805", "859704", "879704", "899604", "8b9504", "8d9504", "8f9403", "919303", "949303", "969203", "989102", "9a9102", "9c9002", "9e9002", "a08f02", "a28e01", "a48e01", "a68d01", "a88c01", "aa8c01", "ac8b00", "ae8a00", "b08a00", "b28900", "b58900", "b58700", "b68501", "b78302", "b78102", "b87f03", "b97d04", "b97b04", "ba7905", "bb7806", "bb7606", "bc7407", "bd7208", "bd7008", "be6e09", "bf6c0a", "bf6a0a", "c0690b", "c1670c", "c1650c", "c2630d", "c3610e", "c35f0e", "c45d0f", "c55b10", "c55a10", "c65811", "c75612", "c75412", "c85213", "c95014", "c94e14", "ca4c15", "cb4b16", "cb4a16", "cc4917", "cc4818", "cd4719", "cd4719", "ce461a", "ce451b", "cf441c", "cf441c", "d0431d", "d0421e", "d1411f", "d1411f", "d24020", "d23f21", "d33e22", "d33e22", "d43d23", "d43c24", "d53b25", "d53b25", "d63a26", "d63927", "d73828", "d73828", "d83729", "d8362a", "d9352b", "d9352b", "da342c", "da332d", "db322e", "dc322f"]
],
"yellow_red": [
[220, 178, 172, 166, 160],
["ffd700", "fdd500", "fbd300", "fad200", "f8d000", "f7cf00", "f5cd00", "f3cb00", "f2ca00", "f0c800", "efc700", "edc500", "ebc300", "eac200", "e8c000", "e7bf00", "e5bd00", "e3bb00", "e2ba00", "e0b800", "dfb700", "ddb500", "dbb300", "dab200", "d8b000", "d7af00", "d7ad00", "d7ab00", "d7aa00", "d7a800", "d7a700", "d7a500", "d7a300", "d7a200", "d7a000", "d79f00", "d79d00", "d79b00", "d79a00", "d79800", "d79700", "d79500", "d79300", "d79200", "d79000", "d78f00", "d78d00", "d78b00", "d78a00", "d78800", "d78700", "d78500", "d78300", "d78200", "d78000", "d77f00", "d77d00", "d77b00", "d77a00", "d77800", "d77700", "d77500", "d77300", "d77200", "d77000", "d76f00", "d76d00", "d76b00", "d76a00", "d76800", "d76700", "d76500", "d76300", "d76200", "d76000", "d75f00", "d75b00", "d75700", "d75300", "d74f00", "d74c00", "d74800", "d74400", "d74000", "d73c00", "d73900", "d73500", "d73100", "d72d00", "d72900", "d72600", "d72200", "d71e00", "d71a00", "d71600", "d71300", "d70f00", "d70b00", "d70700"]
],
"yellow_orange_red": [
[3, 9, 1],
["b58900", "b58700", "b58600", "b68501", "b68401", "b78202", "b78102", "b88003", "b87f03", "b87d03", "b97c04", "b97b04", "ba7a05", "ba7805", "bb7706", "bb7606", "bc7507", "bc7307", "bc7207", "bd7108", "bd7008", "be6e09", "be6d09", "bf6c0a", "bf6b0a", "c06a0b", "c0680b", "c0670b", "c1660c", "c1650c", "c2630d", "c2620d", "c3610e", "c3600e", "c35e0e", "c45d0f", "c45c0f", "c55b10", "c55910", "c65811", "c65711", "c75612", "c75412", "c75312", "c85213", "c85113", "c94f14", "c94e14", "ca4d15", "ca4c15", "cb4b16", "cb4a16", "cb4a17", "cc4917", "cc4918", "cc4818", "cd4819", "cd4719", "cd471a", "ce461a", "ce461b", "ce451b", "cf451c", "cf441c", "cf441d", "d0431d", "d0431e", "d0421e", "d1421f", "d1411f", "d14120", "d24020", "d24021", "d23f21", "d33f22", "d33e22", "d33e23", "d43d23", "d43d24", "d43c24", "d53c25", "d53b25", "d53b26", "d63a26", "d63a27", "d63927", "d73928", "d73828", "d73829", "d83729", "d8372a", "d8362a", "d9362b", "d9352b", "d9352c", "da342c", "da342d", "da332d", "db332e"]
],
"blue_red": [
[39, 74, 68, 67, 103, 97, 96, 132, 131, 167, 203, 197],
["19b4fe", "1bb2fc", "1db1fa", "1faff8", "22aef6", "24adf4", "26abf2", "29aaf0", "2ba9ee", "2da7ec", "30a6ea", "32a5e8", "34a3e6", "36a2e4", "39a0e2", "3b9fe1", "3d9edf", "409cdd", "429bdb", "449ad9", "4798d7", "4997d5", "4b96d3", "4d94d1", "5093cf", "5292cd", "5490cb", "578fc9", "598dc7", "5b8cc6", "5e8bc4", "6089c2", "6288c0", "6487be", "6785bc", "6984ba", "6b83b8", "6e81b6", "7080b4", "727eb2", "757db0", "777cae", "797aac", "7b79ab", "7e78a9", "8076a7", "8275a5", "8574a3", "8772a1", "89719f", "8c709d", "8e6e9b", "906d99", "926b97", "956a95", "976993", "996791", "9c668f", "9e658e", "a0638c", "a3628a", "a56188", "a75f86", "a95e84", "ac5c82", "ae5b80", "b05a7e", "b3587c", "b5577a", "b75678", "ba5476", "bc5374", "be5273", "c05071", "c34f6f", "c54e6d", "c74c6b", "ca4b69", "cc4967", "ce4865", "d14763", "d34561", "d5445f", "d7435d", "da415b", "dc4059", "de3f58", "e13d56", "e33c54", "e53a52", "e83950", "ea384e", "ec364c", "ee354a", "f13448", "f33246", "f53144", "f83042", "fa2e40"]
],
"white_red": [
[231, 255, 223, 216, 209, 202, 196],
["ffffff", "fefefe", "fdfdfd", "fdfdfd", "fcfcfc", "fbfbfb", "fafafa", "fafafa", "f9f9f9", "f8f8f8", "f7f7f7", "f7f7f7", "f6f6f6", "f5f5f5", "f4f4f4", "f4f3f4", "f3f3f3", "f2f2f2", "f1f1f1", "f0f0f0", "f0f0f0", "efefef", "eeeeee", "efecea", "f1eae4", "f2e8de", "f3e6d8", "f5e4d3", "f6e2cd", "f7e0c7", "f8dec2", "f9dcbc", "fadab6", "fad8b1", "fbd5ac", "fbd2a9", "fbcea5", "fbcaa1", "fbc79e", "fbc39a", "fbc097", "fbbc93", "fbb88f", "fbb58c", "fab188", "faad85", "faaa81", "fba67e", "fba37a", "fb9f76", "fb9c73", "fb986f", "fb946c", "fb9168", "fa8d65", "fa8961", "fa865c", "fa8256", "fb7f4f", "fb7b48", "fb7841", "fb743a", "fb7133", "fb6d2c", "fa6a23", "fa661a", "fa620e", "fa5f03", "fa5d03", "fa5b03", "fa5a03", "fa5803", "fa5703", "fa5503", "fa5303", "fa5103", "fa4f03", "fa4e03", "fa4c03", "fa4a04", "fa4804", "fa4604", "fa4404", "fa4204", "fa3f04", "fa3d04", "fa3b04", "fa3805", "fa3605", "fa3305", "fb3105", "fb2e05", "fb2a05", "fb2705", "fb2306", "fb1f06", "fb1b06", "fb1506", "fb0e06", "fa0506", "fa0007"]
],
"dark_green_gray": [
[70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247],
["51b000", "52b000", "54b000", "55b002", "56b007", "57b00d", "58b011", "59af15", "5aaf18", "5caf1b", "5daf1e", "5eaf21", "5faf23", "60ae25", "61ae27", "62ae2a", "63ae2c", "64ae2e", "65ae30", "66ae31", "67ad33", "68ad35", "69ad37", "69ad38", "6aad3a", "6bad3c", "6cac3d", "6dac3f", "6eac40", "6fac42", "70ac44", "70ac45", "71ab47", "72ab48", "73ab49", "74ab4b", "75ab4c", "75ab4e", "76aa4f", "77aa51", "78aa52", "79aa53", "79aa55", "7aaa56", "7ba957", "7ca959", "7ca95a", "7da95b", "7ea95d", "7fa95e", "7fa85f", "80a861", "81a862", "81a863", "82a865", "83a766", "83a767", "84a768", "85a76a", "85a76b", "86a66c", "87a66d", "87a66f", "88a670", "89a671", "89a672", "8aa574", "8ba575", "8ba576", "8ca577", "8da579", "8da47a", "8ea47b", "8ea47c", "8fa47d", "90a47f", "90a380", "91a381", "91a382", "92a384", "93a385", "93a286", "94a287", "94a288", "95a28a", "95a18b", "96a18c", "97a18d", "97a18e", "98a190", "98a091", "99a092", "99a093", "9aa094", "9aa096", "9b9f97", "9b9f98", "9c9f99", "9c9f9a", "9d9e9c", "9d9e9d"]
],
"light_green_gray": [
[148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 187, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250],
["a3d900", "a4d800", "a4d800", "a5d805", "a5d80d", "a6d714", "a6d719", "a6d71d", "a7d621", "a7d625", "a8d628", "a8d62b", "a8d52e", "a9d531", "a9d533", "aad536", "aad438", "aad43a", "abd43d", "abd33f", "abd341", "acd343", "acd345", "acd247", "add249", "add24b", "add14d", "aed14f", "aed151", "aed152", "afd054", "afd056", "afd058", "b0d059", "b0cf5b", "b0cf5d", "b1cf5e", "b1ce60", "b1ce62", "b1ce63", "b2ce65", "b2cd67", "b2cd68", "b3cd6a", "b3cc6b", "b3cc6d", "b3cc6e", "b4cc70", "b4cb71", "b4cb73", "b4cb75", "b5ca76", "b5ca78", "b5ca79", "b5ca7a", "b6c97c", "b6c97d", "b6c97f", "b6c880", "b6c882", "b7c883", "b7c885", "b7c786", "b7c788", "b7c789", "b8c68a", "b8c68c", "b8c68d", "b8c68f", "b8c590", "b9c591", "b9c593", "b9c494", "b9c496", "b9c497", "b9c498", "bac39a", "bac39b", "bac39d", "bac29e", "bac29f", "bac2a1", "bac2a2", "bac1a4", "bbc1a5", "bbc1a6", "bbc0a8", "bbc0a9", "bbc0aa", "bbc0ac", "bbbfad", "bbbfae", "bbbfb0", "bbbeb1", "bcbeb3", "bcbeb4", "bcbdb5", "bcbdb7", "bcbdb8", "bcbdb9", "bcbcbb"]
]
}
}
@@ -0,0 +1,57 @@
{
"name": "Default",
"groups": {
"information:additional": { "fg": "gray9", "bg": "gray4", "attrs": [] },
"information:regular": { "fg": "gray10", "bg": "gray4", "attrs": ["bold"] },
"information:highlighted": { "fg": "white", "bg": "gray4", "attrs": [] },
"information:priority": { "fg": "brightyellow", "bg": "mediumorange", "attrs": [] },
"warning:regular": { "fg": "white", "bg": "brightred", "attrs": ["bold"] },
"critical:failure": { "fg": "white", "bg": "darkestred", "attrs": [] },
"critical:success": { "fg": "white", "bg": "darkestgreen", "attrs": [] },
"background": { "fg": "white", "bg": "gray0", "attrs": [] },
"background:divider": { "fg": "gray5", "bg": "gray0", "attrs": [] },
"session": { "fg": "black", "bg": "gray10", "attrs": ["bold"] },
"date": { "fg": "gray8", "bg": "gray2", "attrs": [] },
"time": { "fg": "gray10", "bg": "gray2", "attrs": ["bold"] },
"time:divider": { "fg": "gray5", "bg": "gray2", "attrs": [] },
"email_alert": "warning:regular",
"email_alert_gradient": { "fg": "white", "bg": "yellow_orange_red", "attrs": ["bold"] },
"hostname": { "fg": "black", "bg": "gray10", "attrs": ["bold"] },
"weather": { "fg": "gray8", "bg": "gray0", "attrs": [] },
"weather_temp_gradient": { "fg": "blue_red", "bg": "gray0", "attrs": [] },
"weather_condition_hot": { "fg": "khaki1", "bg": "gray0", "attrs": [] },
"weather_condition_snowy": { "fg": "skyblue1", "bg": "gray0", "attrs": [] },
"weather_condition_rainy": { "fg": "skyblue1", "bg": "gray0", "attrs": [] },
"uptime": { "fg": "gray8", "bg": "gray0", "attrs": [] },
"external_ip": { "fg": "gray8", "bg": "gray0", "attrs": [] },
"internal_ip": { "fg": "gray8", "bg": "gray0", "attrs": [] },
"network_load": { "fg": "gray8", "bg": "gray0", "attrs": [] },
"network_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0", "attrs": [] },
"network_load_sent_gradient": "network_load_gradient",
"network_load_recv_gradient": "network_load_gradient",
"network_load:divider": "background:divider",
"system_load": { "fg": "gray8", "bg": "gray0", "attrs": [] },
"system_load_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0", "attrs": [] },
"environment": { "fg": "gray8", "bg": "gray0", "attrs": [] },
"cpu_load_percent": { "fg": "gray8", "bg": "gray0", "attrs": [] },
"cpu_load_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0", "attrs": [] },
"battery": { "fg": "gray8", "bg": "gray0", "attrs": [] },
"battery_gradient": { "fg": "white_red", "bg": "gray0", "attrs": [] },
"battery_full": { "fg": "red", "bg": "gray0", "attrs": [] },
"battery_empty": { "fg": "white", "bg": "gray0", "attrs": [] },
"player": { "fg": "gray10", "bg": "black", "attrs": [] },
"user": { "fg": "white", "bg": "darkblue", "attrs": ["bold"] },
"branch": { "fg": "gray9", "bg": "gray2", "attrs": [] },
"branch_dirty": { "fg": "brightyellow", "bg": "gray2", "attrs": [] },
"branch_clean": { "fg": "gray9", "bg": "gray2", "attrs": [] },
"branch:divider": { "fg": "gray7", "bg": "gray2", "attrs": [] },
"stash": "branch_dirty",
"stash:divider": "branch:divider",
"cwd": "information:additional",
"cwd:current_folder": "information:regular",
"cwd:divider": { "fg": "gray7", "bg": "gray4", "attrs": [] },
"virtualenv": { "fg": "white", "bg": "darkcyan", "attrs": [] },
"attached_clients": { "fg": "gray8", "bg": "gray0", "attrs": [] },
"workspace": "information:regular"
}
}
@@ -0,0 +1,40 @@
{
"name": "Gruvbox Dark",
"groups": {
"information:additional": { "fg": "gb:light2", "bg": "gb:dark2", "attrs": [] },
"information:regular": { "fg": "gb:light0", "bg": "gb:dark2", "attrs": ["bold"] },
"information:highlighted": { "fg": "gb:light0", "bg": "gb:dark2", "attrs": ["bold"]},
"information:priority": { "fg": "gb:light0", "bg": "gb:neutral_yellow", "attrs": [] },
"warning:regular": { "fg": "gb:light0", "bg": "gb:neutral_red", "attrs": [] },
"critical:failure": { "fg": "gb:light0", "bg": "gb:neutral_red", "attrs": [] },
"critical:success": { "fg": "gb:light0", "bg": "gb:neutral_green", "attrs": [] },
"background": { "fg": "gb:light0", "bg": "gb:dark1", "attrs": [] },
"background:divider": { "fg": "gb:light4", "bg": "gb:dark0", "attrs": [] },
"user": { "fg": "gb:light0", "bg": "gb:neutral_blue", "attrs": ["bold"] },
"virtualenv": { "fg": "gb:light0", "bg": "gb:neutral_green", "attrs": [] },
"branch": { "fg": "gb:light4", "bg": "gb:dark1", "attrs": [] },
"branch_dirty": { "fg": "gb:neutral_yellow", "bg": "gb:dark1", "attrs": [] },
"branch_clean": { "fg": "gb:light4", "bg": "gb:dark1", "attrs": [] },
"stash": "branch_dirty",
"email_alert_gradient": { "fg": "gb:light0", "bg": "yellow_orange_neutral_red", "attrs": [] },
"email_alert": "warning:regular",
"cwd": "information:additional",
"cwd:current_folder": "information:regular",
"cwd:divider": { "fg": "gb:light4", "bg": "gb:dark2", "attrs": [] },
"network_load": { "fg": "gb:light4", "bg": "gb:dark0", "attrs": [] },
"network_load:divider": "network_load",
"network_load_gradient": { "fg": "green_yellow_orange_neutral_red", "bg": "gb:dark0", "attrs": [] },
"network_load_sent_gradient": "network_load_gradient",
"network_load_recv_gradient": "network_load_gradient",
"hostname": { "fg": "gb:light0", "bg": "gb:dark2", "attrs": [] },
"environment": { "fg": "gb:light0", "bg": "gb:neutral_green", "attrs": [] },
"attached_clients": { "fg": "gb:light0", "bg": "gb:neutral_green", "attrs": [] },
"date": { "fg": "gb:light4", "bg": "gb:dark1", "attrs": [] },
"time": { "fg": "gb:light4", "bg": "gb:dark1", "attrs": ["bold"] },
"time:divider": { "fg": "gb:light4", "bg": "gb:dark1", "attrs": [] },
"system_load": { "fg": "gb:light4", "bg": "gb:dark0", "attrs": [] },
"weather_temp_gradient": { "fg": "blue_neutral_red", "bg": "gb:dark0", "attrs": [] },
"weather": { "fg": "gb:light4", "bg": "gb:dark0", "attrs": [] },
"uptime": { "fg": "gb:light4", "bg": "gb:dark0", "attrs": [] }
}
}
@@ -0,0 +1,6 @@
{
"groups": {
"prompt": "information:additional",
"prompt_count": "information:highlighted"
}
}
@@ -0,0 +1,8 @@
{
"groups": {
"current_code_name": "information:additional",
"current_context": "current_code_name",
"current_line": "information:regular",
"current_file": "information:regular"
}
}
@@ -0,0 +1,5 @@
{
"groups": {
"stack_depth": { "fg": "gray1", "bg": "gray10", "attrs": ["bold"] }
}
}
@@ -0,0 +1,5 @@
{
"groups": {
"stack_depth": { "fg": "gb:light1", "bg": "gb:light4", "attrs": ["bold"] }
}
}
@@ -0,0 +1,5 @@
{
"groups": {
"stack_depth": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] }
}
}
@@ -0,0 +1,10 @@
{
"groups": {
"continuation": "cwd",
"continuation:current": "cwd:current_folder",
"exit_fail": "critical:failure",
"exit_success": "critical:success",
"jobnum": "information:priority",
"superuser": "warning:regular"
}
}
@@ -0,0 +1,16 @@
{
"name": "Default color scheme for shell prompts",
"groups": {
"hostname": { "fg": "brightyellow", "bg": "mediumorange", "attrs": [] },
"environment": { "fg": "white", "bg": "darkestgreen", "attrs": [] },
"mode": { "fg": "darkestgreen", "bg": "brightgreen", "attrs": ["bold"] },
"attached_clients": { "fg": "white", "bg": "darkestgreen", "attrs": [] }
},
"mode_translations": {
"vicmd": {
"groups": {
"mode": {"fg": "darkestcyan", "bg": "white", "attrs": ["bold"]}
}
}
}
}
@@ -0,0 +1,16 @@
{
"name": "Default color scheme for shell prompts",
"groups": {
"hostname": { "fg": "gb:bright_yellow", "bg": "gb:neutral_orange", "attrs": [] },
"environment": { "fg": "gb:light0", "bg": "gb:neutral_green", "attrs": [] },
"mode": { "fg": "gb:dark2", "bg": "gb:bright_green", "attrs": ["bold"] },
"attached_clients": { "fg": "gb:light0", "bg": "gb:neutral_green", "attrs": [] }
},
"mode_translations": {
"vicmd": {
"groups": {
"mode": {"fg": "darkestcyan", "bg": "white", "attrs": ["bold"]}
}
}
}
}
@@ -0,0 +1,13 @@
{
"name": "Solarized dark for shell",
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": ["bold"] }
},
"mode_translations": {
"vicmd": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
}
}
}
}
@@ -0,0 +1,40 @@
{
"name": "Solarized dark",
"groups": {
"information:additional": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
"information:regular": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] },
"information:highlighted": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"]},
"information:priority": { "fg": "solarized:base3", "bg": "solarized:yellow", "attrs": [] },
"warning:regular": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": [] },
"critical:failure": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": [] },
"critical:success": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"background": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": [] },
"background:divider": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] },
"user": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] },
"virtualenv": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"branch": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"branch_dirty": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": [] },
"branch_clean": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"stash": "branch_dirty",
"email_alert_gradient": { "fg": "solarized:base3", "bg": "yellow_orange_red", "attrs": [] },
"email_alert": "warning:regular",
"cwd": "information:additional",
"cwd:current_folder": "information:regular",
"cwd:divider": { "fg": "solarized:base1", "bg": "solarized:base01", "attrs": [] },
"network_load": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] },
"network_load:divider": "network_load",
"network_load_gradient": { "fg": "green_yellow_orange_red", "bg": "solarized:base03", "attrs": [] },
"network_load_sent_gradient": "network_load_gradient",
"network_load_recv_gradient": "network_load_gradient",
"hostname": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"environment": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"attached_clients": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"date": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"time": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": ["bold"] },
"time:divider": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"system_load": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] },
"weather_temp_gradient": { "fg": "blue_red", "bg": "solarized:base03", "attrs": [] },
"weather": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] },
"uptime": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] }
}
}
@@ -0,0 +1,14 @@
{
"groups": {
"active_window_status": {"fg": "darkblue", "bg": "gray0", "attrs": []},
"window_status": {"fg": "gray70", "bg": "gray0", "attrs": []},
"activity_status": {"fg": "yellow", "bg": "gray0", "attrs": []},
"bell_status": {"fg": "red", "bg": "gray0", "attrs": []},
"window": {"fg": "gray6", "bg": "gray0", "attrs": []},
"window:divider": {"fg": "gray4", "bg": "gray0", "attrs": []},
"window:current": {"fg": "mediumcyan", "bg": "darkblue", "attrs": []},
"window_name": {"fg": "white", "bg": "darkblue", "attrs": ["bold"]},
"session": {"fg": "black", "bg": "gray90", "attrs": ["bold"]},
"session:prefix": {"fg": "gray90", "bg": "darkblue", "attrs": ["bold"]}
}
}
@@ -0,0 +1,14 @@
{
"groups": {
"active_window_status": {"fg": "gb:faded_aqua", "bg": "gb:dark1", "attrs": []},
"window_status": {"fg": "gb:light4", "bg": "gb:dark1", "attrs": []},
"activity_status": {"fg": "gb:neutral_yellow", "bg": "gb:dark1", "attrs": []},
"bell_status": {"fg": "gb:neutral_red", "bg": "gb:dark1", "attrs": []},
"window": {"fg": "gb:light3", "bg": "gb:dark1", "attrs": []},
"window:divider": {"fg": "gb:light2", "bg": "gb:dark1", "attrs": []},
"window:current": {"fg": "gb:light1", "bg": "gb:faded_aqua", "attrs": []},
"window_name": {"fg": "gb:light0", "bg": "gb:faded_aqua", "attrs": ["bold"]},
"session": {"fg": "gb:dark0", "bg": "gb:light4", "attrs": ["bold"]},
"session:prefix": {"fg": "gb:light4", "bg": "gb:neutral_blue", "attrs": ["bold"]}
}
}
@@ -0,0 +1,14 @@
{
"groups": {
"active_window_status": { "fg": "solarized:blue", "bg": "solarized:base02", "attrs": [] },
"window_status": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"activity_status": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": [] },
"bell_status": { "fg": "solarized:red", "bg": "solarized:base02", "attrs": [] },
"window": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"window:divider": { "fg": "solarized:base01", "bg": "solarized:base02", "attrs": [] },
"window:current": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"window_name": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] },
"session": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"session:prefix": { "fg": "solarized:base01", "bg": "solarized:base3", "attrs": [] }
}
}
@@ -0,0 +1,51 @@
{
"groups": {
"branch_clean": "branch",
"environment": "information:unimportant",
"file_size": "information:unimportant",
"file_format": "information:unimportant",
"file_encoding": "file_format",
"file_bom": "file_format",
"file_type": "file_format",
"branch": "information:additional",
"file_scheme": "file_name",
"file_directory": "information:additional",
"file_name_empty": "file_directory",
"line_percent": "information:additional",
"line_count": "line_current",
"position": "information:additional",
"single_tab": "line_current",
"many_tabs": "line_current",
"bufnr": "file_directory",
"winnr": "information:unimportant",
"tabnr": "file_directory",
"capslock_indicator": "paste_indicator",
"csv:column_number": "line_current",
"csv:column_name": "line_current_symbol",
"tab:background": "background",
"tab:divider": "background:divider",
"tab_nc:modified_indicator": "modified_indicator",
"tab_nc:file_directory": "information:unimportant",
"tab_nc:file_name": "tab_nc:file_directory",
"tab_nc:tabnr": "tab_nc:file_directory",
"buf_nc:file_directory": "tab_nc:file_directory",
"buf_nc:file_name": "buf_nc:file_directory",
"buf_nc:bufnr": "buf_nc:file_directory",
"buf_nc:modified_indicator": "tab_nc:modified_indicator",
"buf_nc_mod:file_directory": "tab_nc:file_directory",
"buf_nc_mod:file_name": "buf_nc_mod:file_directory",
"buf_nc_mod:bufnr": "buf_nc_mod:file_directory",
"buf_nc_mod:modified_indicator": "tab_nc:modified_indicator",
"commandt:label": "file_name",
"commandt:background": "background",
"commandt:finder": "file_name",
"commandt:path": "file_directory"
}
}
@@ -0,0 +1,154 @@
{
"name": "Default color scheme",
"groups": {
"information:unimportant": { "fg": "gray8", "bg": "gray2", "attrs": [] },
"information:additional": { "fg": "gray9", "bg": "gray4", "attrs": [] },
"background": { "fg": "white", "bg": "gray2", "attrs": [] },
"background:divider": { "fg": "gray6", "bg": "gray2", "attrs": [] },
"mode": { "fg": "darkestgreen", "bg": "brightgreen", "attrs": ["bold"] },
"visual_range": { "fg": "brightestorange", "bg": "darkorange", "attrs": ["bold"] },
"modified_indicator": { "fg": "brightyellow", "bg": "gray4", "attrs": ["bold"] },
"paste_indicator": { "fg": "white", "bg": "mediumorange", "attrs": ["bold"] },
"readonly_indicator": { "fg": "brightestred", "bg": "gray4", "attrs": [] },
"branch_dirty": { "fg": "brightyellow", "bg": "gray4", "attrs": [] },
"branch:divider": { "fg": "gray7", "bg": "gray4", "attrs": [] },
"file_name": { "fg": "white", "bg": "gray4", "attrs": ["bold"] },
"window_title": { "fg": "white", "bg": "gray4", "attrs": [] },
"file_name_no_file": { "fg": "gray9", "bg": "gray4", "attrs": ["bold"] },
"file_vcs_status": { "fg": "brightestred", "bg": "gray4", "attrs": [] },
"file_vcs_status_M": { "fg": "brightyellow", "bg": "gray4", "attrs": [] },
"file_vcs_status_A": { "fg": "brightgreen", "bg": "gray4", "attrs": [] },
"line_percent": { "fg": "gray9", "bg": "gray4", "attrs": [] },
"line_percent_gradient": { "fg": "dark_green_gray", "bg": "gray4", "attrs": [] },
"position": { "fg": "gray9", "bg": "gray4", "attrs": [] },
"position_gradient": { "fg": "green_yellow_red", "bg": "gray4", "attrs": [] },
"line_current": { "fg": "gray1", "bg": "gray10", "attrs": ["bold"] },
"line_current_symbol": { "fg": "gray1", "bg": "gray10", "attrs": [] },
"virtcol_current_gradient": { "fg": "dark_GREEN_Orange_red", "bg": "gray10", "attrs": [] },
"col_current": { "fg": "gray6", "bg": "gray10", "attrs": [] },
"modified_buffers": { "fg": "brightyellow", "bg": "gray2", "attrs": [] },
"attached_clients": { "fg": "gray8", "bg": "gray2", "attrs": [] },
"error": { "fg": "brightestred", "bg": "darkred", "attrs": ["bold"] },
"warning": { "fg": "brightyellow", "bg": "darkorange", "attrs": ["bold"] },
"current_tag": { "fg": "gray9", "bg": "gray2", "attrs": [] },
"tab_nc:modified_indicator": { "fg": "brightyellow", "bg": "gray2", "attrs": ["bold"] }
},
"mode_translations": {
"nc": {
"colors": {
"brightyellow": "darkorange",
"brightestred": "darkred",
"gray0": "gray0",
"gray1": "gray0",
"gray2": "gray0",
"gray3": "gray1",
"gray4": "gray1",
"gray5": "gray1",
"gray6": "gray1",
"gray7": "gray4",
"gray8": "gray4",
"gray9": "gray4",
"gray10": "gray5",
"white": "gray6",
"dark_green_gray": "gray5"
}
},
"i": {
"colors": {
"gray0": "darkestblue",
"gray1": "darkestblue",
"gray2": "darkestblue",
"gray3": "darkblue",
"gray4": "darkblue",
"gray5": "darkestcyan",
"gray6": "darkestcyan",
"gray7": "darkestcyan",
"gray8": "mediumcyan",
"gray9": "mediumcyan",
"gray10": "mediumcyan",
"green_yellow_red": "gray5",
"dark_green_gray": "light_green_gray"
},
"groups": {
"mode": { "fg": "darkestcyan", "bg": "white", "attrs": ["bold"] },
"background:divider": { "fg": "darkcyan", "bg": "darkestblue", "attrs": [] },
"branch:divider": { "fg": "darkcyan", "bg": "darkblue", "attrs": [] }
}
},
"ic": {
"colors": {
"gray0": "darkestblue",
"gray1": "darkestblue",
"gray2": "darkestblue",
"gray3": "darkblue",
"gray4": "darkblue",
"gray5": "darkestcyan",
"gray6": "darkestcyan",
"gray7": "darkestcyan",
"gray8": "mediumcyan",
"gray9": "mediumcyan",
"gray10": "mediumcyan",
"green_yellow_red": "gray5",
"dark_green_gray": "light_green_gray"
},
"groups": {
"mode": { "fg": "darkestcyan", "bg": "white", "attrs": ["bold"] },
"background:divider": { "fg": "darkcyan", "bg": "darkestblue", "attrs": [] },
"branch:divider": { "fg": "darkcyan", "bg": "darkblue", "attrs": [] }
}
},
"ix": {
"colors": {
"gray0": "darkestblue",
"gray1": "darkestblue",
"gray2": "darkestblue",
"gray3": "darkblue",
"gray4": "darkblue",
"gray5": "darkestcyan",
"gray6": "darkestcyan",
"gray7": "darkestcyan",
"gray8": "mediumcyan",
"gray9": "mediumcyan",
"gray10": "mediumcyan",
"green_yellow_red": "gray5",
"dark_green_gray": "light_green_gray"
},
"groups": {
"mode": { "fg": "darkestcyan", "bg": "white", "attrs": ["bold"] },
"background:divider": { "fg": "darkcyan", "bg": "darkestblue", "attrs": [] },
"branch:divider": { "fg": "darkcyan", "bg": "darkblue", "attrs": [] }
}
},
"v": {
"groups": {
"mode": { "fg": "darkorange", "bg": "brightestorange", "attrs": ["bold"] }
}
},
"V": {
"groups": {
"mode": { "fg": "darkorange", "bg": "brightestorange", "attrs": ["bold"] }
}
},
"^V": {
"groups": {
"mode": { "fg": "darkorange", "bg": "brightestorange", "attrs": ["bold"] }
}
},
"R": {
"groups": {
"mode": { "fg": "white", "bg": "brightred", "attrs": ["bold"] }
}
},
"Rc": {
"groups": {
"mode": { "fg": "white", "bg": "brightred", "attrs": ["bold"] }
}
},
"Rx": {
"groups": {
"mode": { "fg": "white", "bg": "brightred", "attrs": ["bold"] }
}
}
}
}
@@ -0,0 +1,121 @@
{
"name": "Solarized dark for vim",
"groups": {
"information:additional": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
"information:unimportant": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"background": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": [] },
"background:divider": { "fg": "solarized:base00", "bg": "solarized:base02", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": ["bold"] },
"visual_range": { "fg": "solarized:green", "bg": "solarized:base3", "attrs": ["bold"] },
"modified_indicator": { "fg": "solarized:yellow", "bg": "solarized:base01", "attrs": ["bold"] },
"paste_indicator": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] },
"readonly_indicator": { "fg": "solarized:red", "bg": "solarized:base01", "attrs": [] },
"branch_dirty": { "fg": "solarized:yellow", "bg": "solarized:base01", "attrs": [] },
"branch:divider": { "fg": "solarized:base1", "bg": "solarized:base01", "attrs": [] },
"stash:divider": "branch:divider",
"file_name": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] },
"window_title": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"file_name_no_file": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] },
"file_format": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"file_vcs_status": { "fg": "solarized:red", "bg": "solarized:base01", "attrs": [] },
"file_vcs_status_M": { "fg": "solarized:yellow", "bg": "solarized:base01", "attrs": [] },
"file_vcs_status_A": { "fg": "solarized:green", "bg": "solarized:base01", "attrs": [] },
"line_percent": { "fg": "solarized:base3", "bg": "solarized:base00", "attrs": [] },
"line_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "solarized:base00", "attrs": [] },
"position": { "fg": "solarized:base3", "bg": "solarized:base00", "attrs": [] },
"position_gradient": { "fg": "green_yellow_orange_red", "bg": "solarized:base00", "attrs": [] },
"line_current": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] },
"line_current_symbol": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"virtcol_current_gradient": { "fg": "GREEN_Orange_red", "bg": "solarized:base2", "attrs": [] },
"col_current": { "fg": "solarized:base0", "bg": "solarized:base2", "attrs": [] },
"environment": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"attached_clients": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"error": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] },
"warning": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] },
"current_tag": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": ["bold"] }
},
"mode_translations": {
"nc": {
"colors": {
"solarized:base01": "solarized:base02",
"solarized:base00": "solarized:base02",
"solarized:base0": "solarized:base01",
"solarized:base1": "solarized:base00",
"solarized:base2": "solarized:base0",
"solarized:base3": "solarized:base1"
}
},
"i": {
"groups": {
"background": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"background:divider": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] },
"modified_indicator": { "fg": "solarized:yellow", "bg": "solarized:base2", "attrs": ["bold"] },
"paste_indicator": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] },
"readonly_indicator": { "fg": "solarized:red", "bg": "solarized:base2", "attrs": [] },
"branch": { "fg": "solarized:base01", "bg": "solarized:base2", "attrs": [] },
"branch:divider": { "fg": "solarized:base00", "bg": "solarized:base2", "attrs": [] },
"file_directory": { "fg": "solarized:base01", "bg": "solarized:base2", "attrs": [] },
"file_name": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": ["bold"] },
"file_size": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
"file_name_no_file": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": ["bold"] },
"file_name_empty": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
"file_format": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
"file_vcs_status": { "fg": "solarized:red", "bg": "solarized:base2", "attrs": [] },
"file_vcs_status_M": { "fg": "solarized:yellow", "bg": "solarized:base2", "attrs": [] },
"file_vcs_status_A": { "fg": "solarized:green", "bg": "solarized:base2", "attrs": [] },
"line_percent": { "fg": "solarized:base3", "bg": "solarized:base1", "attrs": [] },
"line_percent_gradient": { "fg": "solarized:base3", "bg": "solarized:base1", "attrs": [] },
"position": { "fg": "solarized:base3", "bg": "solarized:base1", "attrs": [] },
"position_gradient": { "fg": "solarized:base3", "bg": "solarized:base1", "attrs": [] },
"line_current": { "fg": "solarized:base03", "bg": "solarized:base3", "attrs": ["bold"] },
"line_current_symbol": { "fg": "solarized:base03", "bg": "solarized:base3", "attrs": [] },
"col_current": { "fg": "solarized:base0", "bg": "solarized:base3", "attrs": [] }
}
},
"ic": {
"groups": {
"background": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"background:divider": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
}
},
"ix": {
"groups": {
"background": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"background:divider": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
}
},
"v": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
}
},
"V": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
}
},
"^V": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
}
},
"R": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
},
"Rc": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
},
"Rx": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
}
}
}
@@ -0,0 +1,122 @@
{
"name": "Solarized light for vim",
"groups": {
"information:additional": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
"information:unimportant": { "fg": "solarized:base1", "bg": "solarized:base01", "attrs": [] },
"background": { "fg": "solarized:base03", "bg": "solarized:base01", "attrs": [] },
"background:divider": { "fg": "solarized:base0", "bg": "solarized:base01", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": ["bold"] },
"visual_range": { "fg": "solarized:green", "bg": "solarized:base3", "attrs": ["bold"] },
"modified_indicator": { "fg": "solarized:yellow", "bg": "solarized:base2", "attrs": ["bold"] },
"paste_indicator": { "fg": "solarized:red", "bg": "solarized:base2", "attrs": ["bold"] },
"readonly_indicator": { "fg": "solarized:red", "bg": "solarized:base2", "attrs": [] },
"branch_dirty": { "fg": "solarized:yellow", "bg": "solarized:base2", "attrs": [] },
"branch:divider": { "fg": "solarized:base1", "bg": "solarized:base2", "attrs": [] },
"stash": "branch_dirty",
"stash:divider": "branch:divider",
"file_name": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] },
"window_title": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"file_size": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"file_name_no_file": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] },
"file_name_empty": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"file_vcs_status": { "fg": "solarized:red", "bg": "solarized:base2", "attrs": [] },
"file_vcs_status_M": { "fg": "solarized:yellow", "bg": "solarized:base2", "attrs": [] },
"file_vcs_status_A": { "fg": "solarized:green", "bg": "solarized:base2", "attrs": [] },
"line_percent": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"line_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "solarized:base2", "attrs": [] },
"position": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"position_gradient": { "fg": "green_yellow_orange_red", "bg": "solarized:base2", "attrs": [] },
"line_current": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": ["bold"] },
"line_current_symbol": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": [] },
"virtcol_current_gradient": { "fg": "yellow_orange_red", "bg": "solarized:base02", "attrs": [] },
"col_current": { "fg": "solarized:base00", "bg": "solarized:base02", "attrs": [] },
"error": { "fg": "solarized:base03", "bg": "solarized:red", "attrs": ["bold"] },
"warning": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] },
"current_tag": { "fg": "solarized:base03", "bg": "solarized:base01", "attrs": ["bold"] }
},
"mode_translations": {
"nc": {
"colors": {
"solarized:base2": "solarized:base01",
"solarized:base0": "solarized:base01",
"solarized:base00": "solarized:base2",
"solarized:base1": "solarized:base0",
"solarized:base02": "solarized:base00",
"solarized:base03": "solarized:base1"
}
},
"i": {
"groups": {
"background": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"background:divider": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] },
"modified_indicator": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": ["bold"] },
"paste_indicator": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] },
"readonly_indicator": { "fg": "solarized:red", "bg": "solarized:base02", "attrs": [] },
"branch": { "fg": "solarized:base2", "bg": "solarized:base02", "attrs": [] },
"branch:divider": { "fg": "solarized:base0", "bg": "solarized:base02", "attrs": [] },
"file_directory": { "fg": "solarized:base2", "bg": "solarized:base02", "attrs": [] },
"file_name": { "fg": "solarized:base01", "bg": "solarized:base02", "attrs": ["bold"] },
"file_size": { "fg": "solarized:base01", "bg": "solarized:base02", "attrs": [] },
"file_name_no_file": { "fg": "solarized:base01", "bg": "solarized:base02", "attrs": ["bold"] },
"file_name_empty": { "fg": "solarized:base01", "bg": "solarized:base02", "attrs": [] },
"file_format": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
"file_vcs_status": { "fg": "solarized:red", "bg": "solarized:base02", "attrs": [] },
"file_vcs_status_M": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": [] },
"file_vcs_status_A": { "fg": "solarized:green", "bg": "solarized:base02", "attrs": [] },
"line_percent": { "fg": "solarized:base03", "bg": "solarized:base1", "attrs": [] },
"line_percent_gradient": { "fg": "solarized:base03", "bg": "solarized:base1", "attrs": [] },
"position": { "fg": "solarized:base03", "bg": "solarized:base1", "attrs": [] },
"position_gradient": { "fg": "solarized:base03", "bg": "solarized:base1", "attrs": [] },
"line_current": { "fg": "solarized:base3", "bg": "solarized:base03", "attrs": ["bold"] },
"line_current_symbol": { "fg": "solarized:base3", "bg": "solarized:base03", "attrs": [] },
"virtcol_current_gradient": { "fg": "yellow_orange_red", "bg": "solarized:base03", "attrs": [] },
"col_current": { "fg": "solarized:base00", "bg": "solarized:base03", "attrs": [] }
}
},
"ic": {
"groups": {
"background": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"background:divider": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
}
},
"ix": {
"groups": {
"background": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"background:divider": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
}
},
"v": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
}
},
"V": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
}
},
"^V": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
}
},
"R": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
},
"Rc": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
},
"Rx": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
}
}
}
+53
View File
@@ -0,0 +1,53 @@
{
"common": {
"term_truecolor": true
},
"ext": {
"ipython": {
"colorscheme": "default",
"theme": "in",
"local_themes": {
"rewrite": "rewrite",
"out": "out",
"in2": "in2"
}
},
"pdb": {
"colorscheme": "gruvbox",
"theme": "default"
},
"shell": {
"colorscheme": "gruvbox",
"theme": "default",
"local_themes": {
"continuation": "continuation",
"select": "select"
}
},
"tmux": {
"colorscheme": "gruvbox",
"theme": "default"
},
"vim": {
"colorscheme": "default",
"theme": "default",
"local_themes": {
"__tabline__": "tabline",
"cmdwin": "cmdwin",
"help": "help",
"quickfix": "quickfix",
"powerline.matchers.vim.plugin.nerdtree.nerdtree": "plugin_nerdtree",
"powerline.matchers.vim.plugin.commandt.commandt": "plugin_commandt",
"powerline.matchers.vim.plugin.gundo.gundo": "plugin_gundo",
"powerline.matchers.vim.plugin.gundo.gundo_preview": "plugin_gundo-preview"
}
},
"wm": {
"colorscheme": "default",
"theme": "default",
"update_interval": 2
}
}
}
+153
View File
@@ -0,0 +1,153 @@
{
"use_non_breaking_spaces": false,
"dividers": {
"left": {
"hard": " ",
"soft": "| "
},
"right": {
"hard": " ",
"soft": " |"
}
},
"spaces": 1,
"segment_data": {
"branch": {
"before": "BR "
},
"stash": {
"before": "ST "
},
"cwd": {
"args": {
"ellipsis": "..."
}
},
"player": {
"args": {
"state_symbols": {
"fallback": "",
"play": ">",
"pause": "~",
"stop": "X"
}
}
},
"line_current_symbol": {
"contents": "LN "
},
"time": {
"before": ""
},
"powerline.segments.common.net.network_load": {
"args": {
"recv_format": "DL {value:>8}",
"sent_format": "UL {value:>8}"
}
},
"powerline.segments.common.net.hostname": {
"before": "H "
},
"powerline.segments.common.bat.battery": {
"args": {
"full_heart": "O",
"empty_heart": "O",
"online": "C",
"offline": " "
}
},
"powerline.segments.common.sys.uptime": {
"before": "UP "
},
"powerline.segments.common.mail.email_imap_alert": {
"before": "MAIL "
},
"powerline.segments.common.env.virtualenv": {
"before": "(e) "
},
"powerline.segments.common.wthr.weather": {
"args": {
"icons": {
"day": "DAY",
"blustery": "WIND",
"rainy": "RAIN",
"cloudy": "CLOUDS",
"snowy": "SNOW",
"stormy": "STORM",
"foggy": "FOG",
"sunny": "SUN",
"night": "NIGHT",
"windy": "WINDY",
"not_available": "NA",
"unknown": "UKN"
},
"temp_format": "{temp:.0f} C"
}
},
"powerline.segments.common.time.fuzzy_time": {
"args": {
"unicode_text": false
}
},
"powerline.segments.vim.mode": {
"args": {
"override": {
"n": "NORMAL",
"no": "N-OPER",
"v": "VISUAL",
"V": "V-LINE",
"^V": "V-BLCK",
"s": "SELECT",
"S": "S-LINE",
"^S": "S-BLCK",
"i": "INSERT",
"ic": "I-COMP",
"ix": "I-C_X ",
"R": "RPLACE",
"Rv": "V-RPLC",
"Rc": "R-COMP",
"Rx": "R-C_X ",
"c": "COMMND",
"cv": "VIM-EX",
"ce": "NRM-EX",
"r": "PROMPT",
"rm": "-MORE-",
"r?": "CNFIRM",
"!": "!SHELL",
"t": "TERM "
}
}
},
"powerline.segments.vim.visual_range": {
"args": {
"CTRL_V_text": "{rows} x {vcols}",
"v_text_oneline": "C:{vcols}",
"v_text_multiline": "L:{rows}",
"V_text": "L:{rows}"
}
},
"powerline.segments.vim.readonly_indicator": {
"args": {
"text": "RO"
}
},
"powerline.segments.vim.modified_indicator": {
"args": {
"text": "+"
}
},
"powerline.segments.i3wm.scratchpad": {
"args": {
"icons": {
"fresh": "O",
"changed": "X"
}
}
}
}
}
+25
View File
@@ -0,0 +1,25 @@
{
"segments": {
"left": [
{
"function": "powerline.segments.common.env.virtualenv",
"priority": 10
},
{
"type": "string",
"contents": "In [",
"draw_soft_divider": false,
"highlight_groups": ["prompt"]
},
{
"function": "powerline.segments.ipython.prompt_count",
"draw_soft_divider": false
},
{
"type": "string",
"contents": "]",
"highlight_groups": ["prompt"]
}
]
}
}
+12
View File
@@ -0,0 +1,12 @@
{
"segments": {
"left": [
{
"type": "string",
"contents": "",
"width": "auto",
"highlight_groups": ["prompt"]
}
]
}
}
+24
View File
@@ -0,0 +1,24 @@
{
"default_module": "powerline.segments.ipython",
"segments": {
"left": [
{
"type": "string",
"contents": "Out[",
"draw_soft_divider": false,
"width": "auto",
"align": "r",
"highlight_groups": ["prompt"]
},
{
"function": "prompt_count",
"draw_soft_divider": false
},
{
"type": "string",
"contents": "]",
"highlight_groups": ["prompt"]
}
]
}
}
@@ -0,0 +1,23 @@
{
"default_module": "powerline.segments.ipython",
"segments": {
"left": [
{
"type": "string",
"contents": "",
"draw_soft_divider": false,
"width": "auto",
"highlight_groups": ["prompt"]
},
{
"function": "prompt_count",
"draw_soft_divider": false
},
{
"type": "string",
"contents": ">",
"highlight_groups": ["prompt"]
}
]
}
}
+27
View File
@@ -0,0 +1,27 @@
{
"default_module": "powerline.segments.pdb",
"segments": {
"left": [
{
"function": "stack_depth"
},
{
"type": "segment_list",
"function": "powerline.listers.pdb.frame_lister",
"segments": [
{
"function": "current_file",
"after": ":"
},
{
"function": "current_line",
"after": " "
},
{
"function": "current_code_name"
}
]
}
]
}
}
+151
View File
@@ -0,0 +1,151 @@
{
"dividers": {
"left": {
"hard": " ",
"soft": " "
},
"right": {
"hard": " ",
"soft": " "
}
},
"spaces": 1,
"segment_data": {
"branch": {
"before": " "
},
"stash": {
"before": "⌆ "
},
"cwd": {
"args": {
"ellipsis": "⋯"
}
},
"line_current_symbol": {
"contents": " "
},
"player": {
"args": {
"state_symbols": {
"fallback": "♫",
"play": "▶",
"pause": "▮▮",
"stop": "■"
}
}
},
"time": {
"before": "⌚ "
},
"powerline.segments.common.net.network_load": {
"args": {
"recv_format": "⬇ {value:>8}",
"sent_format": "⬆ {value:>8}"
}
},
"powerline.segments.common.net.hostname": {
"before": " "
},
"powerline.segments.common.bat.battery": {
"args": {
"full_heart": "♥",
"empty_heart": "♥",
"online": "⚡︎",
"offline": " "
}
},
"powerline.segments.common.sys.uptime": {
"before": "⇑ "
},
"powerline.segments.common.mail.email_imap_alert": {
"before": "✉ "
},
"powerline.segments.common.env.virtualenv": {
"before": "ⓔ "
},
"powerline.segments.common.wthr.weather": {
"args": {
"icons": {
"day": "〇",
"blustery": "⚑",
"rainy": "☔",
"cloudy": "☁",
"snowy": "❅",
"stormy": "☈",
"foggy": "≡",
"sunny": "☼",
"night": "☾",
"windy": "☴",
"not_available": "�",
"unknown": "⚠"
}
}
},
"powerline.segments.common.time.fuzzy_time": {
"args": {
"unicode_text": true
}
},
"powerline.segments.vim.mode": {
"args": {
"override": {
"n": "NORMAL",
"no": "N·OPER",
"v": "VISUAL",
"V": "V·LINE",
"^V": "V·BLCK",
"s": "SELECT",
"S": "S·LINE",
"^S": "S·BLCK",
"i": "INSERT",
"ic": "I·COMP",
"ix": "I·C-X ",
"R": "RPLACE",
"Rv": "V·RPLC",
"Rc": "R·COMP",
"Rx": "R·C-X ",
"c": "COMMND",
"cv": "VIM·EX",
"ce": "NRM·EX",
"r": "PROMPT",
"rm": "-MORE-",
"r?": "CNFIRM",
"!": "!SHELL",
"t": "TERM "
}
}
},
"powerline.segments.vim.visual_range": {
"args": {
"CTRL_V_text": "↕{rows} ↔{vcols}",
"v_text_oneline": "↔{vcols}",
"v_text_multiline": "↕{rows}",
"V_text": "⇕{rows}"
}
},
"powerline.segments.vim.readonly_indicator": {
"args": {
"text": ""
}
},
"powerline.segments.vim.modified_indicator": {
"args": {
"text": "+"
}
},
"powerline.segments.i3wm.scratchpad": {
"args": {
"icons": {
"fresh": "●",
"changed": "○"
}
}
}
}
}
@@ -0,0 +1,151 @@
{
"dividers": {
"left": {
"hard": " ",
"soft": " "
},
"right": {
"hard": " ",
"soft": " "
}
},
"spaces": 1,
"segment_data": {
"branch": {
"before": " "
},
"stash": {
"before": "ST "
},
"cwd": {
"args": {
"ellipsis": "…"
}
},
"line_current_symbol": {
"contents": " "
},
"player": {
"args": {
"state_symbols": {
"fallback": "♫",
"play": "▶",
"pause": "▮▮",
"stop": "■"
}
}
},
"time": {
"before": ""
},
"powerline.segments.common.net.network_load": {
"args": {
"recv_format": "⇓ {value:>8}",
"sent_format": "⇑ {value:>8}"
}
},
"powerline.segments.common.net.hostname": {
"before": " "
},
"powerline.segments.common.bat.battery": {
"args": {
"full_heart": "♥",
"empty_heart": "♥",
"online": "⚡︎",
"offline": " "
}
},
"powerline.segments.common.sys.uptime": {
"before": "↑ "
},
"powerline.segments.common.mail.email_imap_alert": {
"before": "MAIL "
},
"powerline.segments.common.env.virtualenv": {
"before": "(e) "
},
"powerline.segments.common.wthr.weather": {
"args": {
"icons": {
"day": "DAY",
"blustery": "WIND",
"rainy": "RAIN",
"cloudy": "CLOUDS",
"snowy": "SNOW",
"stormy": "STORM",
"foggy": "FOG",
"sunny": "SUN",
"night": "NIGHT",
"windy": "WINDY",
"not_available": "NA",
"unknown": "UKN"
}
}
},
"powerline.segments.common.time.fuzzy_time": {
"args": {
"unicode_text": true
}
},
"powerline.segments.vim.mode": {
"args": {
"override": {
"n": "NORMAL",
"no": "N·OPER",
"v": "VISUAL",
"V": "V·LINE",
"^V": "V·BLCK",
"s": "SELECT",
"S": "S·LINE",
"^S": "S·BLCK",
"i": "INSERT",
"ic": "I·COMP",
"ix": "I·C-X ",
"R": "RPLACE",
"Rv": "V·RPLC",
"Rc": "R·COMP",
"Rx": "R·C-X ",
"c": "COMMND",
"cv": "VIM·EX",
"ce": "NRM·EX",
"r": "PROMPT",
"rm": "-MORE-",
"r?": "CNFIRM",
"!": "!SHELL",
"t": "TERM "
}
}
},
"powerline.segments.vim.visual_range": {
"args": {
"CTRL_V_text": "↕{rows} ↔{vcols}",
"v_text_oneline": "↔{vcols}",
"v_text_multiline": "↕{rows}",
"V_text": "⇕{rows}"
}
},
"powerline.segments.vim.readonly_indicator": {
"args": {
"text": ""
}
},
"powerline.segments.vim.modified_indicator": {
"args": {
"text": "+"
}
},
"powerline.segments.i3wm.scratchpad": {
"args": {
"icons": {
"fresh": "●",
"changed": "○"
}
}
}
}
}
@@ -0,0 +1,165 @@
{
"dividers": {
"left": {
"hard": " ",
"soft": " "
},
"right": {
"hard": " ",
"soft": " "
}
},
"spaces": 1,
"segment_data": {
"branch": {
"before": "🔀 "
},
"stash": {
"before": "📝"
},
"cwd": {
"args": {
"ellipsis": "⋯"
}
},
"line_current_symbol": {
"contents": " "
},
"player": {
"args": {
"state_symbols": {
"fallback": "♫",
"play": "⏵",
"pause": "⏸",
"stop": "⏹"
}
}
},
"time": {
"before": "🕐 "
},
"powerline.segments.common.net.network_load": {
"args": {
"recv_format": "⬇ {value:>8}",
"sent_format": "⬆ {value:>8}"
}
},
"powerline.segments.common.net.hostname": {
"before": "🏠 "
},
"powerline.segments.common.bat.battery": {
"args": {
"full_heart": "💙",
"empty_heart": "💛",
"online": "⚡️",
"offline": " "
}
},
"powerline.segments.common.sys.uptime": {
"before": "⇑ "
},
"powerline.segments.common.mail.email_imap_alert": {
"before": "✉ "
},
"powerline.segments.common.env.virtualenv": {
"before": "🐍 "
},
"powerline.segments.common.wthr.weather": {
"args": {
"icons": {
"tornado": "🌪",
"hurricane": "🌀",
"showers": "☔",
"scattered_showers": "☔",
"thunderstorms": "🌩",
"isolated_thunderstorms": "🌩",
"scattered_thunderstorms": "🌩",
"dust": "🌫",
"fog": "🌫",
"cold": "❄",
"partly_cloudy_day": "🌤",
"mostly_cloudy_day": "🌥",
"sun": "🌣",
"hot": "♨",
"day": "☀",
"blustery": "⚑",
"rainy": "☂",
"cloudy": "☁",
"snowy": "☃",
"stormy": "☈",
"foggy": "🌁",
"sunny": "🌣",
"night": "☾",
"windy": "☴",
"not_available": "�",
"unknown": "⚠"
}
}
},
"powerline.segments.common.time.fuzzy_time": {
"args": {
"unicode_text": true
}
},
"powerline.segments.vim.mode": {
"args": {
"override": {
"n": "NORMAL",
"no": "N·OPER",
"v": "VISUAL",
"V": "V·LINE",
"^V": "V·BLCK",
"s": "SELECT",
"S": "S·LINE",
"^S": "S·BLCK",
"i": "INSERT",
"ic": "I·COMP",
"ix": "I·C-X ",
"R": "RPLACE",
"Rv": "V·RPLC",
"Rc": "R·COMP",
"Rx": "R·C-X ",
"c": "COMMND",
"cv": "VIM·EX",
"ce": "NRM·EX",
"r": "PROMPT",
"rm": "-MORE-",
"r?": "CNFIRM",
"!": "!SHELL",
"t": "TERM "
}
}
},
"powerline.segments.vim.visual_range": {
"args": {
"CTRL_V_text": "↕{rows} ↔{vcols}",
"v_text_oneline": "↔{vcols}",
"v_text_multiline": "↕{rows}",
"V_text": "⇕{rows}"
}
},
"powerline.segments.vim.readonly_indicator": {
"args": {
"text": "🔏"
}
},
"powerline.segments.vim.modified_indicator": {
"args": {
"text": "🖫⃥"
}
},
"powerline.segments.i3wm.scratchpad": {
"args": {
"icons": {
"fresh": "●",
"changed": "○"
}
}
}
}
}
@@ -0,0 +1,14 @@
{
"segment_data": {
"hostname": {
"args": {
"only_if_ssh": true
}
},
"cwd": {
"args": {
"dir_limit_depth": 3
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More