diff options
Diffstat (limited to 'dotfiles')
| -rw-r--r-- | dotfiles/.config/zsh/.zshrc | 6 | ||||
| -rwxr-xr-x | dotfiles/.local/bin/chcolors | 5 | ||||
| -rwxr-xr-x | dotfiles/.local/bin/shtheme | 669 | ||||
| -rw-r--r-- | dotfiles/.profile | 2 | 
4 files changed, 676 insertions, 6 deletions
| diff --git a/dotfiles/.config/zsh/.zshrc b/dotfiles/.config/zsh/.zshrc index a7f3000..aa1bc69 100644 --- a/dotfiles/.config/zsh/.zshrc +++ b/dotfiles/.config/zsh/.zshrc @@ -69,7 +69,11 @@ zle -N zle-keymap-select  [ -f "$HOME/.config/zsh/shortcuts" ] && . "$HOME/.config/zsh/shortcuts" -[ -f "$HOME/.cache/colorscheme" ] && trap "source $HOME/.cache/colorscheme" DEBUG +if [ -f "$HOME/.cache/colorscheme" ]; then +	trap "source $HOME/.cache/colorscheme && shtheme ultramar-\$COLORSCHEME" SIGUSR1 +	source $HOME/.cache/colorscheme +	shtheme ultramar-$COLORSCHEME +fi  if [ -f /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]  then diff --git a/dotfiles/.local/bin/chcolors b/dotfiles/.local/bin/chcolors index e62b047..9cd4270 100755 --- a/dotfiles/.local/bin/chcolors +++ b/dotfiles/.local/bin/chcolors @@ -13,8 +13,5 @@ case $COLORSCHEME in  		COLORSCHEME="dark" ;;  esac -sed -i --follow-symlinks \ -	"s/^colors:.*/colors: \*$COLORSCHEME/g" \ -	$HOME/.config/alacritty/alacritty.yml -  echo "export COLORSCHEME=$COLORSCHEME" > $HOME/.cache/colorscheme +pkill -SIGUSR1 zsh diff --git a/dotfiles/.local/bin/shtheme b/dotfiles/.local/bin/shtheme new file mode 100755 index 0000000..2071019 --- /dev/null +++ b/dotfiles/.local/bin/shtheme @@ -0,0 +1,669 @@ +#!/bin/sh + +# Written by Aetnaeus. +# Source: https://github.com/lemnos/theme.sh. +# Licensed under the WTFPL provided this notice is preserved. + +# Find a broken theme? Want to add a missing one? PRs are welcome. + +VERSION=v1.1.5 + +# Use truecolor sequences to simulate the end result. + +preview() { +	awk -F": " -v target="$1" ' +		BEGIN { +			"tput cols" | getline nc +			"tput lines" | getline nr +			nc = int(nc) +			nr = int(nr) +		} + +		/^# Themes/ { start++;next } +		!start { next } + +		function hextorgb(s) { +			hexchars = "0123456789abcdef" +			s = tolower(s) + +			r = (index(hexchars, substr(s, 2, 1))-1)*16+(index(hexchars, substr(s, 3, 1))-1) +			g = (index(hexchars, substr(s, 4, 1))-1)*16+(index(hexchars, substr(s, 5, 1))-1) +			b = (index(hexchars, substr(s, 6, 1))-1)*16+(index(hexchars, substr(s, 7, 1))-1) +		} + +		function fgesc(col) { +			hextorgb(col) +			return sprintf("\x1b[38;2;%d;%d;%dm", r, g, b) +		} + +		function bgesc(col) { +			hextorgb(col) +			return sprintf("\x1b[48;2;%d;%d;%dm", r, g, b) +		} + +		$0 == target {s++} + +		s && /^foreground:/ { fg = $2 } +		s && /^background:/ { bg = $2 } +		s && /^[0-9]+:/ { a[$1] = $2 } + +		/^ *$/ {s=0} + +		function puts(s,   len,   i,   normesc,   filling) { +			normesc = sprintf("\x1b[0m%s%s", fgesc(fg), bgesc(bg)) + +			len=s +			gsub(/\033\[[^m]*m/, "", len) +			len=length(len) + +			filling="" +			for(i=0;i<(nc-len);i++) filling=filling" " + +			printf "%s%s%s%s\n", normesc, s, normesc, filling, "" +			nr-- +		} + +		END { +			puts("") +			for (i = 0;i<16;i++) +				puts(sprintf("  %s Color %d\x1b[0m", fgesc(a[i]), i)) + +			# Note: Some terminals use different colors for bolded text and may produce slightly different ls output. + +			puts("") +			puts(" # ls --color -F") +			puts(sprintf("    file")) +			puts(sprintf("    \x1b[1m%sdir/", fgesc(a[4]))) +			puts(sprintf("    \x1b[1m%sexecutable", fgesc(a[10]))) +			puts(sprintf("    \x1b[1m%ssymlink\x1b[0m%s%s", fgesc(a[6]), fgesc(fg), bgesc(bg))) + + +			while(nr > 0) puts("") + +			printf "\x1b[0m" +		} +	' < "$0" +} + +# Alphabetize and dedupe theme list. + +normalize_themes() { +	awk ' +		# We could eliminate the sorting logic by using gnu extensions but that would reduce portability. + +		function cmp(a,b,ordTbl,    i,c1,c2,n) { +			n = length(a) > length(b) ? length(b) : length(a) +			for(i = 1;i <= n;i++) { +				c1 = substr(a, i, 1) +				c2 = substr(b, i, 1) + +				if(c1 != c2) +					return ordTbl[c1] < ordTbl[c2] +			} + +			return length(a) < length(b) +		} + +		function sort(a,n,    i,j,tmp,ordTbl) { +			 for(i = 0;i < 256;i++) ordTbl[sprintf("%c", i)] = i + +			for(i = 0;i < n;i++) { +				tmp = a[i] +				j = i-1 +				while(j >= 0 && cmp(tmp, a[j], ordTbl)) { +					a[j+1] = a[j] +					j-- +				} + +				a[j+1] = tmp +			} +		} + +		function sortKeys(a,keys,    n,k) { +			for(k in a) +				keys[n++] = k +			sort(keys, n) +			return n +		} + +		/^ *$/ { inTheme = 0;next } +		!inTheme { name = $0;inTheme=1;themes[name] = "";next } +		inTheme { themes[name] = themes[name]$0"\n" } + +		END { +			n = sortKeys(themes, names) + +			print "" +			for(i = 0;i < n;i++) { +				print names[i] +				print tolower(themes[names[i]]) +			} +		} +	' "$@" +} + +# Generate themes from one or more supplied kitty config files. + +generate_themes() { +	awk -v argc=$# ' +		function chkProp(prop) { +			if(!props[prop]) { +				printf "ABORTING: %s is missing required property '\''%s'\''\n", currentFile, prop > "/dev/stderr" +				aborted++ +				exit -1 +			} +		} + +		function printTheme(    name,i,prop) { +			name = currentFile +			gsub(/.*\//, "", name) +			gsub(/\.conf$/, "", name) + +			print name + +			for (i = 0;i < 16;i++) { +				prop = sprintf("color%d", i) + +				chkProp(prop) +				printf "%d: %s\n", i, props[prop] +			} + +			chkProp("foreground") +			chkProp("background") +			chkProp("cursor") + +			print "foreground: "props["foreground"] +			print "background: "props["background"] +			print "cursor: "props["cursor"] +			print "" +		} + +		FILENAME != currentFile { +			if(currentFile) +				printTheme() + +			currentFile = FILENAME +			delete props +		} + +		{ props[$1] = $2 } + +		END { if(!aborted) printTheme() } +	' "$@" +} + +# Add themes to the script from one or more supplied kitty config files. + +add() { +	tmp1="$(mktemp)" +	tmp2="$(mktemp)" + +	awk 'i { print } /^# Themes/ { i++ }' "$0" > "$tmp1" +	echo "" >> "$tmp1" +	generate_themes "$@" >> "$tmp1" || exit $? + +	awk '{print} /^# Themes/ { exit }'  "$0" > "$tmp2" +	normalize_themes "$tmp1" >> "$tmp2" + + +	rm "$tmp1" +	cat "$tmp2" > "$0" || exit $? + +	printf 'Successfully annexed %d themes. More! Feed me more!\n' $# +} + +preview2() { +	INHIBIT_THEME_HIST=1 "$0" "$1" + +	printf '\033[30mColor 0\n' +	printf '\033[31mColor 1\n' +	printf '\033[32mColor 2\n' +	printf '\033[33mColor 3\n' +	printf '\033[34mColor 4\n' +	printf '\033[35mColor 5\n' +	printf '\033[36mColor 6\n' +	printf '\033[37mColor 7\n' + +	printf '\033[90mColor 8\n' +	printf '\033[91mColor 9\n' +	printf '\033[92mColor 10\n' +	printf '\033[93mColor 11\n' +	printf '\033[94mColor 12\n' +	printf '\033[95mColor 13\n' +	printf '\033[96mColor 14\n' +	printf '\033[97mColor 15\n' + +	printf '\n\033[0m' +	printf '# ls --color -F\n' +	printf '    file\n' +	printf '    \033[01;34mdir/\033[0m\n' +	printf '    \033[01;32mexecutable\033[0m*\n' +	printf '    \033[01;36msymlink\033[0m\n' + +	printf '\033[0m' +} + +# Consumes a theme.sh definition from STDIN and applies it. + +apply_theme() { +awk ' +	function tmuxesc(s) { return sprintf("\033Ptmux;\033%s\033\\", s) } +	function normalize_term() { +		# Term detection voodoo + +		if(ENVIRON["TERM_PROGRAM"] == "iTerm.app") +			term="iterm" +		else if(ENVIRON["TMUX"]) { +			"tmux display-message -p \"#{client_termname}\"" | getline term +			"tmux display-message -p \"#{client_termtype}\"" | getline termname + +			if(substr(termname, 1, 5) == "iTerm") +				term="iterm" +			is_tmux++ +		} else +			term=ENVIRON["TERM"] +	} + +	BEGIN { +		normalize_term() + +		if(term == "iterm") { +			bgesc="\033]Ph%s\033\\" +			fgesc="\033]Pg%s\033\\" +			colesc="\033]P%x%s\033\\" +			curesc="\033]Pl%s\033\\" +		} else { +			#Terms that play nice :) + +			fgesc="\033]10;#%s\007" +			bgesc="\033]11;#%s\007" +			curesc="\033]12;#%s\007" +			colesc="\033]4;%d;#%s\007" +		} + +		if(is_tmux) { +			fgesc=tmuxesc(fgesc) +			bgesc=tmuxesc(bgesc) +			curesc=tmuxesc(curesc) +			colesc=tmuxesc(colesc) +		} +	} + +	/^foreground:/ { printf fgesc, substr($2, 2) > "/dev/tty" } +	/^background:/ { printf bgesc, substr($2, 2) > "/dev/tty" } +	/^cursor:/ { printf curesc, substr($2, 2) > "/dev/tty" } +	/^[0-9]+:/ { printf colesc, $1, substr($2, 2) > "/dev/tty" } +' +} + +# Sets the current theme given a name and does the requisite bookkeeping. + +set_current_theme() { +	awk -F": " -v target="$1" -v script="$0" ' +		/^# Themes/ { start++;next; } +		!start { next } + +		$0 == target { found++;next; } + +		found { theme = theme $0 "\n" } +		found && /^ *$/ { exit } + +		END { +			if(found) { +				printf "%s", theme | script + +				config_dir = (ENVIRON["XDG_CONFIG_HOME"] ?  ENVIRON["XDG_CONFIG_HOME"] : ENVIRON["HOME"]) + +				histfile = config_dir"/.theme_history" +				inhibit_hist=ENVIRON["INHIBIT_THEME_HIST"] + +				if(!inhibit_hist) { +					while((getline < histfile) > 0) +						if($0 != target) +							out = out $0 "\n" +					close(histfile) + +					out = out target +					print out > histfile +				} +			} else { +					printf "Theme not found: %s\n", target > "/dev/stderr" +					exit(-1) +			} +		} +	' < "$0" +} + +# Dump the current theme in a format consumable by theme.sh +# by attempting to read it from the terminal. +# +# NOTE: Many terms don't support this properly (e.g alacritty) + +# Refs + +# https://github.com/microsoft/terminal/issues/3718 +# https://github.com/alacritty/alacritty/blob/master/alacritty_terminal/src/ansi.rs#L972 + +print_current_theme() { +	awk ' +	function print_response(s) { +		names["10;"] = "foreground" +		names["11;"] = "background" +		names["12;"] = "cursor" +		for (i = 0; i < 16; i++) +			names[sprintf("4;%d;", i)] = i + +		split(s, a, "]") +		for (i in a) { +			if (match(a[i], /rgb:/)) { +				key = substr(a[i], 1, RSTART-1) + +				r=substr(a[i], RSTART+4, 2) +				g=substr(a[i], RSTART+9, 2) +				b=substr(a[i], RSTART+14, 2) + +				printf "%s: %s\n", names[key], "#"r g b +			} +		} +	} + +	# We cant just use RS/getline for this since +	# mawk does input buffering :(. + +	function read_response() { +		buf = "" + +		# Accrue data until we encounter the terminating CSI response +		while ((end=index(buf,"[")) == 0) { +			# poor POSIX mans read :/ +			cmd="dd if=/dev/tty bs=1024 count=1 2> /dev/null" + +			while (cmd|getline data) +				buf = buf data + +			close(cmd) +		} + +		buf = substr(buf, 1, end-1) +		return buf +	} + +	BEGIN { +		system("stty cbreak -echo") + +		tty = "/dev/tty" + +		# Yo dawg, I heard you like multiplexers... +		if (ENVIRON["TMUX"]) { +			# If we are running inside tmux we sent the request sequences +			# to the currently attached terminal. Note that we still +			# read the result from the virtual terminal. + +			# Flow: +			# theme.sh (request) -> tty (response) -> pts (response) -> theme.sh +			# where pts is the tmux pseudoterminal. + +			"tmux display-message -p \"#{client_tty}\""|getline tty +		} + +		# Terminals may ignore these. + +		for(i=0;i<16;i++) +			printf "\033]4;%d;?\007", i > tty + +		printf "\033]10;?\007" > tty +		printf "\033]11;?\007" > tty +		printf "\033]12;?\007" > tty + +		# Use a CSI DA1 sequence (supported by all terms) +		# as a sentinel value to indicate end-of-response. +		# (assumes request-response order is fifo) + +		printf "\033[c" > tty + +		print_response(read_response()) + +		system("stty -cbreak echo") +	} +	' +} + +isColorTerm() { +	if [ -z "$TMUX" ]; then +		[ -n "$COLORTERM" ] +	else +		tmux display-message -p '#{client_termfeatures}'|grep -q RGB +	fi +} + +list() { +	case "$filterFlag" in +		--light) filter=2 ;; +		--dark) filter=1 ;; +		*) filter=0 ;; +	esac + +	awk -v filter="$filter" -F": " ' +		BEGIN { +			config_dir = ENVIRON["XDG_CONFIG_HOME"] ?  ENVIRON["XDG_CONFIG_HOME"] : ENVIRON["HOME"] + +			histfile = config_dir"/.theme_history" +			while((getline < histfile) > 0) { +				mru[nmru++] = $0 +				mruIndex[$0] = 1 +			} +		} + +		function luma(s,    r,g,b,hexchars) { +			hexchars = "0123456789abcdef" +			s = tolower(s) + +			r = (index(hexchars, substr(s, 2, 1))-1)*16+(index(hexchars, substr(s, 3, 1))-1) +			g = (index(hexchars, substr(s, 4, 1))-1)*16+(index(hexchars, substr(s, 5, 1))-1) +			b = (index(hexchars, substr(s, 6, 1))-1)*16+(index(hexchars, substr(s, 7, 1))-1) + +			return 0.2126 * r + 0.7152 * g + 0.0722 * b +		} + +		/^# Theme/ { st++;next } +		!st { next } + +		/^ *$/ { inner = 0;next } +		!inner { name = $0;inner++;next } + +		/^background/ { +			if((filter == 1 && luma($2) > 130) || +			   (filter == 2 && luma($2) <= 130)) +				next + +			candidates[name] = 1 +		} + +		END { +			for(c in candidates) { +				if(!mruIndex[c]) +					print(c) +			} + +			for(i = 0;i < nmru;i++) +				if(candidates[mru[i]]) +					print(mru[i]) +		} +	' < "$0" +} + + +if [ -z "$1" ]; then +	if [ -t 0 ]; then +		echo "usage: $(basename "$0") [-v] [-h] <option>|<theme>" +		exit 255 +	else +		apply_theme +		exit 0 +	fi +fi + +case "$1" in +	--dark|--light) +		filterFlag=$1 +		shift +		;; +esac + +case "$1" in +-h|--help) +		cat << "!" +usage: theme.sh [--light] | [--dark] <option> | <theme> + +  If <theme> is provided it will immediately be set. Otherwise --dark or +  --light optionally act as filters on the supplied option. Theme history is +  stored in ~/.theme_history or ($XDG_CONFIG_HOME/.theme_history if set) by +  default and will be used for ordering the otherwise alphabetical theme list +  in the relevant options (-l/-i/-i2). + +  E.G: +    'theme.sh --dark -i' + +  will start an interactive selection of dark themes with the user's +  most recently selected themes at the bottom of the list. + +  Theme definitions consistent with the internal format can also be piped +  directly into the script. + +  E.G: + +  # theme.sh < input + +  Where input has the form: + +      0: #4d4d4d +      1: #4d4d4d +      ... +      foreground: #dcdccc +      background: #3f3f3f +      cursor: #dcdccc + +OPTIONS +  -l,--list                 Print all available themes. +  -i,--interactive          Start the interactive selection mode (requires fzf). +  -i2,--interactive2        Interactive mode #2. This shows the theme immediately +                            instead of showing it in the preview window. Useful +			    if your terminal does have TRUECOLOR support. +  -r,--random               Set a random theme and print its name to stdout. +  -a,--add <kitty config>   Annexes the given kitty config file. +  -p,--print-theme          Attempt to read the current theme from the terminal +                            and print it to stdout in a format consumable by theme.sh. +                            NOTE: not all terminals support this option, +		            do not rely on it in scripts. +  -v,--version              Print the version and exit. + +SCRIPTING +  If used from within a script, you will probably want to set +  INHIBIT_THEME_HIST=1 to avoid mangling the user's theme history. +! +	;; +-p|--print-theme) +	print_current_theme +	;; +-i2|--interactive2) +	command -v fzf > /dev/null 2>&1 || { echo "ERROR: -i requires fzf" >&2; exit 1; } +	"$0" $filterFlag -l|fzf\ +		--tac\ +		--bind "enter:execute-silent($0 {})+accept"\ +		--bind "ctrl-c:execute($0 -l|tail -n1|xargs $0)+abort"\ +		--bind "esc:execute($0 {};echo {})+abort"\ +		--exact\ +		--no-sort\ +		--preview "$0 --preview2 {}" +	;; +-r|--random) +	# Sort -R is not portable :/ + +	theme=$($0 $filterFlag -l|awk '{a[n++]=$0};END{srand();print(a[int(rand()*n)])}') +	$0 "$theme" +	echo "Theme: $theme" +	;; +-i|--interactive) +	command -v fzf > /dev/null 2>&1 || { echo "ERROR: -i requires fzf" >&2; exit 1; } +	if ! isColorTerm; then +		printf "WARNING: This does not appear to be a truecolor terminal, falling back to -i2 +         (use -i2 explicitly to get rid of this message or set COLORTERM)\n\n" >&2 +		"$0" $filterFlag -i2 +	else +		"$0" $filterFlag -l|fzf\ +			--tac\ +			--exact\ +			--bind "ctrl-c:abort"\ +			--bind "esc:execute(echo {})+abort"\ +			--bind "enter:execute-silent($0 {})+accept"\ +			--no-sort\ +			--preview "$0 --preview {}" +	fi +	;; +-l|--list) +	list +	;; +-a|--add) +	shift +	add "$@" +	;; +--preview2) +	preview2 "$2" +	;; +--preview) +	preview "$2" +	;; +-v|--version) +	echo "$VERSION (original source https://github.com/lemnos/theme.sh)" +	;; +*) +	set_current_theme "$1" +	;; +esac + +exit $? + +# Themes start here (avoid editing by hand) + +ultramar-dark +0: #33333a +1: #b73030 +2: #6d974b +3: #b2872f +4: #3f6e90 +5: #9c6992 +6: #5b8277 +7: #b0afa8 +8: #676775 +9: #c45c5c +10: #92b078 +11: #e2b55a +12: #81acc1 +13: #b48ead +14: #7fac96 +15: #faf6e5 +foreground: #fcf8e2 +background: #151517 +cursor: #ffffff + +ultramar-light +0: #151517 +1: #b73030 +2: #6d974b +3: #b2872f +4: #3f6e90 +5: #9c6992 +6: #5b8277 +7: #91908d +8: #33333a +9: #c45c5c +10: #92b078 +11: #e2b55a +12: #75a2b8 +13: #b48ead +14: #7fac96 +15: #b0afa8 +foreground: #1b1e25 +background: #faf6e5 +cursor: #000000 + diff --git a/dotfiles/.profile b/dotfiles/.profile index 0627bdd..320c1ae 100644 --- a/dotfiles/.profile +++ b/dotfiles/.profile @@ -44,7 +44,7 @@ export $(dbus-launch)  # Start sway automatically upon login on tty1 or tty2  if [ -z $DISPLAY ] && [ $(tty) = /dev/tty1 ] || [ $(tty) = /dev/tty2 ]; then    # DBUS variables (for Artix) -  sway -d 2> ~/.cache/sway.log 1> /dev/null && clear && exit +  exec sway -d 2> ~/.cache/sway.log 1> /dev/null && clear && exit    mv ~/.cache/sway.log ~/.cache/sway-crash-$(date +"%Y-%m-%dT%H:%M").log  fi | 
