From 8827a5923a925a0598f484c04c94644774a76698 Mon Sep 17 00:00:00 2001 From: Brent Schroeter Date: Tue, 17 Mar 2026 11:47:59 -0700 Subject: [PATCH] initial commit --- Containerfile | 82 ++++++++++++ Makefile | 15 +++ README.md | 21 +++ assets/git/gitconfig | 16 +++ assets/helix/config.toml | 48 +++++++ assets/helix/ignore | 1 + assets/helix/languages.toml | 102 +++++++++++++++ assets/helix/snippets/rust.toml | 171 +++++++++++++++++++++++++ assets/helix/themes/dracula_16.toml | 77 +++++++++++ assets/helix/themes/dracula_helix.toml | 77 +++++++++++ assets/helix/themes/yo_dracula.toml | 159 +++++++++++++++++++++++ assets/jj/config.toml | 15 +++ assets/mise/config.toml | 13 ++ build-image.fish | 49 +++++++ devbox.fish | 34 +++++ 15 files changed, 880 insertions(+) create mode 100644 Containerfile create mode 100644 Makefile create mode 100644 README.md create mode 100644 assets/git/gitconfig create mode 100644 assets/helix/config.toml create mode 100644 assets/helix/ignore create mode 100644 assets/helix/languages.toml create mode 100644 assets/helix/snippets/rust.toml create mode 100644 assets/helix/themes/dracula_16.toml create mode 100644 assets/helix/themes/dracula_helix.toml create mode 100644 assets/helix/themes/yo_dracula.toml create mode 100644 assets/jj/config.toml create mode 100644 assets/mise/config.toml create mode 100644 build-image.fish create mode 100644 devbox.fish diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..61876dd --- /dev/null +++ b/Containerfile @@ -0,0 +1,82 @@ +# syntax=docker/dockerfile:1 + +ARG BASE_IMAGE=ubuntu:25.10 + +FROM $BASE_IMAGE + +# Install basics omitted from the minimal Ubuntu server build. +RUN apt-get update && apt-get upgrade -y && apt-get install -y unminimize +RUN yes | unminimize + +# Install frequently used software dependencies and basics like Git and Fish. +RUN apt-get install -y gpg sudo wget curl build-essential software-properties-common libssl-dev pkg-config libglew-dev git fish + +# Install handy developer tools. +RUN apt-get install -y iputils-ping postgresql-client git-delta jq sqlite3 vim pipx ripgrep openssh-server + +# Install mise-en-place for project (and in some cases global) tooling management. +RUN install -dm 755 /etc/apt/keyrings +RUN wget -qO - https://mise.jdx.dev/gpg-key.pub | gpg --dearmor | tee /etc/apt/keyrings/mise-archive-keyring.gpg 1> /dev/null +RUN echo "deb [signed-by=/etc/apt/keyrings/mise-archive-keyring.gpg arch=arm64] https://mise.jdx.dev/deb stable main" \ + | tee /etc/apt/sources.list.d/mise.list +RUN apt-get update && apt-get install -y mise + +ARG USERNAME=developer + +RUN if [ -z $USERNAME ]; then exit 1; fi + +# Initialize non-root user account, with passwordless sudo. +RUN useradd -m -g sudo -s /usr/bin/fish $USERNAME +RUN sed -i'' 's/%sudo\tALL=(ALL:ALL) ALL/%sudo ALL = (ALL) NOPASSWD: ALL/g' /etc/sudoers +WORKDIR /home/$USERNAME +USER $USERNAME + +# Activate mise for non-root user's shell sessions. +RUN mkdir -p ~/.config/fish && echo 'mise activate fish | source' >> ~/.config/fish/config.fish && mkdir -p ~/.config/mise +COPY --chown=$USERNAME ./assets/mise/config.toml /home/$USERNAME/.config/mise/config.toml + +# Install stable Rust toolchain globally using mise (rustup management is automated). +RUN mise install + +# Install sqlx CLI for managing database migrations in sqlx projects. +RUN mise x -- cargo binstall -y cargo-nextest sqlx-cli + +# Install Claude Code CLI. +RUN curl -fsSL https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/bootstrap.sh | bash +RUN fish -c 'fish_add_path /home/$USERNAME/.local/bin' + +# Copy Helix configurations. +# It seems there's a bug in `apple/container`'s COPY implementation that fails +# to recursively copy directory contents from the host, so we point it to each +# file. +RUN mkdir -p ~/.config/helix/snippets && mkdir -p ~/.config/helix/themes +COPY --chown=$USERNAME ./assets/helix/*.toml /home/$USERNAME/.config/helix/ +COPY --chown=$USERNAME ./assets/helix/ignore /home/$USERNAME/.config/helix/ +COPY --chown=$USERNAME ./assets/helix/snippets/*.toml /home/$USERNAME/.config/helix/snippets/ +COPY --chown=$USERNAME ./assets/helix/themes/*.toml /home/$USERNAME/.config/helix/themes/ + +ARG VCS_EMAIL +ARG VCS_NAME + +# Copy Jujutsu configuration. +RUN mkdir -p ~/.config/jj +COPY --chown=$USERNAME ./assets/jj/config.toml /home/$USERNAME/.config/jj/ +RUN sed -i'' "s/{{ VCS_EMAIL }}/$VCS_EMAIL/" ~/.config/jj/config.toml +RUN sed -i'' "s/{{ VCS_NAME }}/$VCS_NAME/" ~/.config/jj/config.toml + +COPY --chown=$USERNAME ./assets/git/gitconfig /home/$USERNAME/.gitconfig +RUN sed -i'' "s/{{ VCS_EMAIL }}/$VCS_EMAIL/" ~/.gitconfig +RUN sed -i'' "s/{{ VCS_NAME }}/$VCS_NAME/" ~/.gitconfig + +# Delete VCS config if values not provided. +RUN if [ -z "$VCS_EMAIL" ] || [ -z "$VCS_NAME" ]; then rm ~/.gitconfig ~/.config/jj/config.toml; fi + +# Configure delta diff viewer. +ENV DELTA_FEATURES='side-by-side navigate' + +# Configure terminal. +ENV COLORTERM=truecolor +ENV SHELL=fish + +# Pop the user into the Fish shell by default. +CMD /usr/bin/fish diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e856a08 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +.PHONY: check-email fish-install questing noble + +questing: check-email + fish ./build-image.fish --email $(EMAIL) + +noble: check-email + fish ./build-image.fish -t devbox:noble -b ubuntu:24.04 --email $(EMAIL) + +fish-install: + cp ./devbox.fish ~/.config/fish/functions/devbox.fish + +check-email: +ifndef EMAIL + $(error Please set the EMAIL env var) +endif diff --git a/README.md b/README.md new file mode 100644 index 0000000..b8a907a --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# Development Environment in a Box + +My dotfiles, with a devcontainer image to boot. Depends on +[fish-shell](https://fishshell.com/) and +[container](https://github.com/apple/container). + +## Usage + +```fish +# Setup +make fish-install +EMAIL=git@example.com make questing + +# Execution +cd ~/path/to/project +devbox --cpus=4 --mem=8G my-project + +# Cleanup +container stop my-project +container rm my-project +``` diff --git a/assets/git/gitconfig b/assets/git/gitconfig new file mode 100644 index 0000000..efd811e --- /dev/null +++ b/assets/git/gitconfig @@ -0,0 +1,16 @@ +[user] + email = {{ VCS_EMAIL }} + name = {{ VCS_NAME }} + +[core] + pager = delta + +[interactive] + diffFilter = delta --color-only + +[delta] + side-by-side = true + navigate = true + +[merge] + conflictStyle = zdiff3 diff --git a/assets/helix/config.toml b/assets/helix/config.toml new file mode 100644 index 0000000..b0ed918 --- /dev/null +++ b/assets/helix/config.toml @@ -0,0 +1,48 @@ +theme = "yo_dracula" + +[editor] +rulers = [80, 100] +true-color = true + +[editor.cursor-shape] +insert = "bar" + +[editor.file-picker] +hidden = false +git-ignore = false + +[editor.soft-wrap] +enable = true + +[editor.statusline] +right = [ + "diagnostics", + "selections", + "primary-selection-length", + "spacer", + "position", + "position-percentage", +] + +[keys.normal] +"}" = "goto_next_paragraph" +"{" = "goto_prev_paragraph" +"y" = "yank_to_clipboard" +"d" = ["yank_to_clipboard", "delete_selection"] +"p" = "paste_clipboard_after" +"P" = "paste_clipboard_before" + +[keys.select] +"}" = "goto_next_paragraph" +"{" = "goto_prev_paragraph" +"y" = "yank_to_clipboard" +"d" = ["yank_to_clipboard", "delete_selection"] +"p" = "paste_clipboard_after" +"P" = "paste_clipboard_before" + +[keys.normal.space] +v = [":vs", "file_picker"] +s = [":sp", "file_picker"] +w = ":w" +q = ":q" +space = "rotate_view" diff --git a/assets/helix/ignore b/assets/helix/ignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/assets/helix/ignore @@ -0,0 +1 @@ +node_modules diff --git a/assets/helix/languages.toml b/assets/helix/languages.toml new file mode 100644 index 0000000..4f2015b --- /dev/null +++ b/assets/helix/languages.toml @@ -0,0 +1,102 @@ +[language-server.rust-analyzer.config] +check.command = "clippy" + +[language-server.deno] +command = "deno" +args = ["lsp"] +config = { enable = true, lint = true, unstable = true } + +[language-server.scls] +command = "simple-completion-language-server" + +[language-server.scls.config] +max_completion_items = 100 # set max completion results len for each group: words, snippets, unicode-input +feature_words = false # enable completion by word +feature_snippets = true # enable snippets +snippets_first = true # completions will return before snippets by default +snippets_inline_by_word_tail = false # suggest snippets by WORD tail, for example text `xsq|` become `x^2|` when snippet `sq` has body `^2` +feature_unicode_input = false # enable "unicode input" +feature_paths = true # enable path completion +feature_citations = false # enable citation completion (only on `citation` feature enabled) + +[language-server.ruff] +command = "ruff" +args = ["server"] + +[language-server.pyright] +command = "pyright-langserver" +args = ["--stdio"] + + +[[language]] +name = "javascript" +scope = "source.js" +injection-regex = "^(js|javascript)$" +file-types = ["js", "jsx", "mjs"] +shebangs = ["deno", "node"] +roots = ["deno.json", "deno.jsonc", "package.json", "tsconfig.json"] +comment-token = "//" +language-servers = ["deno"] +indent = { tab-width = 2, unit = " " } +auto-format = true + +[[language]] +name = "jsx" +scope = "source.jsx" +injection-regex = "jsx" +file-types = ["jsx"] +shebangs = ["deno", "node"] +roots = ["deno.json", "deno.jsonc", "package.json", "tsconfig.json"] +comment-token = "//" +language-servers = ["deno"] +indent = { tab-width = 2, unit = " " } +grammar = "javascript" +auto-format = true + +[[language]] +name = "typescript" +scope = "source.ts" +injection-regex = "^(ts|typescript)$" +file-types = ["ts"] +shebangs = ["deno", "node"] +roots = ["deno.json", "deno.jsonc", "package.json", "tsconfig.json"] +language-servers = ["deno"] +indent = { tab-width = 2, unit = " " } +auto-format = true + +[[language]] +name = "tsx" +scope = "source.tsx" +injection-regex = "^(tsx)$" # |typescript +file-types = ["tsx"] +shebangs = ["deno", "node"] +roots = ["deno.json", "deno.jsonc", "package.json", "tsconfig.json"] +language-servers = ["deno"] +indent = { tab-width = 2, unit = " " } +auto-format = true + +[[language]] +name = "html" +file-types = ["html", "liquid"] +language-servers = ["scls"] + +[[language]] +name = "rust" +language-servers = ["scls", "rust-analyzer"] + +[[language]] +name = "markdown" +scope = "source.md" +injection-regex = "md|markdown" +file-types = ["md", "livemd", "markdown", "mdx", "mkd", "mkdn", "mdwn", "mdown", "markdn", "mdtxt", "mdtext", "workbook", { glob = "PULLREQ_EDITMSG" }] +roots = [".marksman.toml"] +language-servers = [ "marksman", "markdown-oxide" ] +indent = { tab-width = 2, unit = " " } +block-comment-tokens = { start = "" } +auto-format = true +formatter = { command = "deno" , args = ["fmt", "-", "--ext", "md", "--prose-wrap=always"] } + +[[language]] +name = "python" +language-servers = ["ruff", "pyright"] +auto-format = true diff --git a/assets/helix/snippets/rust.toml b/assets/helix/snippets/rust.toml new file mode 100644 index 0000000..e1b2fff --- /dev/null +++ b/assets/helix/snippets/rust.toml @@ -0,0 +1,171 @@ +[[snippets]] +prefix = "drv" +body = """#[derive(Clone, Debug)] +$1struct $2 { + $3 +}""" + +[[snippets]] +prefix = "pbc" +body = "pub(crate) " + +[[snippets]] +prefix = "pbs" +body = "pub(super) " + +[[snippets]] +prefix = "phono_model" +body = """ +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; +use sqlx::query_as; +use uuid::Uuid; + +use crate::{client::AppDbClient, language::Language}; + +/// +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct $1 { + /// Primary key (defaults to UUIDv7). + pub id: Uuid, +} + +impl $1 { + /// Build an insert statement to create a new object. + pub fn insert() -> InsertBuilder { + InsertBuilder::default() + } + + /// Build an update statement to alter the content of an existing object. + pub fn update() -> UpdateBuilder { + UpdateBuilder::default() + } + + /// Build a single-field query by ID. + pub fn with_id(id: Uuid) -> WithIdQuery { + WithIdQuery { id } + } +} + +#[derive(Builder, Clone, Debug)] +pub struct Insertable { +} + +impl Insertable { + pub async fn execute(self, app_db: &mut AppDbClient) -> Result<$1, sqlx::Error> { + query_as!( + $1, + r#" +insert into $2 () values () +returning + id +"#, + ) + .fetch_one(app_db.get_conn()) + .await + } +} + +#[derive(Builder, Clone, Debug, Default)] +pub struct Update { +} + +impl Update { + pub async fn execute(self, app_db: &mut AppDbClient) -> Result<$1, sqlx::Error> { + query_as!( + $1, + r#" +insert into $2 +() +values () +returning + id +"#, + ) + .fetch_one(&mut *app_db.conn) + .await + } +} + +#[derive(Clone, Debug)] +pub struct WithIdQuery { + id: Uuid, +} + +impl WithIdQuery { + pub async fn fetch_all( + self, + app_db: &mut AppDbClient, + ) -> Result<$1, sqlx::Error> { + query_as!( + FieldFormPrompt, + r#" +select + id +from $2 +where id = $$1 +"#, + self.id, + ) + .fetch_one(app_db.get_conn()) + .await + } +} +""" + +[[snippets]] +prefix = "resptemp" +body = """#[derive(Template)] +#[template(path = $1)] +struct ResponseTemplate { + base_path: String, + breadcrumbs: BreadcrumbTrail, + csrf_token: String, + navbar: Navbar, +} + +Ok(Html( + ResponseTemplate { + breadcrumbs: BreadcrumbTrail::from_base_path(&base_path), + base_path, + csrf_token, + navbar: navbar_template.build(), + }.render()?, +).into_response())""" + +[[snippets]] +prefix = "dieselmodel" +body = """ +use diesel::{ + dsl::{auto_type, AsSelect}, + pg::Pg, + prelude::*, +}; + +use crate::schema::$1; + +pub use crate::schema::$1::{dsl, table}; + +#[derive(Clone, Debug, Identifiable, Queryable, Selectable)] +#[diesel(table_name = $1)] +pub struct $2 { + pub id: Uuid, +} + +impl $2 { + #[auto_type(no_type_alias)] + pub fn all() -> _ { + let select: AsSelect = Self::as_select(); + table.select(select) + } + + #[auto_type(no_type_alias)] + pub fn with_id<'a>(id: &'a Uuid) -> _ { + dsl::id.eq(id) + } +} +""" + +[[snippets]] +prefix = "atnta" +body = "#[auto_type(no_type_alias)]" diff --git a/assets/helix/themes/dracula_16.toml b/assets/helix/themes/dracula_16.toml new file mode 100644 index 0000000..ddc15ac --- /dev/null +++ b/assets/helix/themes/dracula_16.toml @@ -0,0 +1,77 @@ +# Author : Sam Sartor +# Modified by Brent Schroeter +# A port of https://github.com/bceskavich/dracula-at-night +"comment" = { fg = "comment" } +"constant" = { fg = "purple" } +"constant.character.escape" = { fg = "pink" } +"function" = { fg = "green" } +"keyword" = { fg = "pink" } +"operator" = { fg = "pink" } +"punctuation" = { fg = "foreground" } +"string" = { fg = "yellow" } +"string.regexp" = { fg = "red" } +"tag" = { fg = "pink" } +"type" = { fg = "cyan", modifiers = ["italic"] } +"type.enum.variant" = { fg = "foreground", modifiers = ["italic"] } +"variable" = { fg = "foreground" } +"variable.builtin" = { fg = "cyan", modifiers = ["italic"] } +"variable.parameter" = { fg ="orange", modifiers = ["italic"] } + +"diff.plus" = { fg = "green" } +"diff.delta" = { fg = "orange" } +"diff.minus" = { fg = "red" } + +"ui.background" = { fg = "foreground", bg = "background" } +"ui.cursor" = { fg = "background", bg = "orange", modifiers = ["dim"] } +"ui.cursor.match" = { fg = "green", modifiers = ["underlined"] } +"ui.cursor.primary" = { fg = "background", bg = "purple", modifiers = ["dim"] } +"ui.help" = { fg = "foreground", bg = "background_dark" } +"ui.linenr" = { fg = "comment" } +"ui.linenr.selected" = { fg = "foreground" } +"ui.menu" = { fg = "foreground", bg = "background_dark" } +"ui.menu.selected" = { fg = "cyan", bg = "background_dark" } +"ui.popup" = { fg = "foreground", bg = "background_dark" } +"ui.selection" = { fg = "background", bg = "purple", modifiers = ["dim"] } +"ui.selection.primary" = { bg = "background_light" } +"ui.cursorline" = { bg = "background_dark" } +"ui.statusline" = { fg = "foreground", bg = "background_dark" } +"ui.statusline.inactive" = { fg = "comment", bg = "background_dark" } +"ui.statusline.normal" = { fg = "background_dark", bg = "cyan" } +"ui.statusline.insert" = { fg = "background_dark", bg = "green" } +"ui.statusline.select" = { fg = "background_dark", bg = "purple" } +"ui.text" = { fg = "foreground" } +"ui.text.focus" = { fg = "cyan" } +"ui.window" = { fg = "foreground" } +"ui.virtual.ruler" = { bg = "background_dark" } + +"error" = { fg = "red" } +"warning" = { fg = "cyan" } + +"markup.heading" = { fg = "purple", modifiers = ["bold"] } +"markup.list" = "cyan" +"markup.bold" = { fg = "orange", modifiers = ["bold"] } +"markup.italic" = { fg = "yellow", modifiers = ["italic"] } +"markup.strikethrough" = { modifiers = ["crossed_out"] } +"markup.link.url" = "cyan" +"markup.link.text" = "pink" +"markup.quote" = { fg = "yellow", modifiers = ["italic"] } +"markup.raw" = { fg = "foreground" } + +"diagnostic.warning" = { underline = { color = "#cca700", style = "curl" } } +"diagnostic.error" = { underline = { color = "#f48771", style = "curl" } } +"diagnostic.info" = { underline = { color = "#75beff", style = "curl" } } +"diagnostic.hint" = { underline = { color = "#eeeeeb3", style = "curl" } } + +[palette] +background = "#0e1419" +background_dark = "#000000" +background_light = "#403090"# "#41424c" +foreground = "#f8f8f2" +comment = "#6272a4" +red = "#ff5555" +orange = "#ffb86c" +yellow = "#f1fa8c" +green = "#50fa7b" +purple = "#bd93f9" +cyan = "#8be9fd" +pink = "#ff79c6" \ No newline at end of file diff --git a/assets/helix/themes/dracula_helix.toml b/assets/helix/themes/dracula_helix.toml new file mode 100644 index 0000000..82d6064 --- /dev/null +++ b/assets/helix/themes/dracula_helix.toml @@ -0,0 +1,77 @@ +# Author : Sam Sartor +# Modified by Brent Schroeter +# A port of https://github.com/bceskavich/dracula-at-night +"comment" = { fg = "comment" } +"constant" = { fg = "purple" } +"constant.character.escape" = { fg = "pink" } +"function" = { fg = "green" } +"keyword" = { fg = "pink" } +"operator" = { fg = "pink" } +"punctuation" = { fg = "foreground" } +"string" = { fg = "yellow" } +"string.regexp" = { fg = "red" } +"tag" = { fg = "pink" } +"type" = { fg = "cyan", modifiers = ["italic"] } +"type.enum.variant" = { fg = "foreground", modifiers = ["italic"] } +"variable" = { fg = "foreground" } +"variable.builtin" = { fg = "cyan", modifiers = ["italic"] } +"variable.parameter" = { fg ="orange", modifiers = ["italic"] } + +"diff.plus" = { fg = "green" } +"diff.delta" = { fg = "orange" } +"diff.minus" = { fg = "red" } + +"ui.background" = { fg = "foreground", bg = "background" } +"ui.cursor" = { fg = "background", bg = "orange", modifiers = ["dim"] } +"ui.cursor.match" = { fg = "green", modifiers = ["underlined"] } +"ui.cursor.primary" = { fg = "background", bg = "purple", modifiers = ["dim"] } +"ui.help" = { fg = "foreground", bg = "background_dark" } +"ui.linenr" = { fg = "comment" } +"ui.linenr.selected" = { fg = "foreground" } +"ui.menu" = { fg = "foreground", bg = "background_dark" } +"ui.menu.selected" = { fg = "cyan", bg = "background_dark" } +"ui.popup" = { fg = "foreground", bg = "background_dark" } +"ui.selection" = { fg = "background", bg = "purple", modifiers = ["dim"] } +"ui.selection.primary" = { bg = "background_light" } +"ui.cursorline" = { bg = "background_dark" } +"ui.statusline" = { fg = "foreground", bg = "background_dark" } +"ui.statusline.inactive" = { fg = "comment", bg = "background_dark" } +"ui.statusline.normal" = { fg = "background_dark", bg = "cyan" } +"ui.statusline.insert" = { fg = "background_dark", bg = "green" } +"ui.statusline.select" = { fg = "background_dark", bg = "purple" } +"ui.text" = { fg = "foreground" } +"ui.text.focus" = { fg = "cyan" } +"ui.window" = { fg = "foreground" } +"ui.virtual.ruler" = { bg = "background_dark" } + +"error" = { fg = "red" } +"warning" = { fg = "cyan" } + +"markup.heading" = { fg = "purple", modifiers = ["bold"] } +"markup.list" = "cyan" +"markup.bold" = { fg = "orange", modifiers = ["bold"] } +"markup.italic" = { fg = "yellow", modifiers = ["italic"] } +"markup.strikethrough" = { modifiers = ["crossed_out"] } +"markup.link.url" = "cyan" +"markup.link.text" = "pink" +"markup.quote" = { fg = "yellow", modifiers = ["italic"] } +"markup.raw" = { fg = "foreground" } + +"diagnostic.warning" = { underline = { color = "#cca700", style = "curl" } } +"diagnostic.error" = { underline = { color = "#f48771", style = "curl" } } +"diagnostic.info" = { underline = { color = "#75beff", style = "curl" } } +"diagnostic.hint" = { underline = { color = "#eeeeeb3", style = "curl" } } + +[palette] +background = "#0e1419" +background_dark = "#21222c" +background_light = "#403090"# "#41424c" +foreground = "#f8f8f2" +comment = "#6272a4" +red = "#ff5555" +orange = "#ffb86c" +yellow = "#f1fa8c" +green = "#50fa7b" +purple = "#bd93f9" +cyan = "#8be9fd" +pink = "#ff79c6" \ No newline at end of file diff --git a/assets/helix/themes/yo_dracula.toml b/assets/helix/themes/yo_dracula.toml new file mode 100644 index 0000000..a9ffdc8 --- /dev/null +++ b/assets/helix/themes/yo_dracula.toml @@ -0,0 +1,159 @@ +# Author : Sebastian Zivota +# Author : Chirikumbrah + +"annotation" = { fg = "foreground" } + +"attribute" = { fg = "green", modifiers = ["italic"] } + +"comment" = { fg = "comment" } +"comment.block" = { fg = "comment" } +"comment.block.documentation" = { fg = "comment" } +"comment.line" = { fg = "comment" } +"comment.line.documentation" = { fg = "comment" } + +"constant" = { fg = "purple" } +"constant.builtin" = { fg = "purple" } +"constant.builtin.boolean" = { fg = "purple" } +"constant.character" = { fg = "cyan" } +"constant.character.escape" = { fg = "pink" } +"constant.macro" = { fg = "purple" } +"constant.numeric" = { fg = "purple" } +"constructor" = { fg = "purple" } + +"definition" = { underline = { color = "cyan" } } + +"diagnostic" = { underline = { color = "orange", style = "curl" } } +"diagnostic.hint" = { underline = { color = "purple", style = "curl" } } +"diagnostic.warning" = { underline = { color = "yellow", style = "curl" } } +"diagnostic.error" = { underline = { color = "red", style = "curl" } } +"diagnostic.info" = { underline = { color = "cyan", style = "curl" } } +"diagnostic.unnecessary" = { modifiers = ["dim"] } +"diagnostic.deprecated" = { modifiers = ["crossed_out"] } + +"error" = { fg = "red" } +"hint" = { fg = "purple" } +"info" = { fg = "cyan" } +"warning" = { fg = "yellow" } + +"diff.delta" = { fg = "orange" } +"diff.minus" = { fg = "red" } +"diff.plus" = { fg = "green" } + +# d +"function" = { fg = "purple" } +"function.builtin" = { fg = "purple" } +"function.call" = { fg = "purple" } +"function.macro" = { fg = "purple" } +"function.method" = { fg = "purple" } + +"keyword" = { fg = "cyan" } +#"keyword.control.conditional" = { fg = "pink" } +#"keyword.control.exception" = { fg = "purple" } +#"keyword.control.import" = { fg = "pink" } +#"keyword.control.repeat" = { fg = "pink" } +#"keyword.directive" = { fg = "green" } +#"keyword.function" = { fg = "pink" } +#"keyword.operator" = { fg = "pink" } +#"keyword.return" = { fg = "pink" } +#"keyword.storage" = { fg = "pink" } +#"keyword.storage.modifier" = { fg = "pink" } +#"keyword.storage.type" = { fg = "cyan", modifiers = ["italic"] } + +"label" = { fg = "cyan" } + +"markup.bold" = { fg = "orange", modifiers = ["bold"] } +"markup.heading" = { fg = "purple", modifiers = ["bold"] } +"markup.italic" = { fg = "yellow", modifiers = ["italic"] } +"markup.link.text" = { fg = "pink" } +"markup.link.url" = { fg = "cyan" } +"markup.list" = { fg = "cyan" } +"markup.quote" = { fg = "yellow", modifiers = ["italic"] } +"markup.raw" = { fg = "foreground" } +"markup.strikethrough" = { modifiers = ["crossed_out"] } + +"punctuation" = { fg = "foreground" } +"punctuation.bracket" = { fg = "foreground" } +"punctuation.delimiter" = { fg = "foreground" } +"punctuation.special" = { fg = "pink" } + +"special" = { fg = "pink" } + +"string" = { fg = "yellow" } +"string.regexp" = { fg = "red" } +"string.special" = { fg = "orange" } +"string.symbol" = { fg = "yellow" } + +"tag" = { fg = "pink" } +"tag.attribute" = { fg = "purple" } +"tag.delimiter" = { fg = "foreground" } + +# "type" = { fg = "cyan", modifiers = ["italic"] } +# "type.builtin" = { fg = "cyan" } +"type.enum.variant" = { fg = "foreground", modifiers = ["italic"] } + +"ui.background" = { fg = "foreground", bg = "background" } +"ui.cursor" = { fg = "background", bg = "purple", modifiers = ["dim"] } +"ui.cursor.insert" = { fg = "background", bg = "green", modifiers = ["dim"] } +"ui.cursor.match" = { fg = "foreground", bg = "grey" } +"ui.cursor.normal" = { fg = "background", bg = "purple", modifiers = ["dim"] } +"ui.cursor.primary.insert" = { fg = "background", bg = "green" } +"ui.cursor.primary.normal" = { fg = "background", bg = "purple" } +"ui.cursor.primary.select" = { fg = "background", bg = "cyan" } +"ui.cursor.select" = { fg = "background", bg = "cyan", modifiers = ["dim"] } +"ui.cursorline.primary" = { bg = "cursorline" } +"ui.debug" = { fg = "red" } +"ui.help" = { fg = "foreground", bg = "black" } +"ui.highlight.frameline" = { fg = "background", bg = "red" } +"ui.linenr" = { fg = "line_numbers" } +"ui.linenr.selected" = { fg = "foreground" } +"ui.menu" = { fg = "foreground", bg = "current_line" } +"ui.menu.scroll" = { fg = "foreground", bg = "current_line" } +"ui.menu.selected" = { fg = "current_line", bg = "purple", modifiers = ["dim"] } +"ui.popup" = { fg = "foreground", bg = "black" } +"ui.selection" = { bg = "selection" } +"ui.selection.primary" = { bg = "current_line" } +"ui.statusline" = { fg = "foreground", bg = "darker" } +"ui.statusline.inactive" = { fg = "comment", bg = "darker" } +"ui.statusline.insert" = { fg = "black", bg = "green", modifiers = ["bold"] } +"ui.statusline.normal" = { fg = "black", bg = "purple", modifiers = ["bold"] } +"ui.statusline.select" = { fg = "black", bg = "cyan", modifiers = ["bold"] } +"ui.text" = { fg = "foreground" } +"ui.text.focus" = { fg = "cyan" } +"ui.text.directory" = { fg = "cyan" } +"ui.virtual.indent-guide" = { fg = "indent" } +"ui.virtual.inlay-hint" = { fg = "cyan" } +"ui.virtual.inlay-hint.parameter" = { fg = "cyan", modifiers = ["italic", "dim"] } +"ui.virtual.inlay-hint.type" = { fg = "cyan", modifiers = ["italic", "dim"] } +"ui.virtual.jump-label" = { fg = "pink", modifiers = ["bold"] } +"ui.virtual.ruler" = { bg = "black" } +"ui.virtual.whitespace" = { fg = "whitespace" } +"ui.virtual.wrap" = { fg = "current_line" } +"ui.window" = { fg = "foreground" } + +"variable" = { fg = "foreground" } +"variable.builtin" = { fg = "purple", modifiers = ["italic"] } +"variable.other" = { fg = "foreground" } +"variable.other.member" = { fg = "foreground" } +"variable.parameter" = { fg = "foreground", modifiers = ["italic"] } + + +[palette] +background = "#242634" +black = "#191A21" +line_numbers = "#6272A4" +comment = "#ff4477" +current_line = "#44475a" +cursorline = "#2d303e" +cyan = "#8be9fd" +darker = "#222430" +foreground = "#eeeeee" +green = "#50fa7b" +grey = "#666771" +indent = "#56596a" +orange = "#ffb86c" +pink = "#ff79c6" +purple = "#BD93F9" +red = "#ff5555" +selection = "#363848" +whitespace = "#586693" +yellow = "#f1fa8c" diff --git a/assets/jj/config.toml b/assets/jj/config.toml new file mode 100644 index 0000000..3fe4fd0 --- /dev/null +++ b/assets/jj/config.toml @@ -0,0 +1,15 @@ +#:schema https://jj-vcs.github.io/jj/latest/config-schema.json + +[user] +email = "{{ VCS_EMAIL }}" +name = "{{ VCS_NAME }}" + +[ui] +editor = "hx" +default-command = "status" + +[[--scope]] +--when.commands = ["diff", "show"] +[--scope.ui] +pager = "delta" +diff-formatter = ":git" diff --git a/assets/mise/config.toml b/assets/mise/config.toml new file mode 100644 index 0000000..4c91a90 --- /dev/null +++ b/assets/mise/config.toml @@ -0,0 +1,13 @@ +[tools] +helix = "latest" +jujutsu = "latest" +lazygit = "latest" + +rust = { version = "stable", components = "rust-analyzer,rust-docs,rustfmt,clippy" } +"cargo:cargo-binstall" = "latest" + +deno = "latest" + +uv = "latest" +"pipx:pyright" = "latest" +"pipx:ruff" = "latest" diff --git a/build-image.fish b/build-image.fish new file mode 100644 index 0000000..7480a28 --- /dev/null +++ b/build-image.fish @@ -0,0 +1,49 @@ +# Build script for the devcontainer image. + +set -f DEFAULT_TAG 'devbox:questing' +set -f DEFAULT_BASE 'ubuntu:25.10' +set -f DEFAULT_USERNAME brent +set -f DEFAULT_FULL_NAME 'Brent Schroeter' + +argparse -S 'b/base=' 't/tag=' 'u/username=' 'email=' 'full-name=' no-cache -- $argv +or return 1 + +if not set -ql _flag_tag + set -f _flag_tag "$DEFAULT_TAG" +end +if not set -ql _flag_base + set -f _flag_base "$DEFAULT_BASE" +end +if not set -ql _flag_username + set -f _flag_username "$DEFAULT_USERNAME" +end +if not set -ql _flag_full_name + set -f _flag_full_name "$DEFAULT_FULL_NAME" +end +if not set -ql _flag_email + echo '--email is required for VCS configuration' >&2 + return 1 +end + +echo "Build configuration:" +echo " base = $_flag_base" +echo " tag = $_flag_tag" +echo " username = $_flag_username" +echo " email = $_flag_email" +echo " full_name = $_flag_full_name" + +if set -ql _flag_no_cache + container build --no-cache -t "$_flag_tag" \ + --build-arg "BASE_IMAGE=$_flag_base" \ + --build-arg "USERNAME=$_flag_username" \ + --build-arg "VCS_EMAIL=$_flag_email" \ + --build-arg "VCS_NAME=$_flag_full_name" \ + . +else + container build -t "$_flag_tag" \ + --build-arg "BASE_IMAGE=$_flag_base" \ + --build-arg "USERNAME=$_flag_username" \ + --build-arg "VCS_EMAIL=$_flag_email" \ + --build-arg "VCS_NAME=$_flag_full_name" \ + . +end diff --git a/devbox.fish b/devbox.fish new file mode 100644 index 0000000..0c96e19 --- /dev/null +++ b/devbox.fish @@ -0,0 +1,34 @@ +# Fish utility for easily shelling into devcontainers on the host. +# Uses Apple's `container` CLI (`brew install container`). + +function devbox --argument-names name + argparse 'c/cpus=?' 'm/mem=?' 'i/image=?' h/help -- $argv + or return 1 + + if set -ql _flag_h + echo "Usage: devbox [-c | --cpus=COUNT] [-m | --mem=LIMIT] [-i | --image=IMAGE] [-h | --help] NAME" >&2 + echo " Starts and executes a new shell session in a devcontainer with given name." >&2 + return 1 + end + + if not set -ql _flag_cpus + set -f _flag_cpus 10 + end + if not set -ql _flag_mem + set -f _flag_mem 8G + end + if not set -ql _flag_image + set -f _flag_image 'devbox:questing' + end + + if [ "$(container ls -a --format=json | jq '[.[] | select(.configuration.id == "'"$name"'")] | length')" = 0 ] + container run --name "$name" -it -c "$_flag_cpus" -m "$_flag_mem" -v "$(pwd):/home/brent/project" -w /home/brent/project "$_flag_image" + else + if [ "$(container ls -a --format=json | jq -r '.[] | select(.configuration.id == "'"$name"'").status')" = stopped ] + container start "$name" + end + + container ls | grep "^$name\s" # Print container info + container exec -it -w /home/brent/project $name /usr/bin/fish + end +end