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 0000000..c2de439 Binary files /dev/null and b/terminal.png differ 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}, + \