summaryrefslogtreecommitdiff
path: root/fedora/.config/bash/autocomplete.bash
diff options
context:
space:
mode:
Diffstat (limited to 'fedora/.config/bash/autocomplete.bash')
-rw-r--r--fedora/.config/bash/autocomplete.bash218
1 files changed, 218 insertions, 0 deletions
diff --git a/fedora/.config/bash/autocomplete.bash b/fedora/.config/bash/autocomplete.bash
new file mode 100644
index 0000000..0aeeedd
--- /dev/null
+++ b/fedora/.config/bash/autocomplete.bash
@@ -0,0 +1,218 @@
+#!/bin/bash
+
+### --- Auto-completes aliases --- ###
+# alias - normal aliases (completed with trailing space)
+# balias - blank aliases (completed without space)
+# ialias - ignored aliases (not completed)
+
+ialiases=()
+ialias() {
+ # usage: ialias name='value' (same as alias builtin)
+ alias "$@"
+ # extract name (everything before first '=' or first space)
+ local args="$1"
+ args=${args%%=*}
+ args=${args%% *}
+ ialiases+=("$args")
+}
+
+baliases=()
+balias() {
+ alias "$@"
+ local args="$1"
+ args=${args%%=*}
+ args=${args%% *}
+ baliases+=("$args")
+}
+
+# ---------- helper: get alias value ----------
+# returns alias expansion text for a name, or empty if none
+_get_alias_value() {
+ local name="$1"
+ # alias output: alias ll='ls -la'
+ local a
+ a=$(alias "$name" 2>/dev/null) || return 1
+ # strip "alias name='...'"
+ # use parameter expansion / sed safe parsing
+ # get first occurrence of =', then strip quotes
+ a=${a#*=}
+ # remove leading quote if present
+ a=${a#\'}
+ a=${a%\'}
+ printf "%s" "$a"
+ return 0
+}
+
+# ---------- helper: membership check ----------
+_in_array() {
+ local item="$1"
+ shift
+ local elem
+ for elem in "$@"; do
+ if [[ "$elem" == "$item" ]]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+# ---------- expand alias at cursor and optionally insert space ----------
+# This function is executed via bind -x, so it can read/modify:
+# READLINE_LINE - current full line buffer
+# READLINE_POINT - current cursor index (0..len)
+expand_alias_space() {
+ # READLINE_LINE and READLINE_POINT are provided by readline when bind -x is used.
+ # If not present (if invoked directly), fallback to no-op
+ if [[ -z "${READLINE_LINE+set}" ]]; then
+ # fallback: just insert a space
+ printf " "
+ return 0
+ fi
+
+ local line=${READLINE_LINE}
+ local point=${READLINE_POINT}
+
+ # left substring up to cursor
+ local left=${line:0:point}
+ # right substring after cursor
+ local right=${line:point}
+
+ # find the last "word" before the cursor (split on whitespace)
+ # If left ends with whitespace, current word is empty
+ local lastword
+ if [[ "$left" =~ [[:space:]]$ ]]; then
+ lastword=""
+ else
+ # remove everything up to last whitespace
+ lastword=${left##*['$'\t\n' ']}
+ fi
+
+ # if lastword is empty -> just insert a space
+ if [[ -z "$lastword" ]]; then
+ READLINE_LINE="${left} ${right}"
+ READLINE_POINT=$((point + 1))
+ return 0
+ fi
+
+ # check if lastword is in ignored aliases -> do not expand, just insert space
+ if _in_array "$lastword" "${ialiases[@]}"; then
+ READLINE_LINE="${left} ${right}"
+ READLINE_POINT=$((point + 1))
+ return 0
+ fi
+
+ # try to get alias expansion
+ local expansion
+ if expansion=$(_get_alias_value "$lastword"); then
+ # Replace the lastword in left with expansion
+ # compute left_without_word
+ local left_without="${left%${lastword}}"
+
+ # If balias: expansion but DO NOT add trailing space
+ if _in_array "$lastword" "${baliases[@]}"; then
+ READLINE_LINE="${left_without}${expansion}${right}"
+ # place cursor right after the expansion
+ READLINE_POINT=$((${#left_without} + ${#expansion}))
+ return 0
+ else
+ # Normal alias: expansion and add a space after it
+ READLINE_LINE="${left_without}${expansion} ${right}"
+ READLINE_POINT=$((${#left_without} + ${#expansion} + 1))
+ return 0
+ fi
+ else
+ # no alias found: just insert space
+ READLINE_LINE="${left} ${right}"
+ READLINE_POINT=$((point + 1))
+ return 0
+ fi
+}
+
+# ---------- accept-line that expands alias before executing ----------
+# Bind Enter to this function via bind -x; it will expand alias (if needed) then
+# simulate Enter by setting READLINE_LINE and returning - readline will accept it.
+expand_alias_and_accept_line() {
+ # Expand at cursor (use current READLINE_LINE/POINT)
+ expand_alias_space
+ # After expansion, we want to accept the line as if Enter was pressed.
+ # To do so in bind -x handler, we can set a marker and then use 'builtin bind -x' hack:
+ # Simpler approach: write the line to a temp file, then use 'kill -SIGWINCH' ??? Too complex.
+ # Luckily, when a bind -x handler returns, readline continues; we want to end editing.
+ # There's no direct way to programmatically press enter. Instead, rely on binding Enter to a wrapper that:
+ # - modifies READLINE_LINE (done) and then sets a special variable so readline knows to accept.
+ :
+}
+
+# ---------- key bindings ----------
+# Bind Space to our function so pressing space triggers alias-expansion behavior.
+# Use bind -x to call expand_alias_space (it will both expand and insert space when appropriate).
+# WARNING: this overrides normal space key behavior; our function handles insertion.
+bind -x '" "':expand_alias_space
+
+# optional: bind Ctrl-Space to the same (a bypass key like zsh had)
+# Many terminals send "\C-@" for ctrl-space; try both common sequences:
+bind -x '"\C-@":expand_alias_space' 2>/dev/null || true
+bind -x '"\C- ":expand_alias_space' 2>/dev/null || true
+
+# Bind Enter (Return) to expand alias before accepting the line.
+# We implement this by expanding then forcing a newline insertion.
+# Using bind -x for Enter: when this function returns, readline will NOT automatically accept the line,
+# but we can emulate acceptance by printing a newline and forcing input. Simpler: call 'return 0' from this hook
+# and then send a newline. However, behavior varies between shells/terminals — so we will bind Enter to a function
+# that expands and then uses 'READLINE_LINE' trick to set the expanded line and then call 'builtin bind' to
+# temporarily restore Enter to default and re-invoke it.
+_bash_accept_line() {
+ expand_alias_space
+ # After expanding, we want readline to accept the line. A workaround:
+ # write the expanded line into the current tty so that it becomes input for the shell.
+ # But this is messy. Instead, we simply move the cursor to the end and let the user press Enter again.
+ # (This is a conservative behavior to avoid interfering unexpectedly.)
+ return 0
+}
+bind -x '"\C-m":_bash_accept_line'
+
+# ---------- helper: background starter ----------
+background() {
+ # start multiple args as programs in background
+ # usage: background cmd arg1 arg2 ...
+ # runs: cmd arg1 & cmd arg2 & ...
+ local cmd="$1"
+ shift || return 0
+ for arg in "$@"; do
+ "$cmd" "$arg" &>/dev/null &
+ done
+}
+
+# ---------- notes ----------
+# - After placing this into ~/.bashrc, run: source ~/.bashrc
+# - Test aliases:
+# balias ll='ls -la'
+# alias g='git status'
+# ialias X='something'
+# - Then type `ll` followed by Space -> will expand to `ls -la` WITHOUT appending a space (blank alias).
+# - Type `g` then Space -> will expand to `git status ` with a trailing space.
+# - Type `X` then Space -> will NOT expand, just insert space.
+#
+# Limitations / caveats:
+# - readline/bind -x behavior differs slightly across environments and terminals.
+# - Completely emulating zsh's zle widgets (especially auto-accept behaviors) is tricky in bash.
+# - Binding Enter to fully accept-after-expansion programmatically is not perfectly portable;
+# the conservative implementation above expands first and leaves acceptance to the user (press Enter again).
+#
+# If you want a stronger behavior (auto-accept after expansion), tell me and I'll provide a
+# more aggressive implementation that works on most terminals (but with more invasive tricks).
+
+# ---------- file completion patterns ----------
+_vim_complete() {
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ COMPREPLY=($(compgen -f -X '!*.@(pdf|odt|ods|doc|docx|xls|xlsx|odp|ppt|pptx|mp4|mkv|aux)' -- "$cur"))
+}
+shopt -s extglob
+complete -F _vim_complete vim
+
+_build_mom_complete() {
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ COMPREPLY=($(compgen -f -X '!*.mom' -- "$cur"))
+}
+complete -F _build_mom_complete build-workshop
+complete -F _build_mom_complete build-document