commit 099e5d3738ba54c3d4dbc9001a16745c63b85909 Author: jyelon Date: Mon Mar 9 00:14:40 2026 -0400 Initial commit diff --git a/bash/dot-bashrc b/bash/dot-bashrc new file mode 100644 index 0000000..b488fcc --- /dev/null +++ b/bash/dot-bashrc @@ -0,0 +1,117 @@ +# ~/.bashrc: executed by bash(1) for non-login shells. +# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) +# for examples + +# If not running interactively, don't do anything +case $- in + *i*) ;; + *) return;; +esac + +# don't put duplicate lines or lines starting with space in the history. +# See bash(1) for more options +HISTCONTROL=ignoreboth + +# append to the history file, don't overwrite it +shopt -s histappend + +# for setting history length see HISTSIZE and HISTFILESIZE in bash(1) +HISTSIZE=1000 +HISTFILESIZE=2000 + +# check the window size after each command and, if necessary, +# update the values of LINES and COLUMNS. +shopt -s checkwinsize + +# If set, the pattern "**" used in a pathname expansion context will +# match all files and zero or more directories and subdirectories. +#shopt -s globstar + +# make less more friendly for non-text input files, see lesspipe(1) +[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" + +# set variable identifying the chroot you work in (used in the prompt below) +if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then + debian_chroot=$(cat /etc/debian_chroot) +fi + +# set a fancy prompt (non-color, unless we know we "want" color) +case "$TERM" in + xterm-color|*-256color) color_prompt=yes;; +esac + +# uncomment for a colored prompt, if the terminal has the capability; turned +# off by default to not distract the user: the focus in a terminal window +# should be on the output of commands, not on the prompt +#force_color_prompt=yes + +if [ -n "$force_color_prompt" ]; then + if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then + # We have color support; assume it's compliant with Ecma-48 + # (ISO/IEC-6429). (Lack of such support is extremely rare, and such + # a case would tend to support setf rather than setaf.) + color_prompt=yes + else + color_prompt= + fi +fi + +if [ "$color_prompt" = yes ]; then + PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' +else + PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' +fi +unset color_prompt force_color_prompt + +# If this is an xterm set the title to user@host:dir +case "$TERM" in +xterm*|rxvt*) + PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" + ;; +*) + ;; +esac + +# enable color support of ls and also add handy aliases +if [ -x /usr/bin/dircolors ]; then + test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" + alias ls='ls --color=auto' + #alias dir='dir --color=auto' + #alias vdir='vdir --color=auto' + + alias grep='grep --color=auto' + alias fgrep='fgrep --color=auto' + alias egrep='egrep --color=auto' +fi + +# colored GCC warnings and errors +#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' + +# some more ls aliases +alias ll='ls -alF' +alias la='ls -A' +alias l='ls -CF' + +# Add an "alert" alias for long running commands. Use like so: +# sleep 10; alert +alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' + +# Alias definitions. +# You may want to put all your additions into a separate file like +# ~/.bash_aliases, instead of adding them here directly. +# See /usr/share/doc/bash-doc/examples in the bash-doc package. + +if [ -f ~/.bash_aliases ]; then + . ~/.bash_aliases +fi + +# enable programmable completion features (you don't need to enable +# this, if it's already enabled in /etc/bash.bashrc and /etc/profile +# sources /etc/bash.bashrc). +if ! shopt -oq posix; then + if [ -f /usr/share/bash-completion/bash_completion ]; then + . /usr/share/bash-completion/bash_completion + elif [ -f /etc/bash_completion ]; then + . /etc/bash_completion + fi +fi diff --git a/bash/dot-profile b/bash/dot-profile new file mode 100644 index 0000000..d89ea5a --- /dev/null +++ b/bash/dot-profile @@ -0,0 +1,27 @@ +# ~/.profile: executed by the command interpreter for login shells. +# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login +# exists. +# see /usr/share/doc/bash/examples/startup-files for examples. +# the files are located in the bash-doc package. + +# the default umask is set in /etc/profile; for setting the umask +# for ssh logins, install and configure the libpam-umask package. +#umask 022 + +# if running bash +if [ -n "$BASH_VERSION" ]; then + # include .bashrc if it exists + if [ -f "$HOME/.bashrc" ]; then + . "$HOME/.bashrc" + fi +fi + +# set PATH so it includes user's private bin if it exists +if [ -d "$HOME/bin" ] ; then + PATH="$HOME/bin:$PATH" +fi + +# set PATH so it includes user's private bin if it exists +if [ -d "$HOME/.local/bin" ] ; then + PATH="$HOME/.local/bin:$PATH" +fi diff --git a/claude/CLAUDE.md b/claude/CLAUDE.md new file mode 100644 index 0000000..006a293 --- /dev/null +++ b/claude/CLAUDE.md @@ -0,0 +1,162 @@ +# Global Rules + +- Do not start doing complicated things without the user's + explicit approval first. + +- Do not try to be the project architect. The user is the + architect, you are the assistant. + +- Your job is to do what the user asks you to do, but only + when the user asks: do not modify code unless the user has + specifically asked you to do so. + +- Never check anything into git. Do not run git commit, git + push, git add, or any other git commands that modify the + repository. I will handle all git interactions myself. + +- If a prompt ends with an ellipsis, it means the user has + more to type. In that case, only comment if you have + concerns. + +## How Writing the API Docs helps you make the API better. + +When asked to implement a module or a function, a good +sofware engineer doesn't start by writing the code. Instead, +you a write a block comment explaining the API to the +customer. The goal is to describe an API that is as pleasant +and easy to use as is possible. That's what you write: the +documentation for the greatest API ever. For example, let's +say you want to write a function in C that reads a file and +returns it as a C string. You write this: + +``` + /* Reads a file. Returns the content as a C string. */ +``` + +Simple and easy to use. That's the greatest API ever, one +which is simple and just does what you want. So then you +write the code: + +``` + // Read a file. Returns a char* with the file content. + // + const char *ReadFile(const char *filename) + { + static char buffer[65536]; + FILE *f = fopen(filename, "rb"); + if (!f) return NULL; + size_t n = fread(buffer, 1, sizeof(buffer) - 1, f); + fclose(f); + if (n == sizeof(buffer) - 1) return NULL; + buffer[n] = '\0'; + return buffer; + } +``` + +Then, after writing the code, you go back to the comment, +and you ask yourself: is this documentation truthful? Is +this really what the function does? In our example, it's +not. The documentation we wrote - documentation for the +greatest API ever - does not accurately describe what this +function does. Here's more accurate documentation: + +``` + /* Read a file. Returns a char* with the file content. + If the file is more than 65535 characters, returns + nullptr. Not thread-safe. */ +``` + +Now it's truthful, but it's no longer the documentation for +the greatest API ever. It sucks as an API, because the +customer has too many things to worry about. + +So now you have a struggle on your hands. You have to +figure out to make the code have a nicer API. So you +consider maybe using malloc for the buffer. That would get +rid of the 64k limit, and thread-safety issue. So, you go +back change the code to malloc a buffer. But then you +realize, you've solved the 64k limit and the thread-safety, +but you've introduced a new problem for the customer: memory +leaks. + +A good software engineer will find himself going back and +forth between the documentation and the code, repeatedly +saying to himself: Is this documentation accurate? Could +it be simpler? Can I fix the code to make the API simpler? +A decent engineer will go back and forth several times. + +## Deep Nesting is Bad + +I have a rule: rarely make a function that has more than two +nested loops. Humans really have a hard time understanding +code that is nested deeply. So the rule is basically, +that this is OK: + +``` + if (x) { + while (y) { + ... + } + } +``` + +That's two levels of nesting. But add another conditional +or loop inside the while, and it's too much. + +Now, sometimes you need something like a namespace, which +adds another pair of braces: namespace { ... }. That +doesn't count as a level of nesting. The namespace increases +the indentation, but it's not increasing the code +complexity. Indentation isn't the problem. The problem is +that deeply nested loops and deeply nested conditionals are +hard to follow. + +## Keeping Things Synchronized is Bad + +Let's say I have an enum: + +``` + enum ShapeType { CIRCLE, SQUARE, TRIANGLE } +``` + +Then, somewhere else, in a completely different file, +I have this: + +``` + const char *ShapeString(ShapeType s) { + switch (shape) { + case CIRCLE: return "CIRCLE"; + case SQUARE: return "SQUARE"; + case TRIANGLE: return "TRIANGLE"; + } + } +``` + +Now I have to keep these two synchronized. If I add another +shape, I have to add it in *two* places. Humans are +terrible at remembering that they have to update two places: +I honestly think AIs aren't any better. You can make this +a lot better if you put the 'ShapeString' function *right* +next to the enum. If you can put them right next to each +other, then anybody who edits the enum will also see that +they have to update the ShapeString function. + +## A Recap of My Software Engineering Rules + +1. Always write a block comment with the API docs before + writing a function or module. Make it the greatest API + ever: make it super easy-to-use. + +2. After writing the API docs, write the code. Then, + begin a process of iteration in which you compare the + docs and the code, fixing both of them until they match, + but always prioritizing fixing the code to make the API + simpler, and not settling for documenting something that's + hard to use. + +3. In functions, keep the nesting level of loops and + conditionals 2 deep or less. + +4. Don't create a situation where you have to keep two + things synchronized, *especially* if the two things + are in separate files. diff --git a/claude/settings.json b/claude/settings.json new file mode 100755 index 0000000..07fd0aa --- /dev/null +++ b/claude/settings.json @@ -0,0 +1,66 @@ +{ + "env": { + "CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION": "false" + }, + "permissions": { + "allow": [ + "Read", + "Read(~/*)", + "Glob(~/*)", + "Grep(~/*)", + "WebFetch", + "WebSearch", + "Bash(grep:*)", + "Bash(ls:*)", + "Bash(find:*)", + "Bash(code --goto:*)", + "Bash(git check-ignore:*)", + "Bash(head:*)", + "Bash(tail:*)", + "Bash(python3:*)", + "Bash(wc:*)", + "Bash(file:*)", + "Bash(stat:*)", + "Bash(du:*)", + "Bash(df:*)", + "Bash(which:*)", + "Bash(whereis:*)", + "Bash(type:*)", + "Bash(env:*)", + "Bash(printenv:*)", + "Bash(echo:*)", + "Bash(diff:*)", + "Bash(sort:*)", + "Bash(uniq:*)", + "Bash(tree:*)", + "Bash(git status:*)", + "Bash(git log:*)", + "Bash(git diff:*)", + "Bash(git show:*)" + ], + "deny": [ + "Bash(git add *)", + "Bash(git commit *)", + "Bash(git push *)", + "Bash(git pull *)", + "Bash(git fetch *)", + "Bash(git merge *)", + "Bash(git rebase *)", + "Bash(git reset *)", + "Bash(git checkout *)", + "Bash(git switch *)", + "Bash(git branch *)", + "Bash(git stash *)", + "Bash(git cherry-pick *)", + "Bash(git revert *)", + "Bash(git tag *)", + "Bash(git clean *)", + "Bash(git restore *)", + "Bash(git rm *)", + "Bash(git mv *)", + "Bash(rm -rf *)" + ], + "defaultMode": "acceptEdits" + }, + "theme": "light" +} diff --git a/emacs/dot-emacs b/emacs/dot-emacs new file mode 100644 index 0000000..73f84ae --- /dev/null +++ b/emacs/dot-emacs @@ -0,0 +1 @@ +(put 'erase-buffer 'disabled nil) diff --git a/git/dot-gitconfig b/git/dot-gitconfig new file mode 100644 index 0000000..081760f --- /dev/null +++ b/git/dot-gitconfig @@ -0,0 +1,10 @@ +[filter "lfs"] + clean = git-lfs clean -- %f + smudge = git-lfs smudge -- %f + process = git-lfs filter-process + required = true +[user] + name = jyelon + email = jyelon@gmail.com +[credential] + helper = cache --timeout 43200 diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..fe0f0d4 --- /dev/null +++ b/install.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# +# Installs config files from this repo by creating symlinks. +# On first run, backs up originals to ~/.orig-config. +# + +REPO_DIR="$HOME/jbashrc" + +# The list of config files: "repo-relative-path:absolute-target" +FILES=( + "bash/dot-bashrc:$HOME/.bashrc" + "bash/dot-profile:$HOME/.profile" + "claude/CLAUDE.md:$HOME/.claude/CLAUDE.md" + "claude/settings.json:$HOME/.claude/settings.json" + "emacs/dot-emacs:$HOME/.emacs" + "git/dot-gitconfig:$HOME/.gitconfig" + "vscode/chatLanguageModels.json:$HOME/.config/Code/User/chatLanguageModels.json" + "vscode/keybindings.json:$HOME/.config/Code/User/keybindings.json" + "vscode/settings.json:$HOME/.config/Code/User/settings.json" +) + +# Back up originals that haven't been backed up yet. +mkdir -p "$HOME/.orig-config" +for entry in "${FILES[@]}"; do + src_rel="${entry%%:*}" + target="${entry#*:}" + backup="$HOME/.orig-config/$src_rel" + if [ ! -e "$backup" ] && [ -e "$target" ] && [ ! -L "$target" ]; then + mkdir -p "$(dirname "$backup")" + cp "$target" "$backup" + echo "Backed up $target" + fi +done + +# Create symlinks. +for entry in "${FILES[@]}"; do + src="$REPO_DIR/${entry%%:*}" + target="${entry#*:}" + mkdir -p "$(dirname "$target")" + ln -sf "$src" "$target" + echo "Linked $target -> $src" +done diff --git a/vscode/chatLanguageModels.json b/vscode/chatLanguageModels.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/vscode/chatLanguageModels.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/vscode/keybindings.json b/vscode/keybindings.json new file mode 100644 index 0000000..2b3fddc --- /dev/null +++ b/vscode/keybindings.json @@ -0,0 +1,23 @@ +// Place your key bindings in this file to override the defaults +[ + { + "key": "ctrl+r", + "command": "-workbench.action.openRecent" + }, + { + "key": "ctrl+r", + "command": "-workbench.action.terminal.runRecentCommand" + }, + { + "key": "ctrl+r", + "command": "-workbench.action.quickOpenNavigateNextInRecentFilesPicker" + }, + { + "key": "ctrl+r", + "command": "-workbench.action.terminal.chat.rerunRequest" + }, + { + "key": "ctrl+r", + "command": "workbench.action.reloadWindow" + } +] \ No newline at end of file diff --git a/vscode/settings.json b/vscode/settings.json new file mode 100644 index 0000000..39db58f --- /dev/null +++ b/vscode/settings.json @@ -0,0 +1,11 @@ +{ + "editor.inlayHints.enabled": "off", + "editor.hover.enabled": "off", + "claudeCode.preferredLocation": "panel", + "workbench.editor.empty.hint": "hidden", + "editor.rulers": [ + 60, + 78 + ], + "explorer.confirmDelete": false +} \ No newline at end of file