From 4224ea09b4706ac3c62013531a874676b64fbf5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Recai=20Okta=C5=9F?= Date: Fri, 1 Mar 2024 20:09:21 +0300 Subject: [PATCH] Initial commit --- .editorconfig | 6 + .github/workflows/lint.yml | 14 + .gitignore | 2 + .luacheckrc | 3 + .rubocop.yml | 81 +++ .shellcheckrc | 3 + LICENSE | 24 + README.md | 5 + Vagrantfile | 8 + alacritty/alacritty.yml | 134 +++++ alacritty/install.sh | 9 + bash/bashrc | 236 ++++++++ bash/install.sh | 5 + bat/config | 2 + bat/install.sh | 9 + biome/bin/biome-kludge | 96 ++++ biome/biome.json | 12 + biome/install.sh | 13 + bun/bunfig.toml | 10 + bun/install.sh | 9 + bundle/Gemfile | 20 + bundle/bin/bundle-kludge | 184 ++++++ bundle/install.sh | 15 + deinstall.sh | 51 ++ direnv/direnvrc | 57 ++ direnv/install.sh | 9 + dropbox/install.sh | 8 + eslint/eslintrc | 21 + eslint/install.sh | 5 + fish/config.fish | 137 +++++ fish/functions/fundle.fish | 462 +++++++++++++++ fish/functions/mc.fish | 19 + fish/install.sh | 15 + fzf/bin/search | 18 + fzf/install.sh | 7 + gh/config.yml | 14 + gh/install.sh | 9 + git/bin/git-. | 3 + git/bin/git-.. | 3 + git/bin/git-renew | 81 +++ git/config | 62 ++ git/hooks/commit-msg | 49 ++ git/hooks/pre-commit | 31 + git/hooks/pre-push | 33 ++ git/ignore | 29 + git/install.sh | 15 + gnome/bin/background | 25 + gnome/install.sh | 40 ++ install.sh | 42 ++ irb/install.sh | 9 + irb/irbrc | 4 + markdownlint/install.sh | 5 + markdownlint/markdownlintrc | 22 + mc/install.sh | 16 + mc/mc.ini | 17 + mc/mc.keymap | 6 + mc/menu | 383 +++++++++++++ mc/skins/nord.ini | 175 ++++++ neomutt/install.sh | 9 + neomutt/muttrc | 102 ++++ npm/install.sh | 8 + nvim/init.lua | 1070 +++++++++++++++++++++++++++++++++++ nvim/install.sh | 11 + pylint/install.sh | 9 + pylint/pylintrc | 7 + rubocop/config.yml | 57 ++ rubocop/install.sh | 9 + terminal.png | Bin 0 -> 16642 bytes tmux/bin/editor | 4 + tmux/bin/viewer | 4 + tmux/install.sh | 13 + tmux/tmux.conf | 78 +++ todo/actions/e | 1 + todo/actions/edit | 16 + todo/actions/n | 1 + todo/actions/note | 3 + todo/actions/pr | 1 + todo/actions/projectview | 81 +++ todo/actions/r | 1 + todo/actions/revive | 61 ++ todo/actions/wtf | 5 + todo/actions/xp | 59 ++ todo/config | 100 ++++ todo/install.sh | 10 + vifm/install.sh | 9 + vifm/vifmrc | 510 +++++++++++++++++ vscode/install.sh | 17 + vscode/settings.json | 25 + wezterm/install.sh | 9 + wezterm/wezterm.lua | 275 +++++++++ zsh/install.sh | 5 + zsh/zshrc | 309 ++++++++++ 92 files changed, 5661 insertions(+) create mode 100644 .editorconfig create mode 100644 .github/workflows/lint.yml create mode 100644 .gitignore create mode 100644 .luacheckrc create mode 100644 .rubocop.yml create mode 100644 .shellcheckrc create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Vagrantfile create mode 100644 alacritty/alacritty.yml create mode 100644 alacritty/install.sh create mode 100644 bash/bashrc create mode 100644 bash/install.sh create mode 100644 bat/config create mode 100644 bat/install.sh create mode 100755 biome/bin/biome-kludge create mode 100644 biome/biome.json create mode 100644 biome/install.sh create mode 100644 bun/bunfig.toml create mode 100644 bun/install.sh create mode 100644 bundle/Gemfile create mode 100755 bundle/bin/bundle-kludge create mode 100644 bundle/install.sh create mode 100644 deinstall.sh create mode 100644 direnv/direnvrc create mode 100644 direnv/install.sh create mode 100644 dropbox/install.sh create mode 100644 eslint/eslintrc create mode 100644 eslint/install.sh create mode 100644 fish/config.fish create mode 100644 fish/functions/fundle.fish create mode 100644 fish/functions/mc.fish create mode 100644 fish/install.sh create mode 100755 fzf/bin/search create mode 100644 fzf/install.sh create mode 100644 gh/config.yml create mode 100644 gh/install.sh create mode 100755 git/bin/git-. create mode 100755 git/bin/git-.. create mode 100755 git/bin/git-renew create mode 100644 git/config create mode 100755 git/hooks/commit-msg create mode 100755 git/hooks/pre-commit create mode 100755 git/hooks/pre-push create mode 100644 git/ignore create mode 100644 git/install.sh create mode 100755 gnome/bin/background create mode 100644 gnome/install.sh create mode 100644 install.sh create mode 100644 irb/install.sh create mode 100644 irb/irbrc create mode 100644 markdownlint/install.sh create mode 100644 markdownlint/markdownlintrc create mode 100644 mc/install.sh create mode 100644 mc/mc.ini create mode 100644 mc/mc.keymap create mode 100644 mc/menu create mode 100644 mc/skins/nord.ini create mode 100644 neomutt/install.sh create mode 100644 neomutt/muttrc create mode 100644 npm/install.sh create mode 100644 nvim/init.lua create mode 100644 nvim/install.sh create mode 100644 pylint/install.sh create mode 100644 pylint/pylintrc create mode 100644 rubocop/config.yml create mode 100644 rubocop/install.sh create mode 100644 terminal.png create mode 100755 tmux/bin/editor create mode 100755 tmux/bin/viewer create mode 100644 tmux/install.sh create mode 100644 tmux/tmux.conf create mode 120000 todo/actions/e create mode 100755 todo/actions/edit create mode 120000 todo/actions/n create mode 100755 todo/actions/note create mode 120000 todo/actions/pr create mode 100755 todo/actions/projectview create mode 120000 todo/actions/r create mode 100755 todo/actions/revive create mode 100755 todo/actions/wtf create mode 100755 todo/actions/xp create mode 100644 todo/config create mode 100644 todo/install.sh create mode 100644 vifm/install.sh create mode 100644 vifm/vifmrc create mode 100644 vscode/install.sh create mode 100644 vscode/settings.json create mode 100644 wezterm/install.sh create mode 100644 wezterm/wezterm.lua create mode 100644 zsh/install.sh create mode 100644 zsh/zshrc diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..48cdcb2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +[*.lua] +indent_style = tab +tab_width = 8 +quote_style = double +max_line_length = 140 + diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..24ac70d --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,14 @@ +name: Lint +on: [push, pull_request, workflow_dispatch] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Install πŸ₯ + run: sudo apt-get -y update && sudo apt-get -y install shellcheck + - name: Checkout πŸ›ŽοΈ + uses: actions/checkout@v4 + - name: Lint Shell πŸ”¬ + run: shellcheck $(find . -name '*.sh') + - name: Lint Lua πŸ”¬ + uses: lunarmodules/luacheck@v1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..18fc4d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.vagrant*/ +/.local/ diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..35ee643 --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,3 @@ +std = "luajit" +globals = { "vim" } +max_line_length = 140 diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..698eadc --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,81 @@ +inherit_gem: + rubocop-shopify: rubocop.yml + +require: + - "rubocop-md" + - "rubocop-minitest" + - "rubocop-packaging" + - "rubocop-performance" + - "rubocop-rake" + +Layout/ExtraSpacing: + Exclude: + - "**/lib/sevgi/standard/**/*.rb" + - "**/test/**/*.rb" +Layout/HashAlignment: + Enabled: true + EnforcedHashRocketStyle: table + EnforcedColonStyle: table +Layout/LineLength: + Max: 140 + Exclude: + - "**/test/**/*.rb" +Layout/MultilineArrayLineBreaks: + Exclude: + - "**/test/**/*.rb" +Layout/MultilineMethodArgumentLineBreaks: + Exclude: + - "**/test/**/*.rb" +Layout/MultilineOperationIndentation: + Enabled: false + +Metrics/BlockLength: + Exclude: + - "**/test/**/*.rb" + - "*.gemspec" +Metrics/ClassLength: + Exclude: + - "**/test/**/*.rb" +Metrics/MethodLength: + Exclude: + - "**/test/**/*.rb" + +Naming/MethodName: + Enabled: false + +Minitest/UselessAssertion: + Exclude: + - "**/test/test_common.rb" # TODO: to avoid a bug + +Style/AsciiComments: + Enabled: false +Style/ClassAndModuleChildren: + Exclude: + - "**/test/**/*.rb" +Style/Documentation: + Enabled: false +Style/LambdaCall: + Enabled: false +Style/MethodCallWithArgsParentheses: + Exclude: + - "**/test/**/*.rb" +Style/ParallelAssignment: + Enabled: false +Style/SymbolArray: + Exclude: + - "**/lib/sevgi/standard/**/*.rb" + - "**/test/**/*.rb" +Style/SymbolLiteral: + Exclude: + - "**/lib/sevgi/standard/**/*.rb" + - "**/test/**/*.rb" +Style/TrailingCommaInArguments: + Exclude: + - "**/test/**/*.rb" + +AllCops: + NewCops: enable + Exclude: + - "vendor/**/*" + - "_/**/*" + - "**/_/**/*" diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..acfd298 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,3 @@ +disable=SC1090 +disable=SC1091 +disable=SC2154 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/README.md b/README.md new file mode 100644 index 0000000..65406f8 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +

+ +
+ Neovim on Fish on WezTerm with Nord color theme +

diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..231b915 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,8 @@ +Vagrant.configure("2") do |config| + config.vm.box = "roktas/debian" + + config.vm.provision "shell", privileged: false, inline: <<~EOF + bash /vagrant/deinstall.sh + bash /vagrant/install.sh + EOF +end diff --git a/alacritty/alacritty.yml b/alacritty/alacritty.yml new file mode 100644 index 0000000..f5ff6c4 --- /dev/null +++ b/alacritty/alacritty.yml @@ -0,0 +1,134 @@ +scrolling: + history: 10000 + multiplier: 3 + +font: + normal: + family: Spleen 32x64 + style: Regular + size: 16 + +draw_bold_text_with_bright_colors: true + +selection: + semantic_escape_chars: ",β”‚`|:\"' ()[]{}<>\t" + +cursor: + unfocused_hollow: true + +live_config_reload: true + +shell: + program: /usr/bin/env + args: + - "tmux" + - "-u" + +mouse: + hide_when_typing: false + +mouse_bindings: + - {mouse: Middle, action: PasteSelection} + +key_bindings: + - {key: F11, action: ToggleFullscreen} + + - {key: Left, mods: Shift, action: ResetFontSize} + - {key: Up, mods: Shift, action: IncreaseFontSize} + + - {key: Down, mods: Shift, action: DecreaseFontSize} + - {key: Left, mods: Control, action: ResetFontSize} + + - {key: Up, mods: Control, action: IncreaseFontSize} + - {key: Up, mods: Control, action: IncreaseFontSize} + - {key: Up, mods: Control, action: IncreaseFontSize} + - {key: Up, mods: Control, action: IncreaseFontSize} + - {key: Up, mods: Control, action: IncreaseFontSize} + - {key: Up, mods: Control, action: IncreaseFontSize} + - {key: Up, mods: Control, action: IncreaseFontSize} + - {key: Up, mods: Control, action: IncreaseFontSize} + - {key: Up, mods: Control, action: IncreaseFontSize} + - {key: Up, mods: Control, action: IncreaseFontSize} + + - {key: Down, mods: Control, action: DecreaseFontSize} + - {key: Down, mods: Control, action: DecreaseFontSize} + - {key: Down, mods: Control, action: DecreaseFontSize} + - {key: Down, mods: Control, action: DecreaseFontSize} + - {key: Down, mods: Control, action: DecreaseFontSize} + - {key: Down, mods: Control, action: DecreaseFontSize} + - {key: Down, mods: Control, action: DecreaseFontSize} + - {key: Down, mods: Control, action: DecreaseFontSize} + - {key: Down, mods: Control, action: DecreaseFontSize} + - {key: Down, mods: Control, action: DecreaseFontSize} + +# Copyright (c) 2017-present Arctic Ice Studio +# Copyright (c) 2017-present Sven Greb + +# Project: Nord Alacritty +# Version: 0.1.0 +# Repository: https://github.com/arcticicestudio/nord-alacritty +# License: MIT +# References: +# https://github.com/alacritty/alacritty + +colors: + primary: + background: '#2e3440' + foreground: '#d8dee9' + dim_foreground: '#a5abb6' + cursor: + text: '#2e3440' + cursor: '#d8dee9' + vi_mode_cursor: + text: '#2e3440' + cursor: '#d8dee9' + selection: + text: CellForeground + background: '#4c566a' + search: + matches: + foreground: CellBackground + background: '#88c0d0' + footer_bar: + background: '#434c5e' + foreground: '#d8dee9' + normal: + black: '#3b4252' + red: '#bf616a' + green: '#a3be8c' + yellow: '#ebcb8b' + blue: '#81a1c1' + magenta: '#b48ead' + cyan: '#88c0d0' + white: '#e5e9f0' + bright: + black: '#4c566a' + red: '#bf616a' + green: '#a3be8c' + yellow: '#ebcb8b' + blue: '#81a1c1' + magenta: '#b48ead' + cyan: '#8fbcbb' + white: '#eceff4' + dim: + black: '#373e4d' + red: '#94545d' + green: '#809575' + yellow: '#b29e75' + blue: '#68809a' + magenta: '#8c738c' + cyan: '#6d96a5' + white: '#aeb3bb' + +window: + dimensions: + columns: 124 + lines: 40 + padding: + x: 2 + y: 2 + # startup_mode: Fullscreen + #gtk_theme_variant: Dark + +env: + WINIT_X11_SCALE_FACTOR: '1.0' diff --git a/alacritty/install.sh b/alacritty/install.sh new file mode 100644 index 0000000..60a54ae --- /dev/null +++ b/alacritty/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/alacritty + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/alacritty.yml -t "$config" +} diff --git a/bash/bashrc b/bash/bashrc new file mode 100644 index 0000000..0b050d3 --- /dev/null +++ b/bash/bashrc @@ -0,0 +1,236 @@ +# shellcheck disable=1091,2148,2155 + +# Some parts are adapted from https://github.com/mrzool/bash-sensible +[[ -n ${PS1:-} ]] || return + +# ---------------------------------------------------------------------------------------------------------------------- +# Settings +# ---------------------------------------------------------------------------------------------------------------------- + +case :$PATH: in *:"$HOME"/.local/bin:*) export PATH=$HOME/.local/bin:$PATH ;; esac +case :$PATH: in *:"$HOME"/Dropbox/bin:*) export PATH=$HOME/Dropbox/bin:$PATH ;; esac + +export SHELL=$(command -v bash) + +HISTSIZE=500000 +HISTFILESIZE=100000 +HISTCONTROL='erasedups:ignoreboth' +HISTTIMEFORMAT='%F %T ' +HISTIGNORE='&:[ ]*:exit:ls:bg:fg:history:clear'; export HISTIGNORE + +shopt -s autocd +shopt -s cdspell +shopt -s checkwinsize +shopt -s cmdhist +shopt -s dirspell +shopt -s globstar +shopt -s histappend +shopt -s nocaseglob +shopt -s no_empty_cmd_completion + +# ---------------------------------------------------------------------------------------------------------------------- +# Bindings +# ---------------------------------------------------------------------------------------------------------------------- + +bind '"\eq":"\C-d"' +bind '"\e[A": history-search-backward' +bind '"\e[B": history-search-forward' +bind '"\e[C": forward-char' +bind '"\e[D": backward-char' +bind 'set completion-ignore-case on' +bind 'set completion-map-case on' +bind 'set mark-symlinked-directories on' +bind 'set show-all-if-ambiguous on' + +# ---------------------------------------------------------------------------------------------------------------------- +# Portability +# ---------------------------------------------------------------------------------------------------------------------- + +case $OSTYPE in +linux*) + XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-/run/user/${EUID:-$(id -u)}} + + if command -v dircolors &>/dev/null; then + if [[ -r ~/.dircolors ]]; then + eval "$(dircolors -b ~/.dircolors)" + else + eval "$(dircolors -b)" + fi + fi + + alias ls='ls --color=auto' + ;; +darwin*) + XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-"$HOME"/Library/Caches/TemporaryItems} + + alias ls='ls -G' + alias readlink=greadlink + ;; +esac + +# ---------------------------------------------------------------------------------------------------------------------- +# Completion +# ---------------------------------------------------------------------------------------------------------------------- + +# shellcheck disable=1091 +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 + +# ---------------------------------------------------------------------------------------------------------------------- +# Prompt +# ---------------------------------------------------------------------------------------------------------------------- + +# shellcheck disable=2034 +declare -Ag ansi_colors_256=( + [black]='\e[1m\e[38;5;8m' + [blue]='\e[1m\e[38;5;12m' + [cyan]='\e[1m\e[38;5;14m' + [green]='\e[1m\e[38;5;10m' + [grey]='\e[1m\e[38;5;8m' + [magenta]='\e[1m\e[38;5;13m' + [red]='\e[1m\e[38;5;9m' + [white]='\e[1m\e[38;5;15m' + [yellow]='\e[1m\e[38;5;11m' + + [null]='\e[0m' +) + +prompt_command() { + local last_exit_code=$? + + if ! [[ $PWD == "$HOME" ]]; then + local pwd=${PWD/#$HOME/\~}; local slug=${pwd##*/} dir=${pwd%/*}/ + else + local slug='~' dir='' + fi + + local char='>'; [[ ${EUID:-} -ne 0 ]] || char='#' + + local -n c=ansi_colors_256 + c[char]=${c[yellow]}; [[ $last_exit_code -eq 0 ]] || c[char]=${c[red]} + + PS1="\[${c[grey]}\]${dir}\[${c[null]}\]\[${c[cyan]}\]${slug}\[${c[null]}\] \[${c[char]}\]${char}\[${c[null]}\] " +} +export PROMPT_COMMAND=prompt_command + +# ---------------------------------------------------------------------------------------------------------------------- +# Aliases and/or Functions +# ---------------------------------------------------------------------------------------------------------------------- + +alias ...='cd $(git rev-parse --show-toplevel)' + +alias a=apt +alias A='sudo apt' + +b() { + local cmd=$1 + shift + + if [[ -z $cmd ]] && [[ ! -f .envrc ]]; then + echo "layout ruby" >.envrc + sleep 0.1 + direnv allow . + + return + fi + + case $cmd in + i) bundle install "$@" ;; + u) bundle update "$@" ;; + e) bundle exec "$@" ;; + c) bundle config "$@" ;; + *) bundle "$@" ;; + esac +} + +alias e=nvim +alias E='sudo nvim' + +alias g=git + +alias j='journalctl --user --unit' +alias J='sudo journalctl' + +alias s='systemctl --user' +alias S='sudo systemctl' + +alias t='todo.sh -t' +alias T='todo.sh' + +alias w='journalctl --user --follow --unit' +alias W='sudo journalctl --user --follow --unit' + +alias egrep='egrep --color=auto' +alias fgrep='fgrep --color=auto' +alias grep='grep --color=auto' + +# ---------------------------------------------------------------------------------------------------------------------- +# External +# ---------------------------------------------------------------------------------------------------------------------- + +# Command not found +if [[ -x /usr/lib/command-not-found ]] || [[ -x /usr/share/command-not-found/command-not-found ]]; then + command_not_found_handle() { + if [[ -x /usr/lib/command-not-found ]]; then + /usr/lib/command-not-found -- "$1" + return $? + elif [[ -x /usr/share/command-not-found/command-not-found ]]; then + /usr/share/command-not-found/command-not-found -- "$1" + return $? + else + printf "%s: command not found\n" "$1" >&2 + return 127 + fi + } +fi + +# Direnv +command -v direnv &>/dev/null && eval "$(direnv hook bash)" + +# Fzf +[[ -f /usr/share/doc/fzf/examples/key-bindings.bash ]] && source /usr/share/doc/fzf/examples/key-bindings.bash +[[ -f /usr/share/doc/fzf/examples/completion.bash ]] && source /usr/share/doc/fzf/examples/completion.bash + + +# Midnight Commander +mc() { + local -i err=0 + local file=$XDG_RUNTIME_DIR/mc + + COLORTERM=truecolor /usr/bin/mc -P "$file" "$@" || err=$? + + if [ -r "$file" ]; then + dir=$(cat "$file") + if [ -n "$dir" ] && [ -d "$dir" ] && [ ! "$dir" = "$PWD" ]; then + cd "$dir" || err=$? + fi + fi + + rm -f "$file" + + return $err +} + +# Zoxide +command -v zoxide &>/dev/null && eval "$(zoxide init bash)" + +# ---------------------------------------------------------------------------------------------------------------------- +# Customization +# ---------------------------------------------------------------------------------------------------------------------- + +if [[ -d ${XDG_CONFIG_HOME:-$HOME/.config}/bash ]]; then + if [[ -d ${XDG_CONFIG_HOME:-$HOME/.config}/bash/conf.d ]]; then + for f in "${XDG_CONFIG_HOME:-$HOME/.config}"/bash/conf.d/*.sh; do + builtin source "$f" + done + + unset f + fi + + if [[ -f ${XDG_CONFIG_HOME:-$HOME/.config}/bash/config.sh ]]; then + builtin source "${XDG_CONFIG_HOME:-$HOME/.config}"/bash/config.sh + fi +fi diff --git a/bash/install.sh b/bash/install.sh new file mode 100644 index 0000000..d927c0b --- /dev/null +++ b/bash/install.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +ln -sf "$PWD"/bashrc "$HOME"/.bashrc diff --git a/bat/config b/bat/config new file mode 100644 index 0000000..6142f12 --- /dev/null +++ b/bat/config @@ -0,0 +1,2 @@ +--theme="Nord" +--style=plain,header diff --git a/bat/install.sh b/bat/install.sh new file mode 100644 index 0000000..1903ff3 --- /dev/null +++ b/bat/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/bat + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/config -t "$config" +} diff --git a/biome/bin/biome-kludge b/biome/bin/biome-kludge new file mode 100755 index 0000000..0dfb4c7 --- /dev/null +++ b/biome/bin/biome-kludge @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail; shopt -s nullglob; unset CDPATH; IFS=$' \t\n'; [[ -z ${TRACE:-} ]] || set -x +export LC_ALL=C.UTF-8 LANG=C.UTF-8 + +KLUDGE_CONFIG_PATH=${XGD_CONFIG_HOME:-$HOME/.config}/biome +KLUDGE_CONFIG_FILE=biome.json + +# ---------------------------------------------------------------------------------------------------------------------- +# Functions +# ---------------------------------------------------------------------------------------------------------------------- + +abort() { + warn "$@" + exit 1 +} + +locate() { + local cwd=${1?${FUNCNAME[0]}: missing argument}; shift + + local err=0; local root; root=$( + [[ -z $cwd ]] || cd "$cwd" || exit + + while :; do + local try + + for try; do + if [[ -e $try ]]; then + echo "$PWD" + exit 0 + fi + done + + # shellcheck disable=2128 + if [[ $PWD == "/" ]]; then + break + fi + + cd .. || exit + done + + exit 1 + ) || err=$? + + if [[ $err -eq 0 ]] && [[ -n ${root:-} ]]; then + echo "$root" + return 0 + fi + + return 1 +} + +warn() { + echo "kludge: $*" >&2 +} + +# ---------------------------------------------------------------------------------------------------------------------- +# Main +# ---------------------------------------------------------------------------------------------------------------------- + +main() { + command -v biome &>/dev/null || abort "Biome required" + + local -a args=() + + if ! locate "$KLUDGE_CONFIG_FILE" &>/dev/null && [[ -f "$KLUDGE_CONFIG_PATH"/"$KLUDGE_CONFIG_FILE" ]]; then + while [[ $# -gt 0 ]]; do + case "${1:-}" in + -*) + args+=("$1") + shift + ;; + *) + break + ;; + esac + done + + case "${1:-}" in + stop) + args+=("$1") + shift + ;; + "") + ;; + *) + args+=("$1" --config-path "$KLUDGE_CONFIG_PATH") + shift + ;; + esac + fi + + exec biome "${args[@]}" "$@" +} + +main "$@" diff --git a/biome/biome.json b/biome/biome.json new file mode 100644 index 0000000..beacc18 --- /dev/null +++ b/biome/biome.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.2.2/schema.json", + "formatter": { + "indentStyle": "space", + "lineWidth": 120 + }, + "javascript": { + "formatter": { + "semicolons": "asNeeded" + } + } +} diff --git a/biome/install.sh b/biome/install.sh new file mode 100644 index 0000000..cac2683 --- /dev/null +++ b/biome/install.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/biome + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/biome.json -t "$config" +} + +install -d "$HOME"/.local/bin && { + find "$PWD"/bin -executable -type f -print0 | xargs -0 ln -t "$HOME"/.local/bin -sf +} diff --git a/bun/bunfig.toml b/bun/bunfig.toml new file mode 100644 index 0000000..57ea4cd --- /dev/null +++ b/bun/bunfig.toml @@ -0,0 +1,10 @@ +[install] +globalDir = "~/.cache/bun/install/global" +globalBinDir = "~/.local/bin" + +[install.cache] +dir = "~/.cache/bun/install/cache" + +[install.lockfile] +path = ".cache/bun/bun.lockb" +savePath = ".cache/bun/bun.lockb" diff --git a/bun/install.sh b/bun/install.sh new file mode 100644 index 0000000..01a7c09 --- /dev/null +++ b/bun/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config} + +install -d "$config" && { + ln -sf "$PWD"/bunfig.toml "$config"/.bunfig.toml +} diff --git a/bundle/Gemfile b/bundle/Gemfile new file mode 100644 index 0000000..bdb4c9c --- /dev/null +++ b/bundle/Gemfile @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +if File.exist?(file = File.expand_path(".ruby-version", __dir__)) + ruby File.read(file).strip +end + +gem "bundler" +gem "debug", platforms: :mri +gem "minitest" +gem "minitest-focus" +gem "minitest-reporters" +gem "rake" +gem "rubocop-md" +gem "rubocop-packaging" +gem "rubocop-rake" +gem "rubocop-rails-omakase" +gem "ruby-lsp" +gem "rubygems-tasks" diff --git a/bundle/bin/bundle-kludge b/bundle/bin/bundle-kludge new file mode 100755 index 0000000..be92cad --- /dev/null +++ b/bundle/bin/bundle-kludge @@ -0,0 +1,184 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail; shopt -s nullglob; unset CDPATH; IFS=$' \t\n'; [[ -z ${TRACE:-} ]] || set -x +export LC_ALL=C.UTF-8 LANG=C.UTF-8 + +KLUDGE_PROGNAME=${0##*/} +KLUDGE_CONFIG=${XGD_CONFIG_HOME:-$HOME/.config}/bundle +KLUDGE_STATE=${XDG_STATE_HOME:-$HOME/.local/state}/bundle + +# ---------------------------------------------------------------------------------------------------------------------- +# Functions +# ---------------------------------------------------------------------------------------------------------------------- + +abort() { + warn "$@" + exit 1 +} + +kludge() { + [[ ! -f $KLUDGE_CONFIG/environment ]] || builtin source "$KLUDGE_CONFIG"/environment + + export GEM_HOME=$KLUDGE_STATE + export BUNDLE_GEMFILE=$KLUDGE_STATE/Gemfile + export BUNDLE_APP_CONFIG=$KLUDGE_STATE + export BUNDLE_BIN=$KLUDGE_STATE/bin + + export PATH=$BUNDLE_BIN:$PATH +} + +gemfile() { + if [[ -f $KLUDGE_CONFIG/Gemfile ]]; then + cat "$KLUDGE_CONFIG"/Gemfile + + return 0 + fi + + cat <<-'EOF' + source "https://rubygems.org" + + if File.exist?(file = File.expand_path(".ruby-version", __dir__)) + ruby File.read(file).strip + end + + group :development do + gem "debug", platforms: :mri + gem "rubocop" + gem "rubocop-minitest" + gem "rubocop-packaging" + gem "rubocop-performance" + gem "rubocop-rake" + gem "ruby-lsp" + end + EOF +} + +gemfiled() { + [[ -n ${BUNDLE_GEMFILE:-} ]] || locate "$PWD" Gemfile &>/dev/null +} + +locate() { + local cwd=${1?${FUNCNAME[0]}: missing argument}; shift + + local err=0; local root; root=$( + [[ -z $cwd ]] || cd "$cwd" || exit + + while :; do + local try + + for try; do + if [[ -e $try ]]; then + echo "$PWD" + exit 0 + fi + done + + # shellcheck disable=2128 + if [[ $PWD == "/" ]]; then + break + fi + + cd .. || exit + done + + exit 1 + ) || err=$? + + if [[ $err -eq 0 ]] && [[ -n ${root:-} ]]; then + echo "$root" + return 0 + fi + + return 1 +} + +ruby-version() { + local dir + + for dir in "${KLUDGE_CONFIG}" "${XDG_CONFIG_HOME:-$HOME/.config}"/rubocop; do + local file=$dir/ruby-version + + if [[ -f $file ]]; then + cat "$file" + + return 0 + fi + done + + ruby -e "puts RUBY_VERSION" +} + +warn() { + echo "$KLUDGE_PROGNAME: $*" >&2 +} + +# ---------------------------------------------------------------------------------------------------------------------- +# Commands +# ---------------------------------------------------------------------------------------------------------------------- + +bexec.destroy() { + rm -rf "$KLUDGE_STATE" +} + +bexec.init() { + rm -rf "$KLUDGE_STATE" && mkdir -p "$KLUDGE_STATE" + + kludge + + pushd "$KLUDGE_STATE" &>/dev/null + + ruby-version >.ruby-version + gemfile >Gemfile + + bundle install --jobs=4 + + popd &>/dev/null +} + +bexec.update() { + if [[ -f $KLUDGE_STATE/Gemfile.lock ]]; then + kludge + + pushd "$KLUDGE_STATE" &>/dev/null && bundle update --all --jobs=4 && popd &>/dev/null + else + bexec.init + fi +} + +# ---------------------------------------------------------------------------------------------------------------------- +# Main +# ---------------------------------------------------------------------------------------------------------------------- + +main() { + command -v bundle &>/dev/null || abort "A valid Ruby development environment with bundler required" + + case "${1:-}" in + --*|-*) + case $1 in + -i|-ini|-init|--init) + bexec.init + ;; + -u|-up|-update|--update) + bexec.update + ;; + -d|-destroy|--destroy) + bexec.destroy + ;; + *) + abort "Unrecognized maintenance option: $1" + ;; + esac + ;; + *) + if [[ -z ${NO_KLUDGE:-} ]]; then + [[ -d "$KLUDGE_STATE" ]] || bexec.init + + gemfiled || kludge + fi + + exec bundle "$@" + ;; + esac +} + +main "$@" diff --git a/bundle/install.sh b/bundle/install.sh new file mode 100644 index 0000000..191fb2f --- /dev/null +++ b/bundle/install.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/bundle + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/Gemfile -t "$config" +} + +install -d "$HOME"/.local/bin && { + find "$PWD"/bin -executable -type f -print0 | xargs -0 ln -t "$HOME"/.local/bin -sf +} + +bin/bundle-kludge -i || true diff --git a/deinstall.sh b/deinstall.sh new file mode 100644 index 0000000..ed37acc --- /dev/null +++ b/deinstall.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +cry() { echo -e "$*" >&2; } +die() { cry "$@"; exit 1; } + +[[ ${EUID:-} -gt 0 ]] || die "You must not be root." + +share=$(readlink -m "${XDG_DATA_HOME:-$HOME/.local/share}/dotfiles") +dropbox=$(readlink -m "$HOME"/Dropbox) +vagrant=$(readlink -m /vagrant) + +# Deactive linked services if any +systemd=${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user +if [[ -d $systemd ]]; then + while read -r link; do + case $(readlink -f "$link") in + "$share"/*.service|"$dropbox"/*.service|"$vagrant"/*.service) + service=$(basename "$link") + + cry "... Deactivating service: $service" + + systemctl stop --user "$service" || true + systemctl disable --user "$service" || true + + need_daemon_reload=t + ;; + esac + done < <(find "$systemd" -maxdepth 1 -type l) +fi + +# Unlink dotfiles (excluding the ones in Dropbox) +cry "... Unlinking dotfiles" +while read -r link; do + case $(readlink -f "$link") in + "$share"/*|"$dropbox"/*|"$vagrant"/*) + [[ -z ${VERBOSE:-} ]] || cry " $link" + + rm -f "$link" + ;; + esac +done < <(find "$HOME" -type l \( -not -path ''"$dropbox"'/*' \)) + +# Perform daemon reload if deactivating occurs +if [[ -n ${need_daemon_reload:-} ]]; then + cry "... Reloading daemon" + + systemctl --user daemon-reload || true + systemctl --user reset-failed || true +fi diff --git a/direnv/direnvrc b/direnv/direnvrc new file mode 100644 index 0000000..fdd3fd9 --- /dev/null +++ b/direnv/direnvrc @@ -0,0 +1,57 @@ +# shellcheck shell=bash + +export DIRENV_WARN_TIMEOUT=10s + +export LOCAL_CACHE_ROOT=${XDG_CACHE_DIR:-$HOME/.cache}/_ +[[ -d $LOCAL_CACHE_ROOT ]] || mkdir -p "$LOCAL_CACHE_ROOT" + +local_cache_dir() { + local dir=${1:-$PWD} + + echo "$LOCAL_CACHE_ROOT"/"${dir//\//+}" +} + +direnv_layout_dir() { + echo "${direnv_layout_dir:-$PWD/.local/opt}" +} + +use-() { + export NO_KLUDGE=true + + use "$@" +} + +# ---------------------------------------------------------------------------------------------------------------------- +# Vagrant +# ---------------------------------------------------------------------------------------------------------------------- + +layout_vagrant() { + VAGRANT_DOTFILE_PATH="$(local_cache_dir)"/vagrant + export VAGRANT_DOTFILE_PATH +} + +# ---------------------------------------------------------------------------------------------------------------------- +# Ruby +# ---------------------------------------------------------------------------------------------------------------------- + +use_ruby() { + local version=${1:-} + + if [[ -z $version ]] && [[ -r .ruby-version ]]; then + version=$(< .ruby-version) + fi + + if [[ -n ${version:-} ]] && [[ -d /opt/ruby/$version ]]; then + load_prefix /opt/ruby/"$version" + fi + + layout ruby +} + +# ---------------------------------------------------------------------------------------------------------------------- +# Local +# ---------------------------------------------------------------------------------------------------------------------- + +layout_local() { + [[ ! -d $PWD/.local/bin ]] || PATH_add "$PWD"/.local/bin +} diff --git a/direnv/install.sh b/direnv/install.sh new file mode 100644 index 0000000..0c2d779 --- /dev/null +++ b/direnv/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/direnv + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/direnvrc -t "$config" +} diff --git a/dropbox/install.sh b/dropbox/install.sh new file mode 100644 index 0000000..80393b0 --- /dev/null +++ b/dropbox/install.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +if [[ -f "$HOME"/Dropbox/etc/install.sh ]]; then + echo >&2 "Setting up private environment..." + bash "$HOME"/Dropbox/etc/install.sh +fi diff --git a/eslint/eslintrc b/eslint/eslintrc new file mode 100644 index 0000000..60c9d01 --- /dev/null +++ b/eslint/eslintrc @@ -0,0 +1,21 @@ +{ + "extends": "airbnb", + "plugins": ["promise"], + "rules": { + "accessor-pairs": 2, + "comma-dangle": [2, "never"], + "handle-callback-err": [2, "^(err|error)$" ], + "indent": [2, 2, { "SwitchCase": 1 }], + "no-native-reassign": 2, + "no-negated-in-lhs": 2, + "no-unmodified-loop-condition": 2, + "no-unused-vars": [2, { "vars": "all", "args": "none" }], + "no-useless-call": 2, + "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], + "promise/param-names": 2, + "semi": [2, "never"], + "space-before-blocks": [2, "always"], + "space-before-function-paren": [2, "always"], + "template-curly-spacing": [2, "never"] + } +} diff --git a/eslint/install.sh b/eslint/install.sh new file mode 100644 index 0000000..9902507 --- /dev/null +++ b/eslint/install.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +ln -sf "$PWD"/eslintrc "$HOME"/.eslintrc diff --git a/fish/config.fish b/fish/config.fish new file mode 100644 index 0000000..32c4762 --- /dev/null +++ b/fish/config.fish @@ -0,0 +1,137 @@ +# ---------------------------------------------------------------------------------------------------------------------- +# Init +# ---------------------------------------------------------------------------------------------------------------------- + +fish_add_path "$HOME"/.local/bin +fish_add_path "$HOME"/Dropbox/bin + +set -U XDG_CACHE_HOME ~/.cache +set -U XDG_CONFIG_HOME ~/.config +set -U XDG_DATA_HOME ~/.local/share + +if not functions -q fundle; eval (wget -qO- https://git.io/fundle-install); end + +set -g fundle_plugins_dir "$XDG_CONFIG_HOME"/fish/plugins + +status --is-interactive; and type -q zoxide; and source (zoxide init fish | psub) +status --is-interactive; and type -q direnv; and source (direnv hook fish | psub) + +# ---------------------------------------------------------------------------------------------------------------------- +# Settings +# ---------------------------------------------------------------------------------------------------------------------- + +set fish_greeting "" +set fish_color_valid_path + +# ---------------------------------------------------------------------------------------------------------------------- +# Bindings +# ---------------------------------------------------------------------------------------------------------------------- + +bind \eq exit + +# ---------------------------------------------------------------------------------------------------------------------- +# Colors +# ---------------------------------------------------------------------------------------------------------------------- + +set nord0 2e3440 +set nord1 3b4252 +set nord2 434c5e +set nord3 4c566a +set nord4 d8dee9 +set nord5 e5e9f0 +set nord6 eceff4 +set nord7 8fbcbb +set nord8 88c0d0 +set nord9 81a1c1 +set nord10 5e81ac +set nord11 bf616a +set nord12 d08770 +set nord13 ebcb8b +set nord14 a3be8c +set nord15 b48ead + +set fish_color_normal $nord4 +set fish_color_command $nord9 +set fish_color_quote $nord14 +set fish_color_redirection $nord9 +set fish_color_end $nord6 +set fish_color_error $nord11 +set fish_color_param $nord4 +set fish_color_comment $nord3 +set fish_color_match $nord8 +set fish_color_search_match $nord8 +set fish_color_operator $nord9 +set fish_color_escape $nord13 +set fish_color_cwd $nord8 --bold +set fish_color_autosuggestion $nord8 --dim +set fish_color_user $nord4 --dim +set fish_color_host $nord9 +set fish_color_cancel $nord15 +set fish_pager_color_prefix $nord13 +set fish_pager_color_completion $nord6 +set fish_pager_color_description $nord10 +set fish_pager_color_progress $nord12 +set fish_pager_color_secondary $nord1 + +# ---------------------------------------------------------------------------------------------------------------------- +# Aliases and/or Functions +# ---------------------------------------------------------------------------------------------------------------------- + +alias ...='cd $(git rev-parse --show-toplevel)' + +function a --wraps=apt --description 'alias a apt'; apt $argv; end +function A --wraps='sudo apt' --description 'alias A sudo apt'; sudo apt $argv; end + +function b --wraps=bundle --description 'alias b bundle' + if not set -q arg[1]; and not test -f .envrc + echo 'layout ruby' >.envrc + sleep 0.1 + direnv allow . + + return + end + + switch $argv[1] + case "i" + bundle install $argv[2..-1] + case "u" + bundle update $argv[2..-1] + case "e" + bundle exec $argv[2..-1] + case "c" + bundle config $argv[2..-1] + case "*" + bundle $argv + end +end + +function d --wraps=direnv --description 'alias d direnv'; direnv $argv; end + +function e --wraps=nvim --description 'alias e nvim'; nvim $argv; end +function E --wraps='sudo nvim' --description 'alias E sudo nvim'; sudo nvim $argv; end + +function g --wraps=git --description 'alias g git'; git $argv; end + +function j --wraps='journalctl' --description 'alias j journalctl'; journalctl --user -u $argv; end +function J --wraps='sudo journalctl' --description 'alias J sudo journalctl'; sudo journalctl $argv; end + +function s --wraps='systemctl' --description 'alias s systemctl'; systemctl --user $argv; end +function S --wraps='sudo systemctl' --description 'alias S sudo systemctl'; sudo systemctl $argv; end + +function r --wraps=rails --description 'alias r rails'; rails $argv; end +function R --wraps=rake --description 'alias R rake'; bexec rake $argv; end + +function t --wraps=todo.sh --description 'alias todo.sh'; todo.sh -t $argv; end +function T --wraps=todo.sh --description 'alias todo.sh wtf'; todo.sh wtf; end + +function w --wraps='journalctl' --description 'alias w journalctl'; journalctl --user -f -u $argv; end +function W --wraps='journalctl' --description 'alias W journalctl'; sudo journalctl --user -f -u $argv; end + +# ---------------------------------------------------------------------------------------------------------------------- +# Plugins +# ---------------------------------------------------------------------------------------------------------------------- + +fundle plugin "metrofish/metrofish" +fundle plugin "PatrickF1/fzf.fish" + +fundle init diff --git a/fish/functions/fundle.fish b/fish/functions/fundle.fish new file mode 100644 index 0000000..2399145 --- /dev/null +++ b/fish/functions/fundle.fish @@ -0,0 +1,462 @@ +set __fundle_current_version '0.7.1' + +function __fundle_seq -a upto + seq 1 1 $upto 2>/dev/null +end + +function __fundle_next_arg -a index + set -l args $argv[2..-1] + set -l arg_index (math $index + 1) + if test (count $args) -lt $arg_index + echo "missing argument for $args[$index]" + return 1 + end + set -l arg $args[$arg_index] + switch $arg + case '--*' + echo "expected argument for $args[$index], got $arg"; and return 1 + case '*' + echo $arg; and return 0 + end +end + +function __fundle_compare_versions -a version1 -a version2 + for i in (__fundle_seq 4) + set -l v1 (echo $version1 | cut -d '.' -f $i | sed -Ee 's/[a-z]+//g') + set -l v2 (echo $version2 | cut -d '.' -f $i | sed -Ee 's/[a-z]+//g') + if test \( -n $v1 -a -z $v2 \) -o \( -n $v1 -a -n $v2 -a $v1 -lt $v2 \) + echo -n "lt"; and return 0 + else if test \( -z $v1 -a -n $v2 \) -o \( -n $v1 -a -n $v2 -a $v1 -gt $v2 \) + echo -n "gt"; and return 0 + end + end + echo -n "eq"; and return 0 +end + +function __fundle_date -d "returns a date" + set -l d (date +%s%N) + if echo $d | string match -rvq 'N' + echo $d + else + gdate +%s%N + end + return 0 +end + +function __fundle_self_update -d "updates fundle" + set -l fundle_repo_url "https://github.com/tuvistavie/fundle.git" + # This `sed` stays for now since doing it easily with `string` requires "--filter", which is only in 2.6.0 + set -l latest (command git ls-remote --tags $fundle_repo_url | sed -n -e 's|.*refs/tags/v\(.*\)|\1|p' | tail -n 1) + if test (__fundle_compare_versions $latest (__fundle_version)) != "gt" + echo "fundle is already up to date"; and return 0 + else + set -l file_url_template 'https://raw.githubusercontent.com/tuvistavie/fundle/VERSION/functions/fundle.fish' + set -l file_url (string replace 'VERSION' -- "v$latest" $file_url_template) + set -l tmp_file (mktemp /tmp/fundle.XXX) + set -l update_message "fundle has been updated to version $latest" + curl -Ls $file_url > $tmp_file; and mv $tmp_file (status -f); and echo $update_message; and return 0 + end +end + +function __fundle_url_rev -d "prints the revision from the url" -a git_url + set -l rev (echo $git_url | cut -d '#' -f 2 -s) + if test -n "$rev" + echo $rev + else + echo HEAD + end +end + +function __fundle_remote_url -d "prints the remote url from the full git url" -a git_url + echo $git_url | cut -d '#' -f 1 +end + +function __fundle_rev_parse -d "prints the revision if any" -a dir -a commitish + set -l sha (command git --git-dir $dir rev-parse -q --verify $commitish 2>/dev/null) + if test $status -eq 0 + echo -n $sha + return 0 + end + return 1 +end + +function __fundle_commit_sha -d "returns sha of the commit-ish" -a dir -a commitish + if test -d "$dir/.git" + set dir "$dir/.git" + end + if __fundle_rev_parse $dir "origin/$commitish" + return 0 + end + __fundle_rev_parse $dir $commitish +end + +function __fundle_plugins_dir -d "returns fundle directory" + if test -z "$fundle_plugins_dir" + if test -n "$XDG_CONFIG_HOME" + echo $XDG_CONFIG_HOME/fish/fundle + else + echo $HOME/.config/fish/fundle + end + else + echo $fundle_plugins_dir + end +end + +function __fundle_no_git -d "check if git is installed" + # `command -q` is >= 2.5.0 + if not command -s git > /dev/null 2>&1 + echo "git needs to be installed and in the path" + return 0 + end + return 1 +end + +function __fundle_check_date -d "check date" + if date +%s%N | string match -rvq 'N' + return 0 + end + if command -s gdate > /dev/null 2>&1 + return 0 + end + echo "You need to have a GNU date compliant date installed to use profiling. Use 'brew install coreutils' on OSX" + return 1 +end + +function __fundle_get_url -d "returns the url for the given plugin" -a repo + set split (string split @ $repo) + set repo $split[1] + set tag $split[2] + set url "https://github.com/$repo.git" + + test ! -z "$tag"; and set url (string join "#tags/" "$url" "$tag") + echo "$url" +end + + +function __fundle_plugin_index -d "returns the index of the plugin" -a plugin + for i in (__fundle_seq (count $__fundle_plugin_names)) + if test "$__fundle_plugin_names[$i]" = "$plugin" + return $i + end + end + # NOTE: should never reach this point + echo "could not find plugin: $plugin" + exit 1 +end + +function __fundle_checkout_revision -a plugin -a git_url + set -l plugin_dir (__fundle_plugins_dir)/$plugin + set -l git_dir $plugin_dir/.git + + set -l sha (__fundle_commit_sha $git_dir (__fundle_url_rev $git_url)) + if test $status -eq 0 + command git --git-dir="$git_dir" --work-tree="$plugin_dir" checkout -q -f $sha + else + echo "Could not checkout $plugin revision $sha" + return 1 + end +end + +function __fundle_update_plugin -d "update the given plugin" -a plugin -a git_url + echo "Updating $plugin" + + set -l remote_url (__fundle_remote_url $git_url) + set -l git_dir (__fundle_plugins_dir)/$plugin/.git + + command git --git-dir=$git_dir remote set-url origin $remote_url 2>/dev/null + command git --git-dir=$git_dir fetch -q 2>/dev/null + + __fundle_checkout_revision $plugin $git_url +end + +function __fundle_install_plugin -d "install the given plugin" -a plugin -a git_url + if __fundle_no_git + return 1 + end + + set -l plugin_dir (__fundle_plugins_dir)/$plugin + set -l git_dir $plugin_dir/.git + set -l remote_url (__fundle_remote_url $git_url) + + if test -d $plugin_dir + echo "$argv[1] installed in $plugin_dir" + return 0 + else + echo "Installing $plugin" + command git clone -q $remote_url $plugin_dir + __fundle_checkout_revision $plugin $git_url + end +end + +function __fundle_update -d "update the given plugin, or all if unspecified" -a plugin + if test -n "$plugin"; and test ! -d (__fundle_plugins_dir)/$plugin/.git + echo "$plugin not installed. You may need to run 'fundle install'" + return 1 + end + + if test -n "$plugin" + set -l index (__fundle_plugin_index $plugin) + __fundle_update_plugin "$plugin" $__fundle_plugin_urls[$index] + else + for i in (__fundle_seq (count $__fundle_plugin_names)) + __fundle_update_plugin $__fundle_plugin_names[$i] $__fundle_plugin_urls[$i] + end + end +end + +function __fundle_show_doc_msg -d "show a link to fundle docs" + if test (count $argv) -ge 1 + echo $argv + end + echo "See the docs for more info. https://github.com/tuvistavie/fundle" +end + +function __fundle_load_plugin -a plugin -a path -a fundle_dir -a profile -d "load a plugin" + if begin; set -q __fundle_loaded_plugins; and contains $plugin $__fundle_loaded_plugins; end + return 0 + end + + set -l plugin_dir (string replace -r '/.$' '' -- "$fundle_dir/$plugin/$path") + + if not test -d $plugin_dir + __fundle_show_doc_msg "$plugin not installed. You may need to run 'fundle install'" + return 1 + end + + # Take everything but "plugin-" from the last path component + set -l plugin_name (string replace -r '.*/(plugin-)?(.*)$' '$2' -- $plugin) + set -l init_file "$plugin_dir/init.fish" + set -l conf_dir "$plugin_dir/conf.d" + set -l bindings_file "$plugin_dir/key_bindings.fish" + set -l functions_dir "$plugin_dir/functions" + set -l completions_dir "$plugin_dir/completions" + set -l plugin_paths $__fundle_plugin_name_paths + + if begin; test -d $functions_dir; and not contains $functions_dir $fish_function_path; end + set fish_function_path $fish_function_path[1] $functions_dir $fish_function_path[2..-1] + end + + if begin; test -d $completions_dir; and not contains $completions_dir $fish_complete_path; end + set fish_complete_path $fish_complete_path[1] $completions_dir $fish_complete_path[2..-1] + end + + if test -f $init_file + source $init_file + else if test -d $conf_dir + # read all *.fish files in conf.d + for f in $conf_dir/*.fish + source $f + end + else + # For compatibility with oh-my-fish themes, if there is no `init.fish` file in the plugin, + # which is the case with themses, the root directory of the plugin is trerated as a functions + # folder, so we include it in the `fish_function_path` variable. + if not contains $plugin_dir $fish_function_path + set fish_function_path $fish_function_path[1] $plugin_dir $fish_function_path[2..-1] + end + end + + if test -f $bindings_file + set -g __fundle_binding_paths $bindings_file $__fundle_binding_paths + end + + set -g __fundle_loaded_plugins $plugin $__fundle_loaded_plugins + + set -l dependencies (printf '%s\n' $plugin_paths $__fundle_plugin_name_paths | sort | uniq -u) + for dependency in $dependencies + set -l name_path (string split : -- $dependency) + if test "$profile" -eq 1 + set -l start_time (__fundle_date +%s%N) + __fundle_load_plugin $name_path[1] $name_path[2] $fundle_dir $profile + set -l ellapsed_time (math \((__fundle_date +%s%N) - $start_time\) / 1000) + echo "$name_path[1]": {$ellapsed_time}us + else + __fundle_load_plugin $name_path[1] $name_path[2] $fundle_dir $profile + end + end + + emit "init_$plugin_name" $plugin_dir +end + +function __fundle_bind -d "set up bindings" + if functions -q fish_user_key_bindings; and not functions -q __fish_user_key_bindings + functions -c fish_user_key_bindings __fish_user_key_bindings + end + + function fish_user_key_bindings + for bindings in $__fundle_binding_paths + source $bindings + end + if functions -q __fish_user_key_bindings + __fish_user_key_bindings + end + end +end + +function __fundle_init -d "initialize fundle" + set -l fundle_dir (__fundle_plugins_dir) + + if test (count $__fundle_plugin_names) -eq 0 + __fundle_show_doc_msg "No plugin registered. You need to call 'fundle plugin NAME' before using 'fundle init'. \ + +Try reloading your shell if you just edited your configuration." + return 1 + end + + set -l profile 0 + if begin; contains -- -p $argv; or contains -- --profile $argv; and __fundle_check_date; end + set profile 1 + end + + set -l has_uninstalled_plugins 0 + for name_path in $__fundle_plugin_name_paths + set -l name_path (string split : -- $name_path) + if test "$profile" -eq 1 + set -l start_time (__fundle_date +%s%N) + __fundle_load_plugin $name_path[1] $name_path[2] $fundle_dir $profile + set -l ellapsed_time (math \((__fundle_date +%s%N) - $start_time\) / 1000) + echo "$name_path[1]": {$ellapsed_time}us + else + __fundle_load_plugin $name_path[1] $name_path[2] $fundle_dir $profile || set has_uninstalled_plugins 1 + end + end + + __fundle_bind + return $has_uninstalled_plugins +end + +function __fundle_install -d "install plugin" + if test (count $__fundle_plugin_names) -eq 0 + __fundle_show_doc_msg "No plugin registered. You need to call 'fundle plugin NAME' before using 'fundle install'" + end + + for i in (__fundle_seq (count $__fundle_plugin_names)) + __fundle_install_plugin $__fundle_plugin_names[$i] $__fundle_plugin_urls[$i] $argv + end + + set -l original_plugins_count (count (__fundle_list -s)) + __fundle_init + + # if plugins count increase after init, new plugins have dependencies + # install new plugins dependencies if any + if test (count (__fundle_list -s)) -gt $original_plugins_count + __fundle_install $argv + end +end + +function __fundle_clean -d "cleans fundle directory" + set -l fundle_dir (__fundle_plugins_dir) + set -l used_plugins (__fundle_list -s) + set -l installed_plugins $fundle_dir/*/*/ + for installed_plugin in $installed_plugins + set -l plugin (string trim --chars="/" \ + (string replace -r -- "$fundle_dir" "" $installed_plugin)) + if not contains $plugin $used_plugins + echo "Removing $plugin" + rm -rf $fundle_dir/$plugin + end + end +end + +function __fundle_plugin -d "add plugin to fundle" -a name + set -l plugin_url "" + set -l plugin_path "." + set -l argv_count (count $argv) + set -l skip_next true + if test $argv_count -eq 0 -o -z "$argv" + echo "usage: fundle plugin NAME [[--url] URL] [--path PATH]" + return 1 + else if test $argv_count -gt 1 + for i in (__fundle_seq (count $argv)) + test $skip_next = true; and set skip_next false; and continue + set -l arg $argv[$i] + switch $arg + case '--url' + set plugin_url (__fundle_next_arg $i $argv) + test $status -eq 1; and echo $plugin_url; and return 1 + set skip_next true + case '--path' + set plugin_path (__fundle_next_arg $i $argv) + test $status -eq 1; and echo $plugin_path; and return 1 + set skip_next true + case '--*' + echo "unknown flag $arg"; and return 1 + case '*' + test $i -ne 2; and echo "invalid argument $arg"; and return 1 + set plugin_url $arg + end + end + end + test -z "$plugin_url"; and set plugin_url (__fundle_get_url $name) + set name (string split @ $name)[1] + + if not contains $name $__fundle_plugin_names + set -g __fundle_plugin_names $__fundle_plugin_names $name + set -g __fundle_plugin_urls $__fundle_plugin_urls $plugin_url + set -g __fundle_plugin_name_paths $__fundle_plugin_name_paths $name:$plugin_path + end +end + +function __fundle_version -d "prints fundle version" + echo $__fundle_current_version +end + +function __fundle_print_help -d "prints fundle help" + echo "usage: fundle (init | plugin | list | install | update | clean | self-update | version | help)" +end + +function __fundle_list -d "list registered plugins" + if begin; contains -- -s $argv; or contains -- --short $argv; end + for name in $__fundle_plugin_names + echo $name + end + else + for i in (__fundle_seq (count $__fundle_plugin_names)) + echo {$__fundle_plugin_names[$i]}\n\t{$__fundle_plugin_urls[$i]} + end + end +end + +function fundle -d "run fundle" + if __fundle_no_git + return 1 + end + + set -l sub_args "" + + switch (count $argv) + case 0 + __fundle_print_help + return 1 + case 1 + case '*' + set sub_args $argv[2..-1] + end + + switch $argv[1] + case "init" + __fundle_init $sub_args + case "plugin" + __fundle_plugin $sub_args + case "list" + __fundle_list $sub_args + case "plugins" + echo "'fundle plugins' has been replaced by 'fundle list'" + case "install" + __fundle_install $sub_args + case "update" + __fundle_update $sub_args + case "clean" + __fundle_clean + case "self-update" + __fundle_self_update + case "version" -v --version + __fundle_version + case "help" -h --help + __fundle_print_help + return 0 + case "*" + __fundle_print_help + return 1 + end +end diff --git a/fish/functions/mc.fish b/fish/functions/mc.fish new file mode 100644 index 0000000..9ea51d8 --- /dev/null +++ b/fish/functions/mc.fish @@ -0,0 +1,19 @@ +function mc --wraps=mc + set -q TMPDIR || set -l TMPDIR /tmp + set -l t (mktemp -p "$TMPDIR" -d mc.XXXXXXXX ) || return + + if set -q t[1] + set -l f "$t/dir" + + env SHELL=/bin/bash COLORTERM=truecolor /usr/bin/mc -P "$f" $argv + + if test -r "$f" + set -l d (cat "$f") + if test -n "$d"; and test -d "$d"; and test "$d" != "$PWD" + builtin cd "$d" + end + end + + rm -rf "$t" + end +end diff --git a/fish/install.sh b/fish/install.sh new file mode 100644 index 0000000..fb8a343 --- /dev/null +++ b/fish/install.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/fish + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/config.fish -t "$config" +} + +install -d "$config"/functions && { + find "$PWD"/functions -type f -print0 | xargs -0 ln -t "$config"/functions -sf +} + +fish -c "fundle install" diff --git a/fzf/bin/search b/fzf/bin/search new file mode 100755 index 0000000..d35a94d --- /dev/null +++ b/fzf/bin/search @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Switch between Ripgrep launcher mode (CTRL-R) and fzf filtering mode (CTRL-F) +rm -f /tmp/rg-fzf-{r,f} +RG_PREFIX="rg --column --line-number --no-heading --color=always --smart-case " +INITIAL_QUERY="${*:-}" +: | fzf --ansi --disabled --query "$INITIAL_QUERY" \ + --bind "start:reload($RG_PREFIX {q})+unbind(ctrl-r)" \ + --bind "change:reload:sleep 0.1; $RG_PREFIX {q} || true" \ + --bind "ctrl-f:unbind(change,ctrl-f)+change-prompt(2. fzf> )+enable-search+rebind(ctrl-r)+transform-query(echo {q} > /tmp/rg-fzf-r; cat /tmp/rg-fzf-f)" \ + --bind "ctrl-r:unbind(ctrl-r)+change-prompt(1. ripgrep> )+disable-search+reload($RG_PREFIX {q} || true)+rebind(change,ctrl-f)+transform-query(echo {q} > /tmp/rg-fzf-f; cat /tmp/rg-fzf-r)" \ + --color "hl:-1:underline,hl+:-1:underline:reverse" \ + --prompt '1. ripgrep> ' \ + --delimiter : \ + --header 'β•± CTRL-R (ripgrep mode) β•± CTRL-F (fzf mode) β•±' \ + --preview 'bat --color=always {1} --highlight-line {2}' \ + --preview-window 'down,40%,border-bottom,+{2}+3/3,~3' \ + --bind 'enter:become(nvim {1} +{2})' diff --git a/fzf/install.sh b/fzf/install.sh new file mode 100644 index 0000000..6d7948e --- /dev/null +++ b/fzf/install.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +install -d "$HOME"/.local/bin && { + find "$PWD"/bin -executable -type f -print0 | xargs -0 ln -t "$HOME"/.local/bin -sf +} diff --git a/gh/config.yml b/gh/config.yml new file mode 100644 index 0000000..fb68eb8 --- /dev/null +++ b/gh/config.yml @@ -0,0 +1,14 @@ +# What protocol to use when performing git operations. Supported values: ssh, https +git_protocol: https +# What editor gh should run when creating issues, pull requests, etc. If blank, will refer to environment. +editor: +# Aliases allow you to create nicknames for gh commands +aliases: + co: pr checkout + new: repo create --private --source . --push + new-: repo create --public --source . --push + reporm: api -X DELETE "repos/$1" + repomv: api -X PATCH "repos/$1" -f name="$2" --jq ".html_url" + repotf: api -X POST "repos/$1/transfer" -f new_owner="$2" --jq ".html_url" + repoar: api -X PATCH "repos/$1" -f archived=true --jq ".archived" +version: "1" diff --git a/gh/install.sh b/gh/install.sh new file mode 100644 index 0000000..9f804b1 --- /dev/null +++ b/gh/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/gh + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/config.yml -t "$config" +} diff --git a/git/bin/git-. b/git/bin/git-. new file mode 100755 index 0000000..cb0cf94 --- /dev/null +++ b/git/bin/git-. @@ -0,0 +1,3 @@ +#!/bin/sh + +exec git commit -a -m . diff --git a/git/bin/git-.. b/git/bin/git-.. new file mode 100755 index 0000000..23c5e44 --- /dev/null +++ b/git/bin/git-.. @@ -0,0 +1,3 @@ +#!/bin/sh + +git commit -a -m . && exec git push "$@" diff --git a/git/bin/git-renew b/git/bin/git-renew new file mode 100755 index 0000000..38139e1 --- /dev/null +++ b/git/bin/git-renew @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x + +ask() { + local answer + + echo -e -n >&2 "\033[1;33m$*\033[0m [y/n] " + read -r answer + + [[ ${answer:-} == y ]] +} + +bye() { + cry "$@" + exit 0 +} + +cry() { + echo -e >&2 "\033[1;36m$*\033[0m" +} + +die() { + echo -e >&2 "\033[1;31m$*\033[0m" + exit 1 +} + +main() { + cd "$(git rev-parse --show-toplevel 2>/dev/null)" || die "Not a Git repository" + + local remote + remote=$(git config remote.origin.url || true) + [[ -n ${remote:-} ]] || die "No remote found" + + local default + default=$(git remote show origin | awk '/HEAD branch/ {print $NF}') + + ask "This will reset '$default' branch on '$remote'" || bye "Bye" + + local filelist + filelist=$(mktemp "${TMPDIR:-/tmp}/filelist.XXXXXXXX") || exit + trap "err=\$? && rm -f '$filelist' || exit \$err" EXIT HUP INT QUIT TERM + + local path + while IFS= read -r -d $'\0' path; do + [[ -e $path ]] || continue + echo "$path" + done < <( + git ls-tree --full-tree -r -z --name-only HEAD + git diff -z --name-only --cached --diff-filter=A + ) >"$filelist" + + local message + message=$(git rev-list --max-parents=0 --format='%s' --no-commit-header HEAD || true) + [[ -n ${message:-} ]] || message="Initial commit" + + rm -rf .git + + git init --initial-branch="$default" + git add --force --pathspec-from-file="$filelist" + git commit --no-verify -a -m "$message" + git remote add origin "$remote" + git push --force --set-upstream origin "$default" + + local purge= + if [[ ${1:-} == purge ]] || ask "Delete all remote branches except '$default'"; then + purge=true + fi + + if [[ -n ${purge:-} ]]; then + git fetch --all + + local branch + while read -r branch; do + cry "βœ— $branch" + git push origin -d "$branch" + done < <(git branch -r --format '%(refname:lstrip=-1)' | grep -vF HEAD | grep -vF "$default") + fi +} + +main "$@" diff --git a/git/config b/git/config new file mode 100644 index 0000000..42f2d24 --- /dev/null +++ b/git/config @@ -0,0 +1,62 @@ +[alias] + a = add + ap = add --patch + b = branch + c = commit + co = checkout + d = diff + f = fetch + la = log --graph --decorate --pretty=oneline --abbrev-commit --all + l = log --pretty=format:'%Cred%h%Creset - %<|(60)%C(bold)%s%Creset %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit + m = merge + p = push + r = remote + s = status -s + + amend = commit --amend --no-edit + ignored = ls-files --exclude-standard --ignored --others + undo = reset --soft HEAD^ +[color] + ui = auto + branch = auto + diff = auto + interactive = auto + status = auto +[color "branch"] + current = yellow reverse + local = yellow + remote = green +[color "diff"] + meta = yellow bold + frag = magenta bold + old = red bold + new = green bold +[color "status"] + added = yellow + changed = green + untracked = cyan +[diff] + renames = copies + ignoreSubmodules = dirty +[merge] + stat = true +[core] + editor = /usr/bin/nvim + hookspath = $HOME/.config/git/hooks +[credential] + helper = /usr/share/doc/git/contrib/credential/libsecret/git-credential-libsecret +[filter "lfs"] + required = true + clean = git-lfs clean -- %f + smudge = git-lfs smudge -- %f + process = git-lfs filter-process +[include] + path = config.local +[pull] + rebase = false +[push] + autoSetupRemote = true +[init] + defaultBranch = main +[include] + path = ./local diff --git a/git/hooks/commit-msg b/git/hooks/commit-msg new file mode 100755 index 0000000..ca13a9d --- /dev/null +++ b/git/hooks/commit-msg @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +abort() { printf '\e[1m\e[38;5;9mβœ—\e[0m \e[1m%s\e[0m\n' "$*" >&2; exit 1; } +warn() { printf '\e[1m\e[38;5;11m!\e[0m \e[1m%s\e[0m\n' "$*" >&2; } +succeed() { printf '\e[1m\e[38;5;10mβœ“\e[0m \e[1m%s\e[0m\n' "$*" >&2; } + +verify() { + local message=$1 + + if ! command -v cog &>/dev/null; then + warn 'Cog required to verify commit message' + return 0 + fi + + if ! cog verify "$message"; then + abort 'Commit message does not conform to https://www.conventionalcommits.org/en/v1.0.0' + fi +} + +nitpick() { + local message=$1 + + if ! echo "$message" | sed -E 's/^[^:]+: +(.*)$/\1/g' | grep -Eq '^([a-zığüşâç]|[A-ZΔ°ΔžΓœΕžΓ–Γ‡]{2,})'; then + abort 'Description must start with lowercase' + fi + + if echo "$message" | grep -Eq '^refact(:|\()'; then + abort 'Do not abbreviate "refactor"' + fi +} + +main() { + local commit_message_file=$1 message + + if [[ $(git config hooks.conventional-commits 2>/dev/null || true) != true ]]; then + exit 0 + fi + if [[ $(git config hooks.commit-msg 2>/dev/null || true) == false ]]; then + exit 0 + fi + + message=$(<"$commit_message_file") + + if verify "$message" && nitpick "$message"; then + succeed 'Commit parse succeeded' + fi +} + +main "$@" diff --git a/git/hooks/pre-commit b/git/hooks/pre-commit new file mode 100755 index 0000000..d9d7c46 --- /dev/null +++ b/git/hooks/pre-commit @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Avoid doing commit in environment branches. + +declare -gr forbidden_branches='^(master|main|release)$' + +check() { + local branch; branch=$(git rev-parse --abbrev-ref HEAD) + + if [[ $branch =~ $forbidden_branches ]]; then + cat >&2 <<-EOF + You should not commit directly into $branch branch. + Please create a new branch from '$branch' and try again. + EOF + + exit 1 + fi +} + +main() { + if [[ $(git for-each-ref --format='%(refname)' refs/heads/ | wc -l) -le 1 ]]; then + exit 0 + fi + + if [[ $(git config hooks.pre-commit 2>/dev/null || true) == false ]]; then + exit 0 + fi + + check +} + +main "$@" diff --git a/git/hooks/pre-push b/git/hooks/pre-push new file mode 100755 index 0000000..b75666d --- /dev/null +++ b/git/hooks/pre-push @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +abort() { printf '\e[1m\e[38;5;9mβœ—\e[0m \e[1m%s\e[0m\n' "$*" >&2; exit 1; } +warn() { printf '\e[1m\e[38;5;11m!\e[0m \e[1m%s\e[0m\n' "$*" >&2; } + +check() { + if ! command -v cog &>/dev/null; then + warn 'Cog required to check commit' + return 0 + fi + + if cog check; then + return 0 + fi + + abort "Invalid commits were found, force push with '--no-verify'" +} + +main() { + if [[ $(git config hooks.conventional-commits 2>/dev/null || true) != true ]]; then + exit 0 + fi + if [[ $(git config hooks.pre-push 2>/dev/null || true) == false ]]; then + exit 0 + fi + if [[ $(git for-each-ref --format='%(refname)' refs/heads/ | wc -l) -le 1 ]]; then + exit 0 + fi + + check +} + +main "$@" diff --git a/git/ignore b/git/ignore new file mode 100644 index 0000000..92070fd --- /dev/null +++ b/git/ignore @@ -0,0 +1,29 @@ +.\#* +*~ +\#* +*.bak +.*.d +*.orig +*.rej +*.sw +.*.sw[a-z] +*.swp +.dropboxignore + +Desktop.ini +.DS_Store? +ehthumbs.db +Icon? +Thumbs.db + +/.vagrant*/ +/.env +/.envrc +/_/ +/.../ + +/.local/* +!/.local/bin/ +!/.local/etc/ +!/.local/lib/ +!/.local/README* diff --git a/git/install.sh b/git/install.sh new file mode 100644 index 0000000..804793b --- /dev/null +++ b/git/install.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/git + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/config -t "$config" + ln -sf "$PWD"/ignore -t "$config" + ln -sf "$PWD"/hooks -t "$config" +} + +install -d "$HOME"/.local/bin && { + find "$PWD"/bin -executable -type f -print0 | xargs -0 ln -t "$HOME"/.local/bin -sf +} diff --git a/gnome/bin/background b/gnome/bin/background new file mode 100755 index 0000000..60c5e20 --- /dev/null +++ b/gnome/bin/background @@ -0,0 +1,25 @@ +#!/bin/sh +# Credits: RenΓ© https://unix.stackexchange.com/a/723275 +# org.freedesktop.appearance color-scheme +# +# Indicates the system's preferred color scheme. +# Supported values are: +# +# 0: No preference +# 1: Prefer dark appearance +# 2: Prefer light appearance +# +# Unknown values should be treated as 0 (no preference). + +scheme=$( + gdbus call --session --timeout=1000 \ + --dest=org.freedesktop.portal.Desktop \ + --object-path /org/freedesktop/portal/desktop \ + --method org.freedesktop.portal.Settings.Read org.freedesktop.appearance color-scheme +) + +case $scheme in +'(<>,)') exit 1 ;; +'(<>,)') exit 2 ;; +* ) exit 0 ;; +esac diff --git a/gnome/install.sh b/gnome/install.sh new file mode 100644 index 0000000..c9f643f --- /dev/null +++ b/gnome/install.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +install -d "$HOME"/.local/bin && { + find "$PWD"/bin -executable -type f -print0 | xargs -0 ln -t "$HOME"/.local/bin -sf +} + +if [[ -n ${DESKTOP_SESSION:-} ]]; then + unbind() { + local -a args=() + + read -r -a args < <(gsettings list-recursively | grep "'$1'" | cut -d' ' -f-2 2>/dev/null) || true + + if (( ${#args[@]} )); then + echo >&2 "Unbinding $1..." + gsettings set "${args[@]}" "[]" + fi + } + + unbind "F1" ; unbind "F1" ; unbind "F1" + unbind "F2" ; unbind "F2" ; unbind "F2" + unbind "F3" ; unbind "F3" ; unbind "F3" + unbind "F4" ; unbind "F4" ; unbind "F4" + unbind "F5" ; unbind "F5" ; unbind "F5" + unbind "F6" ; unbind "F6" ; unbind "F6" + unbind "F7" ; unbind "F7" ; unbind "F7" + unbind "F8" ; unbind "F8" ; unbind "F8" + unbind "F9" ; unbind "F9" ; unbind "F9" + unbind "F10"; unbind "F10"; unbind "F10" + unbind "F12"; unbind "F12"; unbind "F12" + + unbind "Space"; unbind "space" + unbind "Above_Tab"; unbind "Above_Tab" + + echo >&2 "Setting keyboard repeat interval to 10..." + gsettings set org.gnome.desktop.peripherals.keyboard repeat-interval 10 + echo >&2 "Setting keyboard delay to 250..." + gsettings set org.gnome.desktop.peripherals.keyboard delay 250 +fi diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..827eb1b --- /dev/null +++ b/install.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +cry() { echo -e "$*" >&2; } +die() { cry "$@"; exit 1; } +gui() { [[ -n ${DISPLAY:-} ]]; } +run() { cry "--> $1"; bash "$1"/install.sh; } + +[[ ${EUID:-} -gt 0 ]] || die "You must not be root." + +touch ~/.hushlogin + +run alacritty +run bash +run bat +run biome +run bun +run bundle +run direnv +run eslint +run fish +run fzf +run gh +run git +run gnome +run irb +run markdownlint +run mc +run neomutt +run npm +run nvim +run pylint +run rubocop +run tmux +run todo +run vifm +run vscode +run wezterm +run zsh + +! gui || run dropbox diff --git a/irb/install.sh b/irb/install.sh new file mode 100644 index 0000000..8d50017 --- /dev/null +++ b/irb/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/irb + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/irbrc -t "$config" +} diff --git a/irb/irbrc b/irb/irbrc new file mode 100644 index 0000000..a7e8cc5 --- /dev/null +++ b/irb/irbrc @@ -0,0 +1,4 @@ +require 'irb/completion' +require 'irb/ext/eval_history' +ARGV.concat [ '--readline', '--prompt-mode', 'simple' ] +IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.cache/irb/history" diff --git a/markdownlint/install.sh b/markdownlint/install.sh new file mode 100644 index 0000000..116f54b --- /dev/null +++ b/markdownlint/install.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +ln -sf "$PWD"/markdownlintrc "$HOME"/.markdownlintrc diff --git a/markdownlint/markdownlintrc b/markdownlint/markdownlintrc new file mode 100644 index 0000000..7e6acf4 --- /dev/null +++ b/markdownlint/markdownlintrc @@ -0,0 +1,22 @@ +{ + "default": true, + "MD003": { + "style": "setext_with_atx" + }, + "MD004": { + "style": "sublist" + }, + "MD013": { + "line_length": 120, + "tables": false + }, + "MD024": { + "allow_different_nesting": true + }, + "MD029": { + "style": "ordered" + }, + "MD033": { + "allowed_elements": ["br", "iframe", "video"] + } +} diff --git a/mc/install.sh b/mc/install.sh new file mode 100644 index 0000000..a3c348c --- /dev/null +++ b/mc/install.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/mc + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/mc.keymap -t "$config" + ln -sf "$PWD"/menu -t "$config" + cp "$PWD"/mc.ini "$config"/ini # MC overwrites ini, hence copy +} + +data=${XDG_DATA_HOME:-$HOME/.local/share}/mc +rm -rf "$data" && install -d "$data" && { + cp -a "$PWD"/skins "$data" +} diff --git a/mc/mc.ini b/mc/mc.ini new file mode 100644 index 0000000..f689946 --- /dev/null +++ b/mc/mc.ini @@ -0,0 +1,17 @@ +[Midnight-Commander] +use_internal_edit=false +use_internal_view=false +confirm_exit=false +skin=nord + +[Layout] +message_visible=false +keybar_visible=false +xterm_title=true +output_lines=0 +command_prompt=true +menubar_visible=false +free_space=true + +[Panels] +navigate_with_arrows=true diff --git a/mc/mc.keymap b/mc/mc.keymap new file mode 100644 index 0000000..eca336d --- /dev/null +++ b/mc/mc.keymap @@ -0,0 +1,6 @@ +[filemanager] +Quit = f10; alt-q + +[panel] +SortByName = alt-N +SortByMTime = alt-M diff --git a/mc/menu b/mc/menu new file mode 100644 index 0000000..ef60c92 --- /dev/null +++ b/mc/menu @@ -0,0 +1,383 @@ +shell_patterns=0 + +############################################################################## +# %% The % character +# %f The current file (if non-local vfs, file will be copied locally and +# %f will be full path to it) +# %p The current file +# %d The current working directory +# %s "Selected files"; the tagged files if any, otherwise the current file +# %t Tagged files +# %u Tagged files (and they are untagged on return from expand_format) +# %view Runs the commands and pipes standard output to the view command +# If %view is immediately followed by '{', recognize keywords +# ascii, hex, nroff and unform +# +# If the format letter is in uppercase, it refers to the other panel +# +# With a number followed the % character you can turn quoting on (default) +# and off. For example: +# %f quote expanded macro +# %1f ditto +# %0f don't quote expanded macro +############################################################################## + ++ ! t t +@ Do something on the current file + CMD=%{Enter command} + $CMD %f + ++ t t +@ Do something on the tagged files + CMD=%{Enter command} + for i in %t ; do + $CMD "$i" + done + +0 Edit a bug report and send it to root + I=`mktemp "${MC_TMPDIR:-/tmp}/mail.XXXXXX"` || exit 1 + ${EDITOR-vi} "$I" + test -r "$I" && mail root < "$I" + rm -f "$I" + +=+ f \.1$ | f \.3$ | f \.4$ | f \.5$ | f \.6$ | f \.7$ | f \.8$ | f \.man$ & t r +1 Display the file with roff -man + %view{ascii,nroff} roff -c -Tlatin1 -mandoc %f + += t d +2 Compress the current subdirectory (zip) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read zip + [ "$zip"x = x ] && zip="$Pwd" + cd .. && \ + zip -r "$zip.zip" "$Pwd" && \ + echo "../$zip.zip created." + +3 Compress the current subdirectory (tar.gz) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + [ "$tar"x = x ] && tar="$Pwd" + cd .. && \ + tar cf - "$Pwd" | gzip -f9 > "$tar.tar.gz" && \ + echo "../$tar.tar.gz created." + +4 Compress the current subdirectory (tar.bz2) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + [ "$tar"x = x ] && tar="$Pwd" + cd .. && \ + tar cf - "$Pwd" | bzip2 -f > "$tar.tar.bz2" && \ + echo "../$tar.tar.bz2 created." + +5 Compress the current subdirectory (tar.7z) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + [ "$tar"x = x ] && tar="$Pwd" + cd .. && \ + tar cf - "$Pwd" | 7za a -si "$tar.tar.7z" && \ + echo "../$tar.tar.7z created." + +6 Compress the current subdirectory (tar.xz) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + [ "$tar"x = x ] && tar="$Pwd" + cd .. && \ + tar cf - "$Pwd" | xz -f > "$tar.tar.xz" && \ + echo "../$tar.tar.xz created." + +7 Compress the current subdirectory (tar.zst) + Pwd=`basename %d /` + echo -n "Name of the compressed file (without extension) [$Pwd]: " + read tar + [ "$tar"x = x ] && tar="$Pwd" + cd .. && \ + tar cf - "$Pwd" | zstd -f > "$tar.tar.zst" && \ + echo "../$tar.tar.zst created." + += f \.c$ & t r ++ f \.c$ & t r & ! t t +c Compile and link current .c file + make "`basename %f .c`" 2>/dev/null || cc -O -o "`basename %f .c`" %f + ++ t r & ! t t +a Append file to opposite + cat %f >> %D/%f + ++ t t +A Append files to opposite files + for i in %t ; do + cat "$i" >> %D/"$i" + done + ++ t r & ! t t +d Delete file if a copy exists in the other directory. + if [ %d = %D ]; then + echo "The two directories must be different." + exit 1 + fi + if [ -f %D/%f ]; then # if two of them, then + if cmp -s %D/%f %f; then + rm %f && echo %f": DELETED." + else + echo %f" and "%D/%f" differ: NOT deleted." + echo -n "Press RETURN " + read key + fi + else + echo %f": No copy in "%D/%f": NOT deleted." + fi + ++ t t +D Delete tagged files if a copy exists in the other directory. + if [ %d = %D ]; then + echo "The two directores must be different." + exit 1 + fi + for i in %t ; do + if [ -f %D/"$i" ]; then + SUM1=`sum "$i"` + SUM2=`sum %D/"$i"` + if [ "$SUM1" = "$SUM2" ]; then + rm "$i" && echo "${i}: DELETED." + else + echo "$i and "%D"/$i differ: NOT deleted." + fi + else + echo "$i has no copy in "%D": NOT deleted." + fi + done + +m View manual page + MAN=%{Enter manual name} + %view{ascii,nroff} MANROFFOPT='-c -Tlatin1' MAN_KEEP_FORMATTING=1 man -P cat "$MAN" + += f \.gz$ & t r ++ ! t t +n Inspect gzip'ed newsbatch file + dd if=%f bs=1 skip=12 | zcat | ${PAGER-more} + # assuming the cunbatch header is 12 bytes long. + += t r & ++ ! t t +h Strip headers from current newsarticle + CHECK=`awk '{print $1 ; exit}' %f` 2>/dev/null + case "$CHECK" in + Newsgroups:|Path:) + I=`mktemp "${MC_TMPDIR:-/tmp}/news.XXXXXX"` || exit 1 + cp %f "$I" && sed '/^'"$CHECK"' /,/^$/d' "$I" > %f + [ "$?" = "0" ] && rm "$I" + echo %f": header removed." + ;; + *) + echo %f" is not a news article." + ;; + esac + ++ t t +H Strip headers from the marked newsarticles + for i in %t ; do + CHECK=`awk '{print $1 ; exit}' "$i"` 2>/dev/null + WFILE=`mktemp "${MC_TMPDIR:-/tmp}/news.XXXXXX"` || exit 1 + case "$CHECK" in + Newsgroups:|Path:) + cp "$i" "$WFILE" && sed '/^'"$CHECK"' /,/^$/d' "$WFILE" > "$i" + if [ "$?" = "0" ]; then + rm "$WFILE"; echo "$i header removed. OK." + else + echo "Oops! Please check $i against $WFILE." + fi + ;; + *) + echo "$i skipped: Not a news article." + ;; + esac + done + += t r ++ ! t t +r Copy file to remote host + echo -n "To which host?: " + read Host + echo -n "To which directory on $Host?: " + read Dir + rcp -p %f "${Host}:${Dir}" + ++ t t +R Copy files to remote host (no error checking) + echo -n "Copy files to which host?: " + read Host + echo -n "To which directory on $Host? :" + read Dir + rcp -pr %u "${Host}:${Dir}" + += f \.tex$ & t r ++ f \.tex$ & t r & ! t t +t Run latex on file and show it with xdvi + latex %f && xdvi "`basename %f .tex`".dvi + +=+ f ^part | f ^Part | f uue & t r ++ t t +U Uudecode marked news articles (needs work) + ( + for i in %t ; do # strip headers + FIRST=`awk '{print $1 ; exit}' "$i"` + cat "$i" | sed '/^'"$FIRST"' /,/^$/d' + done + ) | sed '/^$/d' | sed -n '/^begin 6/,/^end$/p' | uudecode + if [ "$?" != "0" ]; then + echo "Cannot decode "%t"." + fi + echo "Please test the output file before deleting anything." + +=+ f \.tar\.gz$ | f \.tar\.z$ | f \.tgz$ | f \.tpz$ | f \.tar\.lz$ | f \.tar\.lz4$ | f \.tar\.lzma$ | f \.tar\.7z$ | f \.tar\.xz$ | f \.tar\.zst | f \.tar\.Z$ | f \.tar\.bz2$ & t rl +x Extract the contents of a compressed tar file + unset PRG + case %f in + *.tar.7z) PRG="7za e -so";; + *.tar.bz2) PRG="bunzip2 -c";; + *.tar.gz|*.tar.z|*.tgz|*.tpz|*.tar.Z) PRG="gzip -dc";; + *.tar.lz) PRG="lzip -dc";; + *.tar.lz4) PRG="lz4 -dc";; + *.tar.lzma) PRG="lzma -dc";; + *.tar.xz) PRG="xz -dc";; + *.tar.zst) PRG="zstd -dc";; + *) exit 1;; + esac + $PRG %f | tar xvf - + ++ t r & ! t t +u Zip or unzip selected file + if [ %x = "zip" ]; then + unzip %f + else + zip %b.zip %f + fi + += t r ++ ! t t +y Gzip or gunzip current file + unset DECOMP + case %f in + *.gz|*.[zZ]) DECOMP=-d;; + esac + # Do *not* add quotes around $DECOMP! + gzip $DECOMP -v %f + ++ t t +Y Gzip or gunzip tagged files + for i in %t ; do + unset DECOMP + case "$i" in + *.gz|*.[zZ]) DECOMP=-d;; + esac + gzip $DECOMP -v "$i" + done + ++ ! t t +b Bzip2 or bunzip2 current file + unset DECOMP + case %f in + *.bz2) DECOMP=-d;; + esac + bzip2 $DECOMP -v %f + ++ t t +B Bzip2 or bunzip2 tagged files + for i in %t ; do + unset DECOMP + case "$i" in + *.bz2) DECOMP=-d;; + esac + bzip2 $DECOMP -v "$i" + done + ++ f \.tar.gz$ | f \.tgz$ | f \.tpz$ | f \.tar.Z$ | f \.tar.z$ | f \.tar.bz2$ | f \.tar.F$ & t r & ! t t +z Extract compressed tar file to subdirectory + unset D + set gzip -cd + case %f in + *.tar.F) D=`basename %f .tar.F`; set freeze -dc;; + *.tar.Z) D=`basename %f .tar.Z`;; + *.tar.bz2) D=`basename %f .tar.bz2`; set bunzip2 -c;; + *.tar.gz) D=`basename %f .tar.gz`;; + *.tar.z) D=`basename %f .tar.z`;; + *.tgz) D=`basename %f .tgz`;; + *.tpz) D=`basename %f .tpz`;; + esac + mkdir "$D"; cd "$D" && ("$1" "$2" ../%f | tar xvf -) + ++ t t +Z Extract compressed tar files to subdirectories + for i in %t ; do + set gzip -dc + unset D + case "$i" in + *.tar.F) D=`basename "$i" .tar.F`; set freeze -dc;; + *.tar.Z) D=`basename "$i" .tar.Z`;; + *.tar.bz2) D=`basename "$i" .tar.bz2`; set bunzip2 -c;; + *.tar.gz) D=`basename "$i" .tar.gz`;; + *.tar.z) D=`basename "$i" .tar.z`;; + *.tgz) D=`basename "$i" .tgz`;; + *.tpz) D=`basename "$i" .tpz`;; + esac + mkdir "$D"; (cd "$D" && "$1" "$2" "../$i" | tar xvf -) + done + ++ f \.gz$ | f \.tgz$ | f \.tpz$ | f \.Z$ | f \.z$ | f \.bz2$ & t r & ! t t +c Convert gz<->bz2, tar.gz<->tar.bz2 & tgz->tar.bz2 + unset D + unset EXT + case %f in + *.Z) EXT=Z;; + *.bz2) EXT=bz2;; + *.gz) EXT=gz;; + *.tgz) EXT=tgz;; + *.tpz) EXT=tpz;; + *.z) EXT=z;; + esac + case "$EXT" in + bz2|Z|gz|z) D=`basename %f ."$EXT"`;; + tgz|tpz) D=`basename %f ."$EXT"`.tar;; + esac + if [ "$EXT" = "bz2" ]; then + bunzip2 -v %f + gzip -f9 -v "$D" + else + gunzip -v %f + bzip2 -v "$D" + fi + ++ t t +C Convert gz<->bz2, tar.gz<->tar.bz2 & tgz->tar.bz2 + for i in %t ; do + unset D + unset EXT + case "$i" in + *.Z) EXT=Z;; + *.bz2) EXT=bz2;; + *.gz) EXT=gz;; + *.tgz) EXT=tgz;; + *.tpz) EXT=tpz;; + *.z) EXT=z;; + esac + case "$EXT" in + bz2|Z|gz|z) D=`basename "$i" ."$EXT"`;; + tgz|tpz) D=`basename "$i" ."$EXT"`.tar;; + esac + if [ "$EXT" = "bz2" ]; then + bunzip2 -v "$i" + gzip -f9 -v "$D" + else + gunzip -v "$i" + bzip2 -v "$D" + fi + done + ++ x /usr/bin/open | x /usr/local/bin/open & x /bin/sh +o Open next a free console + open -s -- sh diff --git a/mc/skins/nord.ini b/mc/skins/nord.ini new file mode 100644 index 0000000..172dd6c --- /dev/null +++ b/mc/skins/nord.ini @@ -0,0 +1,175 @@ +[skin] + description = Nord + truecolors = true + +[Lines] + horiz = ─ + vert = β”‚ + lefttop = β”Œ + righttop = ┐ + leftbottom = β”” + rightbottom = β”˜ + topmiddle = ┬ + bottommiddle = β”΄ + leftmiddle = β”œ + rightmiddle = ─ + cross = β”Ό + dhoriz = ─ + dvert = β”‚ + dlefttop = β”Œ + drighttop = ┐ + dleftbottom = β”” + drightbottom = β”˜ + dtopmiddle = ┬ + dbottommiddle = β”΄ + dleftmiddle = β”œ + drightmiddle = ─ + +[aliases] + black = #3b4252 + red = #bf616a + green = #a3be8c + yellow = #ebcb8b + blue = #81a1c1 + purple = #b48ead + cyan = #88c0d0 + white = #e5e9f0 + brightblack = #4c566a + brightred = #bf616a + brightgreen = #a3be8c + brightyellow = #ebcb8b + brightblue = #81a1c1 + brightpurple = #b48ead + brightcyan = #8fbcbb + brightwhite = #eceff4 + background = #2e3440 + foreground = #d8dee9 + +[core] + _default_ = foreground;background + selected = white;gray + marked = brown;background + markselect = brown;gray + gauge = background;white + input = magenta;background + inputmark = magenta;gray + inputunchanged = blue;background + commandlinemark = background;white + reverse = brown;background + header = white;background + disabled = gray;background + #inputhistory = + #commandhistory = + +[dialog] + _default_ = white;background + dhotnormal = brown;background + dfocus = white;gray + dhotfocus = brown;gray + dtitle = brown;background + +[error] + _default_ = red;background + errdfocus = red;gray + errdhotnormal = brightred;background + errdhotfocus = brown;gray + errdtitle = brown;background + +[filehighlight] + directory = blue; #bold + executable = brightgreen; + symlink = foreground; + hardlink = + stalelink = brightred; + device = brightmagenta; + special = gray; + core = red; + temp = gray; + archive = magenta; + doc = + source = brightcyan; + media = green; + graph = cyan; + database = brightred; + +[menu] + _default_ = white;background + menusel = white;gray + menuhot = brown;background + menuhotsel = brown;gray + menuinactive = foreground;background + +[popupmenu] + _default_ = white;background + menusel = white;gray + menutitle = white;background + +[buttonbar] + button = foreground;background + hotkey = brown;background + +[statusbar] + _default_ = white;background + +[help] + _default_ = white;background + helpitalic = red;background + helpbold = brown;background + helplink = gray;background + helpslink = white;gray + helptitle = brown;background + +[editor] + _default_ = lightgray;background + editbold = white;gray + editmarked = white;gray + editwhitespace = gray;background + editlinestate = white;cyan + bookmark = white;red + bookmarkfound = white;gray + editrightmargin = brightblue;background + #editbg = + editframe = gray; + editframeactive = white; + editframedrag = brightblue; + +[viewer] + _default_ = lightgray;background + viewbold = brown;background + viewunderline = brightred;background + viewselected = brown;gray + +[diffviewer] + changedline = blue;gray + changednew = red;gray + changed = white;gray + added = white;brown + removed = white;red + error = red;white + +[widget-common] + sort-sign-up = ↑ + sort-sign-down = ↓ + +[widget-panel] + sort-up-char = ↑ + sort-down-char = ↓ + hiddenfiles-show-char = β€’ + hiddenfiles-hide-char = β—‹ + history-prev-item-char = Β« + history-next-item-char = Β» + history-show-list-char = ^ + filename-scroll-left-char = Β« + filename-scroll-right-char = Β» + +[widget-scollbar] + first-vert-char = ↑ + last-vert-char = ↓ + first-horiz-char = Β« + last-horiz-char = Β» + current-char = β–  + background-char = β–’ + +[widget-editor] + window-state-char = ↕ + window-close-char = βœ• diff --git a/neomutt/install.sh b/neomutt/install.sh new file mode 100644 index 0000000..75e399a --- /dev/null +++ b/neomutt/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/neomutt + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/muttrc -t "$config" +} diff --git a/neomutt/muttrc b/neomutt/muttrc new file mode 100644 index 0000000..4eb5d08 --- /dev/null +++ b/neomutt/muttrc @@ -0,0 +1,102 @@ +# Settings + +set abort_nosubject=no +set attribution="* %n [%d]" +set date_format="!%Y-%m-%d %T%Z" +set delete=yes +set edit_headers=yes +set fast_reply=yes +set help=no +set history=1000 +set include=yes +set index_format="%4C %Z %[!%d/%m] %-24.24n %s" +set mime_forward=ask-no +set move=no +set pgp_verify_sig=no +set print=ask-yes +set reverse_name=yes +set reverse_realname=yes +set save_history=1000 +set sort_aux=date-sent +set sort=threads +set status_format="%f%> %?n?(%n)? %?M?%M/?%m%?n? " +set status_on_top=yes +set tilde=yes +set text_flowed=yes +set editor='vim "+setlocal filetype=mail fo+=naw tw=72 comments+=nb:>"' +set visual='vim "+setlocal filetype=mail fo+=naw tw=72 comments+=nb:>"' + +set certificate_file="~/.cache/mutt/certificates" +set header_cache="~/.cache/mutt/headers" +set history_file="~/.cache/mutt/history" +set message_cachedir="~/.cache/mutt/bodies" + +ignore * +unignore from subject to cc reply-to date +hdr_order date to cc reply-to from subject + +bind browser select-entry +bind index,pager w sync-mailbox +bind index display-message +bind pager exit +macro index "?" "kutu seΓ§" +macro index,pager,browser \e "=[Gmail]/GΓΆnderilmiş Postalar" "gΓΆnderilen postalara geΓ§" +macro index,pager,browser \e "!" "gelen kutusuna geΓ§" +macro index,pager \eo "?" "kutu seΓ§" + +# IMAP + +unset record +set copy=no +set imap_check_subscribed=yes +set imap_keepalive=120 +set folder="imaps://imap.gmail.com:993" +set spoolfile="+INBOX" +set postponed="+[Gmail]/Taslaklar" +set query_command="goobook query '%s'" + +set smtp_url=smtp://$imap_user:$imap_pass@smtp.gmail.com:587/ + +# Colors + +color attachment brightyellow black +color body brightblue default "((ftp|http|https)://|news:)[^ >)\"\t]+" +color body color198 default "(^| )\\*[-a-z0-9*]+\\*[,.?]?[ \n]" +color body color198 default "(http|https|git)://gist[.]github[.]com/.*" +color body cyan default "[-a-z_0-9.+]+@[-a-z_0-9.]+" +color body green default "(^| )_[-a-z0-9_]+_[,.?]?[ \n]" +color body green default "(^| )_[-a-z0-9_]+_[,.?]?[\n]" +color hdrdefault color153 color233 +color header brightyellow black 'from:' +color header color120 black 'subject:' +color index brightyellow black ~T # Tagged +color index color153 black '~P' # Mail from me +color index magenta black ~F # Flagged +color index red black ~D # Deleted +color index yellow black ~N # New +color index yellow black ~O # Old +color indicator brightwhite color240 +color markers brightred black +color normal white black +color quoted1 color66 color232 +color quoted2 color32 color232 +color quoted3 color30 color232 +color quoted4 color99 color232 +color quoted5 color36 color232 +color quoted6 color114 color232 +color quoted7 color109 color232 +color quoted8 color41 color232 +color quoted9 color138 color232 +color quoted color107 color232 +color signature color240 color232 +color status black color111 +color tilde color240 black +color tree color198 black + +# Hooks + +folder-hook . 'push ~N|~F|~d<3m' + +# Local + +source local diff --git a/npm/install.sh b/npm/install.sh new file mode 100644 index 0000000..0a346e8 --- /dev/null +++ b/npm/install.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +if command -v npm &>/dev/null; then + npm config set prefix ~/.local + npm config set cache ~/.cache/npm +fi diff --git a/nvim/init.lua b/nvim/init.lua new file mode 100644 index 0000000..c7c7e49 --- /dev/null +++ b/nvim/init.lua @@ -0,0 +1,1070 @@ +--- +-- Most parts are adapted from Fatih's dptfiles: https://github.com/fatih/dotfiles +--- + +------------------------------------------------------------------------------------------------------------------------ +-- Initialize +------------------------------------------------------------------------------------------------------------------------ + +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.loop.fs_stat(lazypath) then ---@diagnostic disable-line: undefined-field + vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", -- latest stable release + lazypath, + }) +end +vim.opt.rtp:prepend(lazypath) + +local diag_format = function(d) + return string.format("[%s] %s", d.code, d.message) +end + +vim.diagnostic.config({ + virtual_text = { + format = diag_format, + }, + float = { + format = diag_format, + }, + start_on = false, +}) + +------------------------------------------------------------------------------------------------------------------------ +-- Plugins +------------------------------------------------------------------------------------------------------------------------ + +require("lazy").setup({ + -- L3MON4D3/LuaSnip + { + "L3MON4D3/LuaSnip", + dependencies = { "rafamadriz/friendly-snippets" }, + config = function() + require("luasnip.loaders.from_vscode").lazy_load() + end + }, + + -- Rawnly/gist.nvim + { + "Rawnly/gist.nvim", + cmd = { "GistCreate", "GistCreateFromFile", "GistsList" }, + config = true, + }, + + -- Wansmer/treesj + { + "Wansmer/treesj", + dependencies = { "nvim-treesitter/nvim-treesitter" }, + keys = { "m", "j", "s" }, + config = function() + require("treesj").setup({ + -- none + }) + end, + }, + + -- WhoIsSethDaniel/toggle-lsp-diagnostics.nvim + { + "WhoIsSethDaniel/toggle-lsp-diagnostics.nvim", + config = function() + require("toggle_lsp_diagnostics").init(vim.diagnostic.config()) + end, + }, + + + -- bronson/vim-visual-star-search + { + "bronson/vim-visual-star-search" + }, + + -- direnv/direnv.vim + { + "direnv/direnv.vim" + }, + + -- ethanholz/nvim-lastplace + { + "ethanholz/nvim-lastplace", + config = function() + require("nvim-lastplace").setup({ + lastplace_ignore_buftype = { "quickfix", "nofile", "help" }, + lastplace_ignore_filetype = { "gitcommit", "gitrebase", "svn", "hgcommit" }, + lastplace_open_folds = true, + }) + end, + }, + + -- folke/todo-comments.nvim + { + "folke/todo-comments.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + opts = {}, + }, + + -- folke/trouble.nvim + { + "folke/trouble.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + opts = { + }, + config = function() + vim.keymap.set("n", "xx", function() require("trouble").toggle() end) + vim.keymap.set("n", "xw", function() require("trouble").toggle("workspace_diagnostics") end) + vim.keymap.set("n", "xd", function() require("trouble").toggle("document_diagnostics") end) + vim.keymap.set("n", "xq", function() require("trouble").toggle("quickfix") end) + vim.keymap.set("n", "xl", function() require("trouble").toggle("loclist") end) + vim.keymap.set("n", "gR", function() require("trouble").toggle("lsp_references") end) + end, + + }, + + -- folke/neodev.nvim + { + "folke/neodev.nvim", + opts = {} + }, + + -- gbbrod/nord.nvim + { + "gbprod/nord.nvim", + lazy = false, + priority = 1000, + config = function() + require("nord").setup({}) + vim.cmd.colorscheme("nord") + end, + }, + + -- ggandor/lightspeed.nvim + { + "ggandor/lightspeed.nvim" + }, + + -- hrsh7th/nvim-cmp + { + "hrsh7th/nvim-cmp", + dependencies = { + "hrsh7th/cmp-nvim-lsp", + "hrsh7th/cmp-buffer", + "L3MON4D3/LuaSnip", + "saadparwaiz1/cmp_luasnip", + "onsails/lspkind-nvim", + }, + config = function() + local cmp = require("cmp") + local luasnip = require("luasnip") + local lspkind = require("lspkind") + local cmp_autopairs = require("nvim-autopairs.completion.cmp") + + cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done()) + + luasnip.config.setup {} + + local has_words_before = function() + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil + end + + require("cmp").setup({ + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + formatting = { + format = lspkind.cmp_format { + with_text = true, + menu = { + buffer = "[Buffer]", + nvim_lsp = "[LSP]", + nvim_lua = "[Lua]", + }, + }, + }, + mapping = cmp.mapping.preset.insert { + [""] = cmp.mapping.select_next_item(), + [""] = cmp.mapping.select_prev_item(), + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.confirm { select = true }, + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_locally_jumpable() then + luasnip.expand_or_jump() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { "i", "s" }), + [""] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { "i", "s" }), + }, + -- don't auto select item + preselect = cmp.PreselectMode.None, + window = { + documentation = cmp.config.window.bordered(), + }, + view = { + entries = { + name = "custom", + selection_order = "near_cursor", + }, + }, + confirm_opts = { + behavior = cmp.ConfirmBehavior.Insert, + }, + sources = { + { name = "nvim_lsp" }, + { name = "luasnip", keyword_length = 2 }, + { name = "buffer", keyword_length = 5 }, + }, + }) + end, + }, + + -- iamcco/markdown-preview.nvim + { + "iamcco/markdown-preview.nvim", + dependencies = { + "zhaozg/vim-diagram", + "aklt/plantuml-syntax", + }, + build = function() + vim.fn["mkdp#util#install"]() + end, + ft = "markdown", + cmd = { "MarkdownPreview" }, + }, + + -- junegunn/vim-easy-align + { + "junegunn/vim-easy-align", + }, + + -- lukas-reineke/headlines.nvim + { + "lukas-reineke/headlines.nvim", + dependencies = "nvim-treesitter/nvim-treesitter", + cond = false, -- didnt play well with the current colorscheme plugin, waiting to be fixed + config = function() + require("headlines").setup({ + markdown = { + headline_highlights = { + "Headline1", + "Headline2", + "Headline3", + "Headline4", + "Headline5", + "Headline6", + }, + codeblock_highlight = "CodeBlock", + dash_highlight = "Dash", + quote_highlight = "Quote", + }, + }) + end, + }, + + -- lukas-reineke/indent-blankline.nvim + { + "lukas-reineke/indent-blankline.nvim", + main = "ibl", + config = function() + vim.g.indent_blankline_filetype_exclude = { "help", "packer" } + vim.g.indent_blankline_buftype_exclude = { "terminal", "nofile" } + vim.g.indent_blankline_char_highlight = "LineNr" + vim.g.indent_blankline_show_trailing_blankline_indent = false + + local highlight = { + "RainbowRed", + "RainbowYellow", + "RainbowBlue", + "RainbowOrange", + "RainbowGreen", + "RainbowViolet", + "RainbowCyan", + } + + local hooks = require "ibl.hooks" + -- create the highlight groups in the highlight setup hook, so they are reset + -- every time the colorscheme changes + hooks.register(hooks.type.HIGHLIGHT_SETUP, function() + vim.api.nvim_set_hl(0, "RainbowRed", { fg = "#E06C75" }) + vim.api.nvim_set_hl(0, "RainbowYellow", { fg = "#E5C07B" }) + vim.api.nvim_set_hl(0, "RainbowBlue", { fg = "#61AFEF" }) + vim.api.nvim_set_hl(0, "RainbowOrange", { fg = "#D19A66" }) + vim.api.nvim_set_hl(0, "RainbowGreen", { fg = "#98C379" }) + vim.api.nvim_set_hl(0, "RainbowViolet", { fg = "#C678DD" }) + vim.api.nvim_set_hl(0, "RainbowCyan", { fg = "#56B6C2" }) + end) + + require("ibl").setup { + indent = { highlight = highlight }, + enabled = false + } + end, + }, + + -- numToStr/Comment.nvim + { + "numToStr/Comment.nvim", + opts = {}, + lazy = false, + }, + + -- nvim-lualine/lualine.nvim + { + "nvim-lualine/lualine.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + config = function() + require("lualine").setup({ + options = { + icons_enabled = true, + theme = "nord", + section_separators = { "ξ‚°", "ξ‚²" }, + component_separators = { "ξ‚±", "ξ‚³" }, + disabled_filetypes = {}, + }, + sections = { + lualine_a = { "mode", "paste" }, + lualine_b = { + { "branch", icon = "ξœ₯" }, + { + "diff", + color_added = "#a7c080", + color_modified = "#ffdf1b", + color_removed = "#ff6666" + }, + }, + lualine_c = { + { "diagnostics", sources = { "nvim_diagnostic" } }, + function() + return "%=" + end, + "filename", + }, + lualine_x = { "filetype" }, + lualine_y = { + { + "progress", + }, + }, + lualine_z = { + { + "location", + icon = "ξœ”", + }, + }, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = { "filename" }, + lualine_x = { "location" }, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + extensions = {}, + }) + end, + }, + + -- nvim-telescope/telescope.nvim + { + "nvim-telescope/telescope.nvim", + tag = "0.1.1", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-treesitter/nvim-treesitter", + "nvim-tree/nvim-web-devicons", + }, + config = function() + require("telescope").setup({ + extensions = { + fzf = { + fuzzy = true, + }, + }, + }) + + -- To get fzf loaded and working with telescope, you need to call + -- load_extension, somewhere after setup function: + require("telescope").load_extension("fzf") + + -- To get ui-select loaded and working with telescope, you need to call + -- load_extension, somewhere after setup function: + require("telescope").load_extension("ui-select") + end, + }, + + -- nvim-telescope/telescope-fzf-native.nvim + { + "nvim-telescope/telescope-fzf-native.nvim", + build = "make", + }, + + -- nvim-telescope/telescope-ui-select.nvim + { + "nvim-telescope/telescope-ui-select.nvim", + }, + + -- nvim-treesitter/nvim-treesitter + { + "nvim-treesitter/nvim-treesitter", + dependencies = { + "nvim-treesitter/nvim-treesitter-textobjects", + }, + build = ":TSUpdate", + config = function() + require("nvim-treesitter.configs").setup({ + ensure_installed = { + "go", + "gomod", + "lua", + "ruby", + "vimdoc", + "vim", + "bash", + "fish", + "markdown", + "markdown_inline", + "mermaid", + }, + indent = { enable = true }, + incremental_selection = { + enable = true, + keymaps = { + init_selection = "", + node_incremental = "", + node_decremental = "", + scope_incremental = "", + }, + }, + autopairs = { + enable = true, + }, + highlight = { + enable = true, + + -- Disable slow treesitter highlight for large files + disable = function(_, buf) + local max_filesize = 100 * 1024 -- 100 KB + local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf)) + if ok and stats and stats.size > max_filesize then + return true + end + end, + + -- Setting this to true will run `:h syntax` and tree-sitter at the same time. + -- Set this to `true` if you depend on 'syntax' being enabled (like for indentation). + -- Using this option may slow down your editor, and you may see some duplicate highlights. + -- Instead of true it can also be a list of languages + additional_vim_regex_highlighting = false, + }, + textobjects = { + select = { + enable = true, + lookahead = true, + keymaps = { + ["aa"] = "@parameter.outer", + ["ia"] = "@parameter.inner", + ["af"] = "@function.outer", + ["if"] = "@function.inner", + ["ac"] = "@class.outer", + ["ic"] = "@class.inner", + ["iB"] = "@block.inner", + ["aB"] = "@block.outer", + }, + }, + move = { + enable = true, + set_jumps = true, + goto_next_start = { + ["]]"] = "@function.outer", + }, + goto_next_end = { + ["]["] = "@function.outer", + }, + goto_previous_start = { + ["[["] = "@function.outer", + }, + goto_previous_end = { + ["[]"] = "@function.outer", + }, + }, + swap = { + enable = true, + swap_next = { + ["sn"] = "@parameter.inner", + }, + swap_previous = { + ["sp"] = "@parameter.inner", + }, + }, + }, + }) + end, + }, + + -- preservim/vim-pencil + { + "preservim/vim-pencil", + + config = function() + vim.cmd([[ + augroup pencil + autocmd! + autocmd FileType markdown,mkd call pencil#init() | PencilOff + autocmd FileType text call pencil#init() | PencilOff + augroup END + let g:pencil#textwidth = 120 + ]]) + end, + }, + + -- ramojus/mellifluous.nvim + { + "ramojus/mellifluous.nvim", + }, + + -- rgroli/other.nvim + { + "rgroli/other.nvim", + config = function() + require("other-nvim").setup({ + mappings = { + "rails", --builtin mapping + { + pattern = "(.*).go$", + target = "%1_test.go", + context = "test", + }, + { + pattern = "(.*)_test.go$", + target = "%1.go", + context = "file", + }, + { + pattern = "(.*).sevgi$", + target = "%1.sevgi", + context = "script", + }, + { + pattern = "(.*).svg$", + target = "%1.svg", + context = "output", + }, + }, + }) + + vim.api.nvim_create_user_command("A", function(opts) + require("other-nvim").open(opts.fargs[1]) + end, { nargs = "*" }) + + vim.api.nvim_create_user_command("AV", function(opts) + require("other-nvim").openVSplit(opts.fargs[1]) + end, { nargs = "*" }) + + vim.api.nvim_create_user_command("AS", function(opts) + require("other-nvim").openSplit(opts.fargs[1]) + end, { nargs = "*" }) + end, + }, + + -- roktas/turkish.nvim + { + "roktas/turkish.nvim", + config = function() + require("turkish").defaults() + end, + branch = "edge", + }, + + -- samjwill/nvim-unception + { + "samjwill/nvim-unception", + lazy = false, + init = function() + vim.g.unception_block_while_host_edits = true + end, + }, + + -- windwp/nvim-autopairs + { + "windwp/nvim-autopairs", + config = function() + require("nvim-autopairs").setup({ + check_ts = true, + }) + end, + }, + + ------------------------------------------------------------------------------------------------------------------------ + --- Language Server Protocol Settings + ------------------------------------------------------------------------------------------------------------------------ + + -- neovim/nvim-lspconfig + { + "neovim/nvim-lspconfig", + config = function() + -- General + + local lspconfig = require("lspconfig") + + local capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol + .make_client_capabilities()) + capabilities.textDocument.completion.completionItem.snippetSupport = true + + vim.api.nvim_create_autocmd("LspAttach", { + desc = "LSP actions", + callback = function(event) + local opts = { buffer = event.buf } + + vim.keymap.set("n", "K", "lua vim.lsp.buf.hover()", opts) + vim.keymap.set("n", "gd", "lua vim.lsp.buf.definition()", opts) + vim.keymap.set("n", "gD", "lua vim.lsp.buf.declaration()", opts) + vim.keymap.set("n", "gi", "lua vim.lsp.buf.implementation()", opts) + vim.keymap.set("n", "go", "lua vim.lsp.buf.type_definition()", opts) + vim.keymap.set("n", "gR", "lua vim.lsp.buf.references()", opts) + vim.keymap.set("n", "gs", "lua vim.lsp.buf.signature_help()", opts) + vim.keymap.set("n", "gr", "lua vim.lsp.buf.rename()", opts) + vim.keymap.set({ "n", "x" }, "gf", "lua vim.lsp.buf.format({async = true})", opts) + vim.keymap.set("n", "ga", "lua vim.lsp.buf.code_action()", opts) + + vim.keymap.set("n", "gl", "lua vim.diagnostic.open_float()", opts) + vim.keymap.set("n", "[d", "lua vim.diagnostic.goto_prev()", opts) + vim.keymap.set("n", "]d", "lua vim.diagnostic.goto_next()", opts) + end + }) + + local cmp = require("cmp") + + cmp.setup({ + sources = { + { name = "nvim_lsp" }, + }, + mapping = cmp.mapping.preset.insert({ + -- Enter key confirms completion item + [""] = cmp.mapping.confirm({ select = false }), + + -- Ctrl + space triggers completion menu + [""] = cmp.mapping.complete(), + }), + snippet = { + expand = function(args) + require("luasnip").lsp_expand(args.body) + end, + }, + }) + + -- Bash + + lspconfig.bashls.setup({}) + + -- Crystal + + lspconfig.crystalline.setup({}) + + -- Javascript + + lspconfig.biome.setup({ + cmd = { "biome-kludge", "lsp-proxy" } + }) + + -- Go + + lspconfig.gopls.setup({ + capabilities = capabilities, + flags = { debounce_text_changes = 200 }, + settings = { + gopls = { + usePlaceholders = true, + gofumpt = true, + analyses = { + nilness = true, + unusedparams = true, + unusedwrite = true, + useany = true, + }, + codelenses = { + gc_details = false, + generate = true, + regenerate_cgo = true, + run_govulncheck = true, + test = true, + tidy = true, + upgrade_dependency = true, + vendor = true, + }, + experimentalPostfixCompletions = true, + completeUnimported = true, + staticcheck = true, + directoryFilters = { "-.git", "-node_modules" }, + semanticTokens = true, + hints = { + assignVariableTypes = true, + compositeLiteralFields = true, + compositeLiteralTypes = true, + constantValues = true, + functionTypeParameters = true, + parameterNames = true, + rangeVariableTypes = true, + }, + }, + }, + }) + + -- Lua + + lspconfig.lua_ls.setup({ + capabilities = capabilities, + settings = { + Lua = { + runtime = { + version = "LuaJIT" + }, + diagnostics = { + globals = { "vim" }, + }, + workspace = { + library = { + vim.env.VIMRUNTIME, + } + }, + } + }, + + + }) + + -- Python + + lspconfig.pylsp.setup({ + settings = { + pylsp = { + plugins = { + pylint = { + enabled = true, + executable = "pylint", + }, + }, + }, + }, + }) + + -- Ruby + + local _timers = {} + + local function setup_ruby_ls_diagnostics(client, buffer) + if require("vim.lsp.diagnostic")._enable then + return + end + + local diagnostic_handler = function() + local params = vim.lsp.util.make_text_document_params(buffer) + client.request("textDocument/diagnostic", { textDocument = params }, + function(err, result) + if err then + local err_msg = string.format("diagnostics error - %s", + vim.inspect(err)) + vim.lsp.log.error(err_msg) + end + if not result then + return + end + vim.lsp.diagnostic.on_publish_diagnostics( + nil, + vim.tbl_extend("keep", params, + { diagnostics = result.items }), + { client_id = client.id }, + {} + ) + end) + end + + diagnostic_handler() -- to request diagnostics on buffer when first attaching + + vim.api.nvim_buf_attach(buffer, false, { + on_lines = function() + if _timers[buffer] then + vim.fn.timer_stop(_timers[buffer]) + end + _timers[buffer] = vim.fn.timer_start(200, diagnostic_handler) + end, + on_detach = function() + if _timers[buffer] then + vim.fn.timer_stop(_timers[buffer]) + end + end, + }) + end + + lspconfig.ruby_ls.setup({ + cmd = { "bundle-kludge", "exec", "ruby-lsp" }, + on_attach = function(client, buffer) + setup_ruby_ls_diagnostics(client, buffer) + end, + }) + + -- Markdown + + lspconfig.marksman.setup({}) + end, + }, +}) + +------------------------------------------------------------------------------------------------------------------------ +-- Global settings +------------------------------------------------------------------------------------------------------------------------ + +vim.g.loaded_netrw = 1 +vim.g.loaded_netrwPlugin = 1 + +vim.o.autochdir = true +vim.o.clipboard = "unnamedplus" +vim.o.comments = "fb:-,fb:+,fb:*,fb::" +vim.o.completeopt = "menuone,noselect" +vim.o.cursorline = true +vim.o.foldenable = false +vim.o.hidden = false +vim.o.incsearch = true +vim.o.list = false +vim.o.mouse = "a" +vim.o.nrformats = "bin,hex,alpha" +vim.o.showmode = false +vim.o.smartindent = true +vim.o.spelllang = "en" +vim.o.termguicolors = true +vim.o.textwidth=140 +vim.o.updatetime = 250 +vim.wo.signcolumn = "yes" + +if vim.fn.has("unix") == 1 then vim.opt.shell = "bash" end + +------------------------------------------------------------------------------------------------------------------------ +-- Filetype settings +------------------------------------------------------------------------------------------------------------------------ + +local filetypeSettingsGroup = vim.api.nvim_create_augroup("FileType settings", { clear = true }) + +-- JSON +vim.api.nvim_create_autocmd("FileType", { + pattern = { "json" }, + group = filetypeSettingsGroup, + callback = function() + vim.o.shiftwidth = 2 + vim.o.tabstop = 2 + vim.o.softtabstop = 2 + vim.o.expandtab = true + end, +}) + +-- Markdown +vim.api.nvim_create_autocmd("FileType", { + pattern = { "markdown" }, + group = filetypeSettingsGroup, + callback = function() + vim.o.textwidth = 120 + end, +}) + +-- Powershell +vim.api.nvim_create_autocmd("FileType", { + pattern = { "ps1" }, + group = filetypeSettingsGroup, + callback = function() + vim.o.expandtab = true + vim.o.shiftwidth = 4 + vim.o.softtabstop = 4 + vim.o.tabstop = 4 + vim.o.textwidth = 140 + end, +}) + +-- SVG +vim.api.nvim_create_autocmd("FileType", { + pattern = { "svg" }, + group = filetypeSettingsGroup, + callback = function() + vim.o.expandtab = true + vim.o.shiftwidth = 2 + vim.o.softtabstop = 2 + vim.o.tabstop = 2 + vim.o.textwidth = 140 + end, +}) + +-- TeX +vim.api.nvim_create_autocmd("FileType", { + pattern = { "tex" }, + group = filetypeSettingsGroup, + callback = function() + vim.o.expandtab = true + vim.o.shiftwidth = 2 + vim.o.softtabstop = 2 + vim.o.tabstop = 2 + vim.o.textwidth = 140 + end, +}) + +-- Direnv + +vim.cmd([[autocmd BufNewFile,BufRead .envrc set filetype=sh]]) +vim.cmd([[autocmd BufNewFile,BufRead direnvrc set filetype=bash]]) + +------------------------------------------------------------------------------------------------------------------------ +-- Tweaks +------------------------------------------------------------------------------------------------------------------------ + +-- Don't replace my clipboard when +vim.api.nvim_set_keymap("n", "", '"_x', { noremap = true, silent = true }) +vim.api.nvim_set_keymap("v", "", '"_x', { noremap = true, silent = true }) + +-- Use instead of for increment/decrement mappings (needed under Tmux) +vim.api.nvim_set_keymap("n", "", "", { noremap = true, silent = true }) +vim.api.nvim_set_keymap("v", "", "", { noremap = true, silent = true }) +vim.api.nvim_set_keymap("n", "", "", { noremap = true, silent = true }) +vim.api.nvim_set_keymap("v", "", "", { noremap = true, silent = true }) + +-- Following lines in section are from Fatih: https://github.com/fatih/dotfiles + +-- Run gofmt/gofmpt, import packages automatically on save +vim.api.nvim_create_autocmd("BufWritePre", { + group = vim.api.nvim_create_augroup("setGoFormatting", { clear = true }), + pattern = "*.go", + callback = function() + local params = vim.lsp.util.make_range_params() + params.context = { only = { "source.organizeImports" } } + local result = vim.lsp.buf_request_sync(0, "textDocument/codeAction", params, 2000) + for _, res in pairs(result or {}) do + for _, r in pairs(res.result or {}) do + if r.edit then + vim.lsp.util.apply_workspace_edit(r.edit, "utf-16") + else + vim.lsp.buf.execute_command(r.command) + end + end + end + + vim.lsp.buf.format() + end +}) + +-- Don't jump forward if I higlight and search for a word +local function stay_star() + local sview = vim.fn.winsaveview() + local args = string.format("keepjumps keeppatterns execute %q", "sil normal! *") + vim.api.nvim_command(args) + vim.fn.winrestview(sview) ---@diagnostic disable-line +end +vim.keymap.set("n", "*", stay_star, { noremap = true, silent = true }) + +-- If I visually select words and paste from clipboard, don't replace my +-- clipboard with the selected word, instead keep my old word in the +-- clipboard +vim.keymap.set("x", "p", "\"_dP") + +-- Search mappings: These will make it so that going to the next one in a +-- search will center on the line it's found in. +vim.keymap.set("n", "n", "nzzzv", { noremap = true }) +vim.keymap.set("n", "N", "Nzzzv", { noremap = true }) + +if vim.env.TMUX then + -- Why "sleep 10ms"? Workaround for neovim/neovim#21856 + vim.cmd([[ + autocmd BufReadPost,FileReadPost,BufNewFile,FocusGained * call system("tmux rename-window '" . expand("%:t") . "'") + autocmd VimLeave,FocusLost * call system("tmux setw automatic-rename") | sleep 10m + ]]) +end + +------------------------------------------------------------------------------------------------------------------------ +-- Commands +------------------------------------------------------------------------------------------------------------------------ + +vim.cmd([[autocmd TextYankPost * lua vim.highlight.on_yank {on_visual = true}]]) +vim.cmd([[command! -nargs=0 WS %s/\s\+$//gce]]) + +------------------------------------------------------------------------------------------------------------------------ +-- Keymaps +------------------------------------------------------------------------------------------------------------------------ + +-- : Diagnostics / No Diagnostics +vim.keymap.set({ "n", "x" }, "", function() require("toggle_lsp_diagnostics").toggle_diagnostics() end, { silent = true }) + +-- : Troubles / No Troubles +vim.keymap.set({ "n", "x" }, "", function() require("trouble").toggle() end) + +-- : Format +-- : Action +-- : Rename +vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("UserLspConfig", {}), + callback = function(event) + -- Buffer local mappings. + -- See `:help vim.lsp.*` for documentation on any of the below functions + local opts = { buffer = event.buf } + + vim.keymap.set({ "n", "x" }, "", vim.lsp.buf.format, opts) + vim.keymap.set({ "n", "v" }, "", vim.lsp.buf.code_action, opts) + vim.keymap.set("n", "", vim.lsp.buf.rename, opts) + end, +}) + +-- <">: Switch Window +vim.keymap.set("", '"', "w") + +-- : Update/Write All +vim.keymap.set({ "n", "x" }, "", ":update") +vim.keymap.set( "i", "", ":update") +vim.keymap.set({ "n", "x" }, "", ":wall") +vim.keymap.set("i", "", ":wall") + +-- : Quit/Quit All +vim.keymap.set({ "n", "x" }, "", ":q", { silent = true }) +vim.keymap.set("i", "", ":q", { silent = true }) +vim.keymap.set({ "n", "x" }, "", ":q!", { silent = true }) + +-- : Yank to end +vim.api.nvim_set_keymap("n", "Y", "y$", { noremap = true, silent = true }) + +-- : Disable search highlight with a simple key +vim.api.nvim_set_keymap("n", "", ":noh", { noremap = true, nowait = true, silent = true }) + +-- <Δ±>: Toggle Split + +local splitted_window = nil + +local function toggle_split(is_vertical) + if splitted_window then + vim.api.nvim_win_close(splitted_window, false) + splitted_window = nil + else + if is_vertical then vim.cmd([[vsplit]]) else vim.cmd([[split]]) end + splitted_window = vim.fn.win_getid() + end +end + +vim.keymap.set("", "Δ±", function() toggle_split(false) end) + +-- <~>: uniq sort +vim.keymap.set("v", "~", ":sort u") + +-- <ΓΆ>: Jump to previous diagnostic +vim.keymap.set({ "n", "x" }, "ΓΆ", function() vim.diagnostic.goto_prev() end) + +-- <Γ§>: Jump to next diagnostic +vim.keymap.set({ "n", "x" }, "Γ§", function() vim.diagnostic.goto_next() end) diff --git a/nvim/install.sh b/nvim/install.sh new file mode 100644 index 0000000..42231d8 --- /dev/null +++ b/nvim/install.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/nvim + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/init.lua -t "$config" +} + +nvim --headless +qall! # Install plugins diff --git a/pylint/install.sh b/pylint/install.sh new file mode 100644 index 0000000..6471f38 --- /dev/null +++ b/pylint/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config} + +install -d "$config" && { + ln -sf "$PWD"/pylintrc -t "$config" +} diff --git a/pylint/pylintrc b/pylint/pylintrc new file mode 100644 index 0000000..d187077 --- /dev/null +++ b/pylint/pylintrc @@ -0,0 +1,7 @@ +[MESSAGES CONTROL] + +disable = missing-function-docstring, missing-module-docstring, missing-class-docstring + +[FORMAT] + +max-line-length=120 diff --git a/rubocop/config.yml b/rubocop/config.yml new file mode 100644 index 0000000..06b934d --- /dev/null +++ b/rubocop/config.yml @@ -0,0 +1,57 @@ +inherit_gem: + rubocop-rails-omakase: rubocop.yml + +require: + - "rubocop-md" + - "rubocop-packaging" + - "rubocop-rake" + +Layout/HashAlignment: + Enabled: true + EnforcedHashRocketStyle: table + EnforcedColonStyle: table +Layout/LineLength: + Max: 120 + Exclude: + - "test/**/*.rb" + +Metrics/BlockLength: + Exclude: + - "test/**/*.rb" + - "*.gemspec" +Metrics/ClassLength: + Exclude: + - "test/**/*.rb" +Metrics/MethodLength: + Exclude: + - "test/**/*.rb" + +Naming/FileName: + Exclude: + - "**/Vagrantfile" + - ".*/**/Vagrantfile" + +Rails/RefuteMethods: + Enabled: false + +Style/AsciiComments: + Enabled: false +Style/Documentation: + Enabled: false +Style/ParallelAssignment: + Enabled: false +Style/LambdaCall: + Enabled: false +Style/MethodCallWithArgsParentheses: + Exclude: + - "**/Vagrantfile" + - ".*/**/Vagrantfile" +Style/FrozenStringLiteralComment: + Exclude: + - "**/Vagrantfile" + - ".*/**/Vagrantfile" + +AllCops: + NewCops: enable + Exclude: + - "vendor/**/*" diff --git a/rubocop/install.sh b/rubocop/install.sh new file mode 100644 index 0000000..cbad69f --- /dev/null +++ b/rubocop/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/rubocop + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/config.yml -t "$config" +} diff --git a/terminal.png b/terminal.png new file mode 100644 index 0000000000000000000000000000000000000000..c2de43995aa01376cefbac218a14b20728356580 GIT binary patch literal 16642 zcmeHt2UL^Wwr*_TR*I;INR?s%DWQj6MY?p5CJ6y4NsxrzR6sfiNCy!Rk={Fmjnb4R zptR5=NC_pVQBe{6V1Oil@nd5zStL1PDY9^UyQG=vcb4Iy#}OZ5`mO7e*pKuP5dcqNs;l{Xs+|y5r&BMSIi|9kDuM~y!yU~rO)#*$%)$lwV8Pq)>ufK zwXmFISXNp5I^M=Malm(bJx<^T1f_BwV)LHw#Iz6Rokkf+o35fSysO~VO8-ZDT$(H7 zd2e0yq>0${zKH>EawUTO?faAV{0p-i@pu(qroC_e+kvTYEOB*kB}#gDgR_0hv)k@V z%KmC$yy~3=Tn;r|n#46KdEOpa?7MBQtxd-6-s6j@FUzLF{9xC#66ezN`c$P-%hMLr zFI-R?AFiH}ER%$3-12;J{>0F8&sQ-Trg1{gl7Hk5o6$1qD=U)0b$uFghR*9; z9qpHSxHm69Yx*Jkdb4aAvzHE*qd6>eR7&uyY~Rjgl=Lx@7}l4!@c5JO{xx6jN8&4* zKd#RVe2tQnJ$oT`A=K^tfafv!=J61)iY%+a=`_2LxUwuoMuu(7B|BqPX4z+YYi~c8 zDsoMhdu`3otM!cL?+AxkAM;nGJ#i(T%HWixpNzp3MgrG8y^360-9huLxZDbZJj1=( zU|QWg>w(S!QQIurysmp^yG*tgpNQoeilUasC6ZkXmLN6!$)jluqxt zrE8NaVv-=e`$6rJcnP8Ob6gR&|EX%7!a_I!8KLllE};l-+_sGCil{=`o>txp4XK z8Z(_ww%fGP5*IVSyugeyLhj!eh+O7b`h@Kc-WFX!mx-4VbG_BKjJF(Y zFlwP6mSMZH$>%BrOo)}-Z({A(H);JMgjB7|p9|xe#`^n=on8@jtDt&YkQ_~i#XKW) zqUz(fvk%p+c1tAR9!vkKKnUAqdnBK2iAa8P_ItHQg&@SygDz+5%C4!6;!@@26Jo)dc83x^W?&&N%@4IOng!zy2s%-1#tqKzRS z;T#SI2{jG>n+C?WFDdR_k^fjS+)*qG``VKGqfjwD`~t6wz=xJ{^=R#TnQpXN#qe+u z>cyTwjMTg5teUnI{uS-=nJdLt);_`mzR~ZLIOw?RT@Sl0>FURJ@nj(EUWB{W$iO2? zhtu|NS;1j@dMf5c6vb=wHg&HlMdBi>%n-biGL?y8+%`*PtE|hqRKqyur-Yg~utDKM z>lq~Syl_C7 zA*-07II{MPYL91xkou^7q(j$i|vnzH-FAHMD zgO#F%{m%}l$edV_bvyM~_FBvW;sm|XEj{C)nXTqA@afU3pYq{MBgnRjr2vPFH||zCd?JtrQa_H%uZ?ao5a{<$gqBvaEcv}HMG)y zzyXWqKrg`Wy*%$+%33AIGjwC~V;R!=JR+$kxi99`WB~csKKw{haj5RoIf0L+>wL>b zPm)a6%|fCZDOEG&9^B&@?k_-OMd7z6%fn(@d+oAsl)qScb&q(x2|e>9@CbEzLL42fgP3N zE+04J3M$k=j=%h2GNLa#``LPVde)m$n1J?JljS!F?ubjH4s-7Zn{wr@t8HmKPY&0e znU~dN9@J@g^&pR#1ufR3<2l%WSE!M(6l;geTt<@-G*u!8 z@6?{vlH2Ey_tGuah4k0bKAI>nZD4pa^P132SoinSJmI3=?4!pe$>=mz9pdl5yPD2l zOWjL37Jg;`Dfi`RygaBj_6JgCjcimpn=g#__${e6AHU(*S2A|{@BJFx_ZvPE1AO?_ zJ=1-O@_}^p7|0$=7G~o^_ej4U2y`sKRzcyeih{!5(k+l=Q@o?3?!1#_Y_ZVI(&18C zWX*V%PJqhkHEZYH^*@tt@ZfXPbRTuPibCJi)Q##(jC)4;;?-gcgh{T`PgqzBc{M|L zb*2uYn_SU;($mx;H6G>Q^(6iqv=44Z%CesVgK-0yN!BD_;o=ll!& z0<$!Byu~eUt42n-Dyi)9 zex!8gT>8rp%IA0G!VFR`p1nB|>AAhj)TqcCV9IcRIzgHKid7pmiM+9{V)X(ZsdIx0 zgB{vzJ9lpA)D>YINxE{W^@mAcvcmPaMpN?FGAczC<#ROW#>sdKO_EB8Jm)=|V(pw0MF!946?5Gytr=`)gU;s5{wjJ{90a2-pumz$d`ZFUG?! zz#{ygC-!gS{a7O=@r!yLUICLbpgOxQOAk-1(->y+s(YX7|nnN|(*diQ{Rvc3Q zmeLCL3!S60lfw~>6^sw=07n3VpaEp?@8~hM*1sOm@Ah*z^WOvk*!_b4JLqwR( zy^1TMV9tk3RTQPz4&@cMLcwgU#E-thLcZH^`mk3}5V z44_!cL*D?9kH&$$h$}e3Eiou3Jrv48itSJ`)NvB`TmIbzai;9K)E9SXE?u-{(>UsgmFbV*=spzLG9o$%pc?YJ>p-Gbbwfg z#yGjF{F6=n7dpwG%=Hei7Uksr8~(cRhd;gj6p$Qjk5t9VdK3i2Enz>YA8qLZw>mlk zK#xC7!5&y5ZQww({n^$2Hg5ZO%$Oez7PJCeTJ!LW2@3KEiHU-Fpw)_3#w)UFTUfQ@kT3ySmev;B0uKOgtM zXFt{=Rxo}r5ZB=%Vo<=B_=S1IAOeCsR!|{P!2GSC5PqTGOZb1kA4$H$1o5}yk~|Ed z8XDriJy6NR5G$^7=t;WHj*bqtaHroN^xq8sAJF|~{m)MJ&zAp|?5EWVC`Wf72tB}P zxg!6N{of({2|?W!21lY%eENq$nxZ}KQ0^G{N@jl#{iB53RhR4AFwi7 zb_M7qkU`ay6+ty18W2s)k77l@$PbQpjL{&_*$aoyF;G&f^!RO>yC=a=XjrSdo=|s}Q;c?I zO{Vqv>oqaz%Uxa5*92o!R>L9_>AR-lI#;cn@X_j{uu*Njb9$Tl&y-xQ1l=;z--?W@ zOfGy{xSYFe_uV@!aJF}9y~x*@aMxSfyE`YwYZKSlO*U=Y5_4e32`Z>W5s}>Ksm=@I z>|CB(RcxxV#_sWN-ptu4$zBJSNKR#(-@b0Kob^(0Zlr=Onu9h`{hB}`#!6tg-AX|D zpvlzW5-?I~+$eapE!oE1or1;3iGqcMozou{taV?Dl2L_`Nl90@ z&wzt2pHvkglQ2E!vZTX|e@Y#+TB?`VrfMTlve<%92D{xxUNsuNr%qDp@*Fs#zHpjaW)%VsDvpH=H^zf6+F} zMSlPLMtBGBzR~)8|87Eu%hElX+0KMZ7g{4j$$i%DFOJsqpHT#u%28Aj+9!8WSnzkf z@S8(kxr6x#<8#+&z|L=s94FoAaE$?Ne(&zHjk{rxFa`+$vUOtr^kud9 zqTnS77g}!|SHNIF!z@2?u|3G4au{|Ijmxo5EFDO@Hsaa&<_VI!;dVs3%;}h*>MtK` z9}f6iM!mPj6NsaONYtykt>wsZsk)u{@nd=h2CZr4!V(@Exej|X)fjil^=~kxebT}} z1MTkSKG^15p?QPI=HjqtvzKS8e2|w&0^1_`IyZuFGOjoC)lH(SMpf=dtIUmCw^S(JNZ4a6^s8BM) zzpKUj;3DmYH!)6PYKP8(hft}1rpV-Gr{!jv>A87~IM#Q;>{KdBjZ&3%HmS+4E-y2~ zwP;}9;eiT81oH@=&&KW`{sVRD2%wB2Ufjj1F$qzu<4z*jdGD^wSGCdS?_=0h*p{o; zW=mX&*xI(d+}37gJ}kevx3gt3^Acp0#nb!5_pM0oqWW8!V(Ffl@Y%*%{ue$o5WWZ3 zaW3774_z`@&9Gi@hmm^7Y#WEyAY|J|0Gk13)nCHdzyMA-M5gxMLb*76d zTyXevSqcNp60=J5MXP!>zMcCVD$Nz5-epa_*@^wx&4$SDrh9|$v_3O^y%7L6IS<9R zMg)11_8)IAUY9Wkj3ghTs3^JhcJEMgV{^id#0exKW-0HYd6iBApfOzE<@#I`#lcs_ zYvYxZ6-ImbI_RFW@1+yj>UKMxIzFiTDq(5(EjKA=)_Q1-k=IxWBpLxbRQ$wz%Fb`SW9PxX76X%*qpa7|h4|U9rc-Av zBC}t341^B9uS_*>@My`&)_m}7sD9_{lqi^QDQNw8rA5!Bh`| zzsSgd9ED5V<**<(Qp?WDz6mje$HY}pJT+%`ZS?FKn@aR${>g@gY4S}X1KJs)T`-xi4N+j;#C-|B>vL#7DafvT!!S?_oenD7xe!Ho_wWXBS zJ_H+1YwvkufH9SFb@u8Pes zBD=QYigbMY2F#$H=> zzBcf31&Rn3QE@V=xxu-W0-VcqeH@=kw3ut_rxX~Ed96StV!~Jysfb@VM(yjp52uz9 zdFeX=q?VP(=xzt0@sgQm_ShZis?D&b5$B3peGA`hOwB+TZUiD!Lrm-jtZ_dLNCIH2 zomJBd6O-;Q->|KM=$VT5jXO{THK6B`%G8vHA}=jcBw(tUy0W3dfza0bip|?SzPzQv z^F!h&xm(!%?u2i%gOzi4EZx;a=Dfn`2V{7~>@j=W*!VM*$3N)gRDTJvbyhyDWZAaf z8_E|(AV`&XwR}kNm9c7{6od8IDm7@{N`Buw*>t^?woHcEtWHF_W_M$du7#N9_90Xs z+8Rc$zuP2`EJEjuqX#>=;Zyz8Yd6EUpFad6M~B>&Yv`bBGgWx+>(rr%g4u1QaBk=Z zp#lg?4BkuaQS2wLGD(xM+ZEwDXx$EDk=IPib{z|8yCF5>@jgC|=*_Ol_0@GwKA@tf>R9{nun2%s%K22Aw!^ZSq1ypb&l3OP5{Hysbna!9$m zV_~G$t1@-w7A_ic5tdqENO4<{0}cm&=_x9ZkRR&1;Sht>OJ z**+i;2t&n9oF^$sOzZS_KlLl7`7CGMeux?GESoB7Tn(r`Xk;#uNOEb(VhQF@nd%?( z$!dzK)8h&bB-WL+Ovt2awkh-0UBm7eiYki7;3OitBQvYB91=M%zZgijjpmdMR$*<%bq(C73w0 zw-=g4@6SCx!dx}6tJBnGR_vv_w^n2k78KOqMir4P{jf5P#KcdwwK&{A?ZhC8j38(6 zC}*80%kllt-y_XEiw~va3vXjS@T1F9?DTcE%s1K@r!vz2oFL{pvwqF5=q|4Nhp{@k zb@vps&``s=nf!&w01Ql9Rc$5`$91*GnSL9DYH5MJ_F@ubZ!*YN=!z3A@s_bWA8KJ`tSo+YTR zk14YT`4Gu(lNVO@Lc>uS&WF<#$wlGz$UW=iQJ0J%+`H(n_EY3CwRJDi?XJUKGk3$B zU2ZiFTkNs>)6n4Pur#5ly#1DY2mRMtn;E3jwk{*i`{P^>z?DQ2%+i%A9ueldvoZQc z#RjVL`Puf=_3nsO0lE$rE%0S+&!QR_PfXhjwK6)hQjD?W_n`|+q>EAb_fdoA3yn&+ zuzOhy(3TK=O8JtHxNg7_GxGEE@Au#*n-lD4HC7H!p5(g$#OF^ZXiwa*WVz3U*w{o@)&@;S2 zy9an>u+8$5+DuqWy|4m0&7@?;ae7V0Nh(E0xOA>6^~UDrIc-lV1X@1F2s|_jp_rSf zYU&-yEn#N|;_vLDpwn&NbSOU?RPEZ7p;E+KL=pDVVQLW&7VbS**M&`m4=UwK9@KLa z-=OmOcs#i6`Vtc)mtR${e6V!}Zv%C4SW;4J!oj%F65Bi ztMSqqX0i6T?Os_@?asI$5-SM>@Y2!p@(jSvxsuFM%sI^Zxv1K?cDCQ z2!mXdI8%j{lmR3MPlokF-=ipGJ}NyYDX+%ejrgZCbxw^`3fb z3(LqK-=Oj4u2a$wkAW$a>3$rB6+=)h9q~nBfy_SY6goEVo@#*a%YKp8-zlgv#T(rC z{P}Z<)q5T83_nH7Li<%hVDt@#WF}(JgR;vG)GeozBVHTf6qG}oh+|I5uXHF6!n;zW zIZ3OnJ*|s9UN;329g-auTEgDyN*@f*?O-jzi|=NYb%+kHL$D3($#{^lE)l{ca=JrD z#ZBdycZ%>x>LGF3-)*ohHSa)=d6^B42Lc=?Ix))ppCb-xH6KSNnhxcCu)dumYL+%A=6=fZJdN)4Pd>T0 zHDI>?OO z-;6V=(){rwR=e6}Yjf_i&HZGb2~IV`R%gQl+n6o#`~$arxNeS~q{M9O_Ky%7X5kd4 zaNlXE6Uj;M+y#3=0H(RSXDfxyP%}xMqct<}RsH_*@jeW2isL=Ft;>EwP=!#q zk>|T_sMuVIkYISK!Q4||guXH0aU)j3;DtZukACxWfW@bMECgY4l>Q`Ro9WW7H@Dn z8kz5>?y})8Hq{rnty)NorW7T3+a7i{{MrWcy#;-Cae*nV&EQn2rOpH}>|SUisbG>l}SGt(nw@0+c zQkyf9M%V**w9AT$t5);eZG79l-%U)D{O08K;KSULQR$3pF~QlhMI}luuNm_P{T2oa zA}2_ja^O4WFFZ*BZk`=+3C`o4Z}RgcXI4Ld_MFPeP79Ca_I^f@#SlRA<&I^JqNP83 zz{lVWezpVl0JY_9_Y@4NCW_16yA|F)KeXMs#G))68*acN0ts%7Bu->UGpLs_LO?n{P7CzdPRj!yC$9n@PtE}!a;HI{N3177AlY-rfp**JW5ADsfL}?2 zo>#8U@QS&u-?BeD(jI1P23xP@HBkJ)ZQJlHKHPA?ga#x#OC|qusneYxtLT5@)-gH@ zXAecirp#~4Y2$s1@FFb9n(rj&?nO=dfb$V=^*gAHX*kaZWNS(dhXDL7O%_HtgCBc; z2*WkCDqRc#gpwPwBQoe+%8rmEbPedZWQRpNA=KF7n=m#apN z6|a{|%%ya|Z?udvWg0wQ-4jNZ%y`y^C365VG&~&J;8{uVj9>Ndl}=g^TTlv#*K6LW@ccdc>zx60y!0& zVQ(xhb>3**`kn3^*~ZP#VD{SP?*;R3#^Y^!t6P##Hdm^i@k;tSDMmLN9?TRD)!3sH z6|KrNdYsz|rB*(?rEOc18So=7TiHfU1XKIgd#*27R8M@B^qE*Ss&F#_+7T|q(&}#^ z55cR?Nt`uQ9-D+KnXOd^qqQ!?^9M_3`|-POD!)7y<;73E#TV|+4apfL;Uc5umE|I;!yl;E`)9bhb8J}py7-jy2p7a|0CAKq6 zH%|h#eypNRy97zAqRwnWGsfi<*u!8?^_eL^@NyfJKN?GWQYL1ge?XeG=lJW?DBU5}1M6$m_tCh%)FqW7@UA?RB9MEY)Uuh0k*+u;?-! zHyt8WX3tuwZ06(WL*Vq|eV048-%rSV$vy-6n0|5T%3H8P2j1K71MG8a(%iUk@J)SM zXHhw==n=>FSq+7W3kFfm%if7YzWlhk@6DN}l>@5}Lxm>PMGh5MQWs1;02!#RDa7UN z#~?OK`MNBaRnGSoq24hON9;lDYz!NPKZG$Jiw#dBO+^`%A<_Bw>Tddc4^^JZZghLq zYx_poN2Br)T_Y`2ig5{YNj^S=!`l0mXDGJPrYNNL^4|V_2mVP%9(3LRSb)2(3MUae zK71!D`m$8|=6ZL7a>|E9RnBmdP=$lyl5LGj-yU$*qw-?Kjn|eBb~=1AKp-Z~-iUK9 zMR%Yb-I#nJzL>aV!Bq8?I>jpNIkb0grkkkF%>lijW$)q3Qst7lTkt8_25SB>-y68; z?6^3>^+(tS!LiqCJmn4|(B(Zi*tu^A@Nuv!snjJ=c|uxhAwqK?;C2L?afOSnsq=iN zQO#x;neu70nVNC?<@(})?9hl8Vyw3#i5AZ8$Z&J&ZJj zDW~eW7T|j&zfbQ0Ejj^d;obUHOV8$t=Sxg}G}`CE+asglE5HNZe?rrnS(?!#?m6}N zE0Z+?jUT|$;cZlJe3yv#G*`xcWF?#(x?>UuZFxE~Hu2G$Jkpo1p|*bcUfXS)TEoKe zvSEk4wg#;hKBDjICV`s5EC(XcjC6@?3JU64*lIrX#q}}Oxgf>PAB<%QhAn~!=tIUGHII-Ei z!c#RZiY9Zzb@uCvV?e7==AjY1e!F?ZZ9nS+yCyxN+a)dhvsz_a@VhHM2osNO8M+`j zpp>|zid8Q1*t(-cjG}Z6qh|atFgB9GiKk-GyL19QI^6(t&6Y-*X&LMe6T|>YcktcU zvc+yQPkh^!WQyP`C+{w`wfMHBElItXtm;#(_Ph{6!$Fc@AgmzpJDvqgJ{1*F$-F8I zGXQQ*iaQV2TG1orF;L?2iIqK={VHh$xaXC4#$9LVo~KX^N;Fk$tFl-~_^^HNOz- zVH*D=d~2vEUMX62>Rnl0{^+IVNrs|)zIG$mgY`ITKF^H}QIj2ztakbC)xdEn9VG~t z0RfL3j*STJepKT4=)1$28sUB zo#P*}5}#9d0Dc|7c=%g@-(OSy;gUZh`>QSKS55z~#Qopd_Fu^AXn+6wO8Kvq=*dSe zAm;u5?w^0PR*%l;Py6Q|Iom(C-oHAL97*(7`{ZA3sQ+(#@{c-7|62F|1?{i4p1(eM h6#UcTPCVm)S~H_jGH#0E2@n)PDoUD)h4S~G{2zodxuO67 literal 0 HcmV?d00001 diff --git a/tmux/bin/editor b/tmux/bin/editor new file mode 100755 index 0000000..6f4addd --- /dev/null +++ b/tmux/bin/editor @@ -0,0 +1,4 @@ +#!/bin/sh + +# Direnv doesn't properly work under some programs, e.g. tmux + midnight commander combo. +exec direnv exec . "$(command -v nvim)" "$@" diff --git a/tmux/bin/viewer b/tmux/bin/viewer new file mode 100755 index 0000000..805eb3e --- /dev/null +++ b/tmux/bin/viewer @@ -0,0 +1,4 @@ +#!/bin/sh + +# Direnv doesn't properly work under some programs, e.g. tmux + midnight commander combo. +exec direnv exec . "$(command -v bat)" --paging=always "$@" diff --git a/tmux/install.sh b/tmux/install.sh new file mode 100644 index 0000000..19e3c84 --- /dev/null +++ b/tmux/install.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/tmux + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/tmux.conf -t "$config" +} + +install -d "$HOME"/.local/bin && { + find "$PWD"/bin -executable -type f -print0 | xargs -0 ln -t "$HOME"/.local/bin -sf +} diff --git a/tmux/tmux.conf b/tmux/tmux.conf new file mode 100644 index 0000000..349174b --- /dev/null +++ b/tmux/tmux.conf @@ -0,0 +1,78 @@ +# ---------------------------------------------------------------------------------------------------------------------- +# Settings +# ---------------------------------------------------------------------------------------------------------------------- + +set -g default-command "/usr/bin/fish" +set -g default-shell "/bin/bash" +set -g history-limit 50000 +set -g message-style bg=default,fg=yellow,bold +set -g set-titles on +set -g set-titles-string "#W" +set -g status-interval 1 +set -g status-justify centre +set -g status-left " #[fg=cyan,bold]#h#[default]" +set -g status-left-length 32 +set -g status-right " #[fg=cyan]#(LC_TIME=tr_TR.UTF-8 date +'%%A') #[fg=cyan,bold]%Y-%m-%d#[default] #[fg=white,bold]%H:%M#[default]:%S#[default] " +set -g status-style bg=default,fg=default +set -ga terminal-overrides ",alacritty:Tc" +set -ga terminal-overrides ",screen-256color:Tc" +set -ga terminal-overrides ",tmux-256color:Tc" +set -ga terminal-overrides ",xterm-256color:Tc" +set -sg escape-time 10 +set -wg aggressive-resize on +set -wg automatic-rename on +set -wg monitor-activity on +set -wg mouse on +set -wg pane-base-index 1 +set -wg window-status-current-format "#[bg=red,fg=white,bold] #I #[default] #[fg=white,bold]#W#[fg=default]" +set -wg window-status-format "#[fg=cyan,bold]#I#[default] #W#F#[fg=default] " +set -wga window-status-activity-style fg=default,noreverse + +# ---------------------------------------------------------------------------------------------------------------------- +# Bindings +# ---------------------------------------------------------------------------------------------------------------------- + +set -g prefix C-a + +unbind % ; bind % split-window -h -c "#{pane_current_path}" +unbind '"' ; bind '"' split-window -c "#{pane_current_path}" +unbind -n M-0 ; bind -n M-0 select-window -t 0 +unbind -n M-1 ; bind -n M-1 select-window -t 1 +unbind -n M-2 ; bind -n M-2 select-window -t 2 +unbind -n M-3 ; bind -n M-3 select-window -t 3 +unbind -n M-4 ; bind -n M-4 select-window -t 4 +unbind -n M-5 ; bind -n M-5 select-window -t 5 +unbind -n M-6 ; bind -n M-6 select-window -t 6 +unbind -n M-7 ; bind -n M-7 select-window -t 7 +unbind -n M-8 ; bind -n M-8 select-window -t 8 +unbind -n M-9 ; bind -n M-9 select-window -t 9 +unbind -n M-\" ; bind -n M-\" last-window +unbind C ; bind C new-window -c "#{pane_current_path}" -n "mc" "exec bash -c mc" +unbind C-a ; bind C-a last-window +unbind R ; bind R source ~/.config/tmux/tmux.conf +unbind b ; bind b new-window -c "#{pane_current_path}" -n "bash" "exec bash" +unbind c ; bind c new-window -c "#{pane_current_path}" -n "sh" "exec fish" +unbind q ; bind q kill-window + +unbind -T root F12 ; bind -T root F12 new-window -c '#{pane_current_path}' -n search 'exec search' +unbind -T root S-F12 ; bind -T root S-F12 new-window -c $DOCPATH -n doc 'exec search' +unbind -T root F9 ; bind -T root F9 run-shell " \ + if [ #I = 9 ]; then \ + tmux last-window; \ + elif tmux list-windows -F '##I' | grep -w -q 9; then \ + tmux select-window -t9; \ + else \ + tmux new-window -c '#{pane_current_path}' -n play -t9; \ + fi \ +" + + +# ---------------------------------------------------------------------------------------------------------------------- +# Tweaks +# ---------------------------------------------------------------------------------------------------------------------- + +if-shell '[ -n "$SSH_CONNECTION" ]' 'set -g prefix2 C-b; unbind C-b; bind C-b last-window; set -g status-position top' + +set-environment -g EDITOR "editor" +set-environment -g VIEWER "viewer" +set-environment -g COLORTERM "truecolor" diff --git a/todo/actions/e b/todo/actions/e new file mode 120000 index 0000000..8491ab9 --- /dev/null +++ b/todo/actions/e @@ -0,0 +1 @@ +edit \ No newline at end of file diff --git a/todo/actions/edit b/todo/actions/edit new file mode 100755 index 0000000..1686670 --- /dev/null +++ b/todo/actions/edit @@ -0,0 +1,16 @@ +#!/bin/bash +case $1 in +"usage") + echo "$(basename $0) [BASENAME]" + echo " Open \$TODO_DIR/BASENAME.txt in \$EDITOR." + echo " If BASENAME is not given, defaults to 'todo'." + ;; +*) + FILE=${2:-todo}.txt + if [ -n "$EDITOR" ]; then + $EDITOR $TODO_DIR/$FILE + else + echo "Error: The EDITOR environment variable is not set" + fi + ;; +esac diff --git a/todo/actions/n b/todo/actions/n new file mode 120000 index 0000000..0aee50c --- /dev/null +++ b/todo/actions/n @@ -0,0 +1 @@ +note \ No newline at end of file diff --git a/todo/actions/note b/todo/actions/note new file mode 100755 index 0000000..45a7617 --- /dev/null +++ b/todo/actions/note @@ -0,0 +1,3 @@ +#!/bin/bash + +"${EDITOR:-nvim}" "$TODO_DIR"/0000.md diff --git a/todo/actions/pr b/todo/actions/pr new file mode 120000 index 0000000..23295da --- /dev/null +++ b/todo/actions/pr @@ -0,0 +1 @@ +projectview \ No newline at end of file diff --git a/todo/actions/projectview b/todo/actions/projectview new file mode 100755 index 0000000..33e66e9 --- /dev/null +++ b/todo/actions/projectview @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# 2009-2011 Paul Mansfield +# License: GPL, http://www.gnu.org/copyleft/gpl.html + +# Stop Verbose lines, thanks to Mark Harrison +TODOTXT_VERBOSE=0 +# Allow control of wrapping if using as simplepv action +NOWRAP=0 + +# Check how we are being run +HOWRUN=$(basename $0) + +# move arguments one to left, therefore eating action name +action=$1 +shift + +# If being run as simplepv then turn off all colours and +# wrap at 40 characters +# Useful for display outside of terminal +if [ $HOWRUN = "simplepv" ] ; then + TODOTXT_PLAIN=1 + PRI_X=$NONE + PRI_A=$NONE + PRI_B=$NONE + PRI_C=$NONE + DEFAULT=$NONE + COLOR_DONE=$NONE + # Check if we want to wrap text or not + if [ "$1" = "--nowrap" ]; then + NOWRAP=1 + shift + fi + # If we have fmt then use it to wrap long lines + $(file /usr/bin/fmt > /dev/null 2>&1) + FMT=$? + # Set final filter + if [ "$NOWRAP" -eq 1 ] ; then + TODOTXT_FINAL_FILTER="$TODOTXT_FINAL_FILTER " + elif [ $FMT -eq 0 ] ; then + TODOTXT_FINAL_FILTER="$TODOTXT_FINAL_FILTER | fmt -t -w 40" + fi +fi + +# Stop filter now and run in a controlled manner after the _list function is run +TODOTXT_DISABLE_FILTER=1 + +[ "$action" = "useage" ] && { + echo " $(basename $0) [TERM...]" + echo " Show todo items containing TERM, grouped by project, and displayed in" + echo " priority order. If no TERM provided, displays entire todo.txt." + echo "" + exit +} + +# Show projects in alphabetical order and todo items in priority order +echo "===== Projects =====" +echo "" + +# Find all projects and sort +PROJECTS=$(grep -o '[^ ]*+[^ ]\+' "$TODO_FILE" | grep '^+' | sort -u | sed 's/^+//g' ) + +# For each project show header and the list of todo items +for project in $PROJECTS ; do + # Use core _list function, does numbering and colouring for us + PROJECT_LIST=$(_list "$TODO_FILE" "+$project\b" "$@" | sed 's/\ *+[a-zA-Z0-9._\-]*\ */ /g') + if [[ -n "${PROJECT_LIST}" ]]; then + echo "--- $project ---" + echo "${PROJECT_LIST}" | eval $TODOTXT_FINAL_FILTER + # If run as simplepv don't add newlines + if [ $HOWRUN != "simplepv" ] ; then + echo "" + fi + fi +done + +# Show todo items not associated to a project +PROJECT_LIST=$(_list "$TODO_FILE" "$@" | grep -v "+[[:alnum:]]*" ) +if [[ -n "${PROJECT_LIST}" ]]; then + echo "--- Not in projects ---" + echo "${PROJECT_LIST}" | eval $TODOTXT_FINAL_FILTER +fi diff --git a/todo/actions/r b/todo/actions/r new file mode 120000 index 0000000..d30c718 --- /dev/null +++ b/todo/actions/r @@ -0,0 +1 @@ +revive \ No newline at end of file diff --git a/todo/actions/revive b/todo/actions/revive new file mode 100755 index 0000000..926f4ed --- /dev/null +++ b/todo/actions/revive @@ -0,0 +1,61 @@ +#!/bin/bash + +# Copyright (c) 2013 Duncan Eastoe + +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +# modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +## Display usage information ## +function usage { + cat <<-END + revive - Restore tasks from done.txt + + Usage: + revive + List available todos to revive (ie. done.txt) + + revive ITEM# + Revive specified todo + END + + exit 0 +} + +## Lists completed todos in done.txt ## +function listAvailableTodos { + $TODO_FULL_SH listfile "$TODO_DIR/done.txt" + + exit 0 +} + +## Copies todo from done.txt back to todo.txt ## +function reviveTodo { + getTodo "$1" "$TODO_DIR/done.txt" + cleanTodo=$(echo "$todo" | sed -E 's/x [0-9]{4}-[0-9]{2}-[0-9]{2} //') + $TODO_FULL_SH add "$cleanTodo" + + exit 0 +} + +if [ "$1" == "usage" ]; then + usage +fi + +shift + +if [ -z "$1" ]; then + listAvailableTodos +elif [[ "$1" =~ [0-9]+ ]]; then + reviveTodo "$1" +else + usage +fi diff --git a/todo/actions/wtf b/todo/actions/wtf new file mode 100755 index 0000000..6541887 --- /dev/null +++ b/todo/actions/wtf @@ -0,0 +1,5 @@ +#!/bin/bash + +! command -v bat &>/dev/null || PAGER=bat + +[[ -f "$TODO_DIR"/README.md ]] && "${PAGER:-cat}" "$TODO_DIR"/README.md diff --git a/todo/actions/xp b/todo/actions/xp new file mode 100755 index 0000000..0c062e9 --- /dev/null +++ b/todo/actions/xp @@ -0,0 +1,59 @@ +#!/bin/bash +# 2013 Chris Jones christopher.donald.jones@gmail.com +#github: https://github.com/gr0undzer0/xp +# License: GPL, http://www.gnu.org/copyleft/gpl.html + +re='^[0-9]+$' +OPTION=$2 + + +if [[ "$OPTION" =~ $re ]] +then +DAYS=$2 +elif [ "$OPTION" = "-o" ] +then +DAYS=$3 +elif [ "$OPTION" = "-h" ] +then +echo "XP - A todo.sh module designed to print a readable guide of what you've accomplished in any number of days." +echo "Usage:" +echo " todo.sh xp [-oh] days " +echo " days: Number of days ago." +echo " Options:" +echo " o : Omit days on which no tasks were completed" +echo " h : Print this help message." +exit +else +echo "Usage:" +echo " todo.sh xp [-oh] argument " +echo " days: Number of days ago." +echo " Options:" +echo " o : Omit days on which no tasks were commited." +echo " h : Print this help message." +exit +fi; + +TODAY=$(date +%s) +WEEK=604800 +DAY=$((604800 / 7)) +for i in $(eval echo "{$DAYS..0}") +do +DAYX=$(($TODAY - $DAY * $i)) +DAYTITLE=$(date -d "@"$DAYX +%Y-%m-%d\ ) +DAYWORD=$(date -d $DAYTITLE +%A) +DAYCONTENT=$(grep $DAYTITLE $DONE_FILE) + +if [[ -z "$DAYCONTENT" && "$OPTION" != -o ]] +then +echo "==========================" +echo "$DAYWORD" ":" "$DAYTITLE" +echo "==========================" +echo "$DAYCONTENT" +elif [[ ! -z "$DAYCONTENT" ]] +then +echo "==========================" +echo "$DAYWORD" ":" "$DAYTITLE" +echo "==========================" +echo "$DAYCONTENT" +fi; +done diff --git a/todo/config b/todo/config new file mode 100644 index 0000000..9995be2 --- /dev/null +++ b/todo/config @@ -0,0 +1,100 @@ +# shellcheck disable=2148 + +# ---------------------------------------------------------------------------------------------------------------------- +# Initialize +# ---------------------------------------------------------------------------------------------------------------------- + +hill() { + local cwd=${1?${FUNCNAME[0]}: missing argument}; shift + + cd "$cwd" || exit + + while :; do + local try + + # shellcheck disable=2128 + if [[ $PWD == "$HOME" ]] || [[ $PWD == "/" ]]; then + break + fi + + for try; do + if [[ -e $try ]]; then + return 0 + fi + done + + cd .. || exit + done + + return 1 +} + +initialize() { + local try + + if try=$(hill . .local && echo "$PWD/.local/home") && [[ -n $try ]]; then + export TODO_DIR=$try + return 0 + fi + + if [[ -d "$HOME"/Dropbox/opt/todotxt+ ]]; then + export TODO_DIR="$HOME"/Dropbox/opt/todotxt+ + else + export TODO_DIR="$HOME"/.todo + fi +} + +initialize "$@" + +export TODO_FILE="$TODO_DIR/todo.txt" +export DONE_FILE="$TODO_DIR/done.txt" +export REPORT_FILE="$TODO_DIR/report.txt" + +export TODOTXT_DEFAULT_ACTION=ls + +export BLACK='\\033[0;30m' +export RED='\\033[0;31m' +export GREEN='\\033[0;32m' +export BROWN='\\033[0;33m' +export BLUE='\\033[0;34m' +export PURPLE='\\033[0;35m' +export CYAN='\\033[0;36m' +export LIGHT_GREY='\\033[0;37m' +export DARK_GREY='\\033[1;30m' +export LIGHT_RED='\\033[1;31m' +export LIGHT_GREEN='\\033[1;32m' +export YELLOW='\\033[1;33m' +export LIGHT_BLUE='\\033[1;34m' +export LIGHT_PURPLE='\\033[1;35m' +export LIGHT_CYAN='\\033[1;36m' +export WHITE='\\033[1;37m' +export DEFAULT='\\033[0m' + +export PRI_A=$YELLOW +export PRI_B=$GREEN +export PRI_C=$LIGHT_BLUE +export PRI_D=... +export PRI_X=$WHITE + +export COLOR_DONE=$LIGHT_GREY + +export COLOR_PROJECT=$RED +export COLOR_CONTEXT=$RED +export COLOR_DATE=$BLUE +export COLOR_NUMBER=$LIGHT_GREY + +export COLOR_META=$CYAN + +export TODOTXT_SORT_COMMAND='env LC_COLLATE=C sort -f -k2' + +# TODOTXT_FINAL_FILTER will filter list output after colorization, +# priority hiding, context hiding, and project hiding. That is, +# just before the list output is displayed. +# +# export TODOTXT_FINAL_FILTER='cat' + +export TODO_NOTE_EXT=.md + +echo 'Depo notlarΔ±nΔ± gΓΆr: "T" | Depo notlarΔ±nΔ± dΓΌzenle: "t n"' + +# vim: ft=bash diff --git a/todo/install.sh b/todo/install.sh new file mode 100644 index 0000000..edeb97e --- /dev/null +++ b/todo/install.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/todo + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/actions -t "$config" + ln -sf "$PWD"/config -t "$config" +} diff --git a/vifm/install.sh b/vifm/install.sh new file mode 100644 index 0000000..09e999c --- /dev/null +++ b/vifm/install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail; [[ -z ${TRACE:-} ]] || set -x; cd "$(dirname "$0")" + +config=${XDG_CONFIG_HOME:-$HOME/.config}/vifm + +rm -rf "$config" && install -d "$config" && { + ln -sf "$PWD"/vifmrc -t "$config" +} diff --git a/vifm/vifmrc b/vifm/vifmrc new file mode 100644 index 0000000..96d3848 --- /dev/null +++ b/vifm/vifmrc @@ -0,0 +1,510 @@ +" ---------------------------------------------------------------------------------------------------------------------- +" Settings +" ---------------------------------------------------------------------------------------------------------------------- + +set confirm=permdelete +set history=500 +set hlsearch +set ignorecase +set incsearch +set nofollowlinks +set norunexec +set scrolloff=4 +set shell=/bin/bash +set smartcase +set sortnumbers +set statusline=" %A %8u:%-8g %16d %8s %T " +set suggestoptions=normal,visual,view,otherpane,keys,marks,registers +set syscalls +set timefmt='%Y/%m/%d %H:%M' +set trash +set undolevels=100 +set vifminfo=dhistory,chistory,state,tui,shistory,phistory,fhistory,dirstack,registers,bookmarks,bmarks +set vimhelp +set wildmenu +set wildstyle=popup + +if executable('rg') + set grepprg='rg --color=never -Hn %i %a %s' +endif + +if executable('fd') + set findprg='fd --color=never %p' +endif + +if !has('win') + set slowfs=curlftpfs +endif + +if executable('nvim') + set vicmd=nvim +elseif executable('vim') + set vicmd=vim +elseif $EDITOR != '' + echo 'Note: using `'.$EDITOR.'` as an editor' + let &vicmd = $EDITOR +endif + +colorscheme Default-256 Default + +" ---------------------------------------------------------------------------------------------------------------------- +" Commands +" ---------------------------------------------------------------------------------------------------------------------- + +command! df df -h %m 2> /dev/null +command! diff nvim -d %f %F +command! make !!make %a +command! mkcd :mkdir %a | cd %a +command! rake !!rake %a +command! reload :write | restart full +command! run !! ./%f +command! zip zip -r %c.zip %f +command! tar tar -czvf %c.tar.gz %f + +command! Ffind : set noquickview + \| let $FZF_PICK = term('find | fzf 2>/dev/tty') + \| if $FZF_PICK != '' + \| execute 'goto' fnameescape($FZF_PICK) + \| endif +command! Fgo : set noquickview + \| let $FZF_PICK = term('find | fzf 2>/dev/tty') + \| if $FZF_PICK != '' + \| execute system('[ -f "$FZF_PICK" ] && echo goto || echo cd') fnameescape($FZF_PICK) + \| endif + +" variation that automatically enters directories +command! Flocate : set noquickview + \| let $FZF_PICK = term('locate $HOME | fzf 2>/dev/tty') + \| if $FZF_PICK != '' + \| execute system('[ -f "$FZF_PICK" ] && echo goto || echo cd') fnameescape($FZF_PICK) + \| endif + +command! Goq :set noquickview + \| :execute 'cd' fnameescape(system('zoxide query -l "%a" | fzf --height 20 2>/dev/tty')) '%IU' + \| redraw + +command! Go :set noquickview + \| :execute 'cd' fnameescape(system('zoxide query "%a"')) '%IU' + \| redraw + +" ---------------------------------------------------------------------------------------------------------------------- +" Keymaps +" ---------------------------------------------------------------------------------------------------------------------- + +nnoremap ,c :write | edit $MYVIFMRC | restart full +nnoremap ,w :set wrap! +nnoremap :sync %c +nnoremap : quit +nnoremap :quit +nnoremap x +nnoremap :quit +nnoremap :!less %f +nnoremap :edit +nnoremap :copy +nnoremap :move +nnoremap :mkdir +nnoremap :delete +nnoremap :select +nnoremap :alink +nnoremap :sync +nnoremap A cw +nnoremap G :Fgo +nnoremap I cw +nnoremap b :!tmux split-window -v -p40 'exec bash'%n +nnoremap cc cw +nnoremap f :Ffind +nnoremap g :Flocate +nnoremap s :sort +nnoremap w :view +vnoremap w :viewgv + +nnoremap ΓΌ ' +nnoremap Ğ :Goq +nnoremap ğ :Go +nnoremap Δ± :grep + +" ---------------------------------------------------------------------------------------------------------------------- +" Special settings and keymaps +" ---------------------------------------------------------------------------------------------------------------------- + +" Activate screen/tmux support +screen! + +if $DISPLAY && executable('nvim') + " Open file in existing instance of nvim + nnoremap o :!nvim --remote-tab-silent %f + " Open file in new instance of nvim + nnoremap O :!nvim %f +endif + +" Interaction with system clipboard +if has('win') + " Yank current directory path to Windows clipboard with forward slashes + nnoremap yp :!echo %"d:gs!\!/! %i | clip + " Yank path to current file to Windows clipboard with forward slashes + nnoremap yf :!echo %"c:gs!\!/! %i | clip +elseif $WAYLAND_DISPLAY + if executable('wl-copy') + " Yank current directory path into primary and selection clipboards + nnoremap yd :!echo -n %d | wl-copy %i && + \ echo -n %d | wl-copy -p %i + " Yank current file path into into primary and selection clipboards + nnoremap yf :!echo -n %c:p | wl-copy %i && + \ echo -n %c:p | wl-copy -p %i + endif +elseif $DISPLAY + if executable('xclip') + " Yank current directory path into the clipboard + nnoremap yd :!echo %d | xclip %i + " Yank current file path into the clipboard + nnoremap yf :!echo %c:p | xclip %i + elseif executable('xsel') + " Yank current directory path into primary and selection clipboards + nnoremap yd :!echo -n %d | xsel --input --primary %i && + \ echo -n %d | xsel --clipboard --input %i + " Yank current file path into into primary and selection clipboards + nnoremap yf :!echo -n %c:p | xsel --input --primary %i && + \ echo -n %c:p | xsel --clipboard --input %i + endif +endif + +if $DISPLAY && executable('nvim') + nnoremap ,C :!nvim --remote-tab-silent $MYVIFMRC & +endif + +" ---------------------------------------------------------------------------------------------------------------------- +" Bookmarks +" ---------------------------------------------------------------------------------------------------------------------- + +mark D ~/Dropbox/ +mark d ~/Downloads/ +mark h ~/ +mark s ~/Dropbox/src/github.com +mark t /tmp + +" ---------------------------------------------------------------------------------------------------------------------- +" File types +" ---------------------------------------------------------------------------------------------------------------------- + +" Pdf +filextype {*.pdf}, zathura %c %i, apvlv %c, xpdf %c +fileviewer {*.pdf}, pdftotext -nopgbrk %c - + +" PostScript +filextype {*.ps,*.eps,*.ps.gz}, + \ {View in zathura} + \ zathura %f, + \ {View in gv} + \ gv %c %i, + +" Djvu +filextype {*.djvu}, + \ {View in zathura} + \ zathura %f, + \ {View in apvlv} + \ apvlv %f, + +" Midi +filetype {*.mid,*.kar} + \ {Play using TiMidity++} + \ timidity %f, + +" Audio +filetype {*.wav,*.mp3,*.flac,*.m4a,*.wma,*.ape,*.ac3,*.og[agx],*.spx,*.opus, + \*.aac,*.mpga}, + \