Add extensive documentation and fix 2 bugs
Bug 1: Allow trailing space for inhibiting recognition of evaluating aliases Bug 2: Preserve pre-evaluation aliases in file extension aliases
This commit is contained in:
parent
fb37d2b89e
commit
d241bfda6a
1 changed files with 130 additions and 17 deletions
147
bash-abbr
147
bash-abbr
|
|
@ -4,14 +4,112 @@
|
|||
# put into the bashrc drop-in directory ~/.bashrc.d/
|
||||
# and then sourced from ~/.bashrc.
|
||||
|
||||
# Disable plugin by uncommenting this line
|
||||
# Disable plugin by uncommenting the following line
|
||||
# return
|
||||
|
||||
# WARNING 1: This plugin creates and overwrites various readline bindings.
|
||||
# Therefore, it might interfere with other plugins/custom bindings.
|
||||
# Some bindings may be changed (e.g. \e\C-a...) while others should not (e.g. \C-m)
|
||||
# WARNING 2: This plugin needs and enables extended globbing.
|
||||
shopt -s extglob
|
||||
###### bash-abbr: fish like abbreviations for bash, and more ######
|
||||
#
|
||||
# After sourcing this plugin and in an interactive bash shell
|
||||
# where --noediting was not supplied during invocation
|
||||
# (readline must be enabled), regular bash aliases will be
|
||||
# expanded as you type. This is different from normal alias
|
||||
# behavior, where they are only expanded internally, invisible
|
||||
# to the user. This is useful when sharing the screen, for
|
||||
# making edits to the expanded version of an alias, or for
|
||||
# personal reassurance that you're executing the correct command.
|
||||
#
|
||||
# Regular, internal alias expansion will be disabled for this in order
|
||||
# to not exhibit unexpected behavior. See the end of this file for an explanation.
|
||||
#
|
||||
# Besides the expected behavior, there are a few extra features
|
||||
# that are usually useful.
|
||||
#
|
||||
## Global Aliases (can be combined with other alias types):
|
||||
# These aliases expand anywhere on the command line.
|
||||
# Syntax:
|
||||
# - alias [alias-name]=*[alias-value]
|
||||
# - alias [alias-name]=$[alias-value] (identical but self-insertion is inhibited, see below)
|
||||
# Examples:
|
||||
# - alias G='*| grep'
|
||||
# Typing `G` and pressing space will expand the string after the asterisk
|
||||
# and self-insert the space.
|
||||
#
|
||||
## Post Evaluating Aliases:
|
||||
# These aliases expand to the evaluation of the *recursively expanded* alias-value.
|
||||
# Syntax:
|
||||
# - alias [alias-name]=[alias-value]!
|
||||
# Examples:
|
||||
# - alias g=git gph='printf "g push %q HEAD" "$(git remote | head -1)"!'
|
||||
# Typing `gph` and pressing enter might evaluate to something like
|
||||
# `git push origin HEAD`. The `origin` part is dynamic, it will
|
||||
# expand to whatever the first configured git remote is. Because this
|
||||
# is the post-evaluating form of the evaluating aliases, the `g` was first
|
||||
# expanded to `git`, only after which it was evaluated.
|
||||
#
|
||||
## Pre Evaluating Aliases:
|
||||
# These aliases expand to the evaluation of the initial alias-value, after
|
||||
# which recursive alias expansion continues.
|
||||
# Syntax:
|
||||
# - alias [alias-name]=[alias-value]$
|
||||
# Examples:
|
||||
# - alias c='*wl-paste$'
|
||||
# Typing `c` anywhere on the command line will immediately expand to the
|
||||
# clipboard contents on wayland based systems. The expansion is subject
|
||||
# to further recursive alias expansion. Note that
|
||||
# - alias c='*wl-paste!'
|
||||
# makes less sense, because copying a command that contains an alias would
|
||||
# not expand in this case, leading to a "command not found"
|
||||
#
|
||||
## File Extension Aliases:
|
||||
# These aliases expand words on the command line that end with a file extension
|
||||
# (dot + suffix) to a custom command invocation that opens files of that file type.
|
||||
# Similar to xdg-open and Freedesktop MIME types, but for the command line.
|
||||
# Syntax:
|
||||
# - alias .[file-extension-without-dot]=[program-handler]
|
||||
# Examples:
|
||||
# - alias .txt=v .js=v .bashrc=v
|
||||
# Typing `test.txt`, `~/.bashrc` or `index.js` and pressing enter will expand to
|
||||
# `v test.txt` (or the others respectively), which might in turn expand to `vim test.txt`
|
||||
# if there is an alias like `alias v=vim`.
|
||||
#
|
||||
## Aliases with inhibited self-insertion:
|
||||
# Upon expanding these aliases, there won't be any self-insertion at all.
|
||||
# Syntax:
|
||||
# - alias [alias-name]=-[alias-value]
|
||||
# - alias [alias-name]=$[alias-value] (global alias)
|
||||
# Examples:
|
||||
# - alias gssh='$git@github.com:'
|
||||
# Typing `gssh` and pressing space will expand to `git@github.com:` without any trailing space.
|
||||
# This is useful, because you usually enter a GitHub username directly after the colon without
|
||||
# any characters in between. The `$` form was chosen because this alias can usually appear
|
||||
# anywhere on the command line.
|
||||
# - alias cuhs='-curl https://'
|
||||
# Typing `cuhs` and pressing space will expand to `curl https://` without any trailing space.
|
||||
# This is similar to the example above, only that the `-` form was chose because this alias
|
||||
# usually doesn't make sense anywhere on the command line.
|
||||
#
|
||||
## Preventing alias types from being recognized:
|
||||
# If the alias-value is supposed to start with a $, * or !, then you can prefix it with a single space.
|
||||
# If the alias-value is supposed to start with a space, prefix it with another space.
|
||||
# If the alias-value is supposed to end with $ or !, suffix it with a space.
|
||||
# If the alias-value is supposed to end with a space, suffix it with another space.
|
||||
#
|
||||
## Combing alias types:
|
||||
# Every alias type can be combined with any other alias type, as far as the syntax
|
||||
# allows it (only one trailing character, only one leading character).
|
||||
# Therefore, you can create an alias like this:
|
||||
# - alias c=cat .txt='$c!'
|
||||
# And then use it on the command line like this:
|
||||
# - echo a.txt|
|
||||
# `|` represents the cursor. Assuming the file a.txt contains the text `hey`,
|
||||
# pressing space now would lead to the following result:
|
||||
# - echo hey|
|
||||
# Therefore, a global alias without self-insertion ($) was used on a file extension alias (.txt)
|
||||
# and the result recursively expanded (c -> cat) and finally evaluated (post-evaluation, !).
|
||||
|
||||
# WARNING: This plugin creates and overwrites various readline bindings.
|
||||
# Therefore, it might interfere with other plugins/custom bindings.
|
||||
# Some bindings may be changed (e.g. \e\C-a...) while others should not (e.g. \C-m)
|
||||
|
||||
# Regexes for heuristically determining whether we're abbreviating the first word.
|
||||
# Construction put into functions to prevent global namespace pollution
|
||||
|
|
@ -96,9 +194,9 @@ _try_abbrev_internal () {
|
|||
# then we also want to expand aliases if the cursor/point is *on* the word instead of just *after* the word.
|
||||
if [[ -z $self_insertion ]]; then
|
||||
line_from_point=${line:point}
|
||||
line_from_point_without_partial_word=${line_from_point##*([^<>&;()|[:space:]])} # extglob must be enabled!
|
||||
trailing_part_of_word=${line_from_point%%[<>&;()|[:space:]]*}
|
||||
# Move point forward to right after the word. Keep mark where it is.
|
||||
point=${#line}-${#line_from_point_without_partial_word}
|
||||
point=$((point+${#trailing_part_of_word}))
|
||||
fi
|
||||
declare -r point line_until_point=${line::point}
|
||||
|
||||
|
|
@ -117,7 +215,12 @@ _try_abbrev_internal () {
|
|||
|
||||
# Account for file extension aliases. Normal aliases take precedence
|
||||
declare file_extension_replacement=${BASH_ALIASES[".${word_at_point##*.}"]-} &&
|
||||
[[ $replacement ]] || { replacement=${file_extension_replacement:+${file_extension_replacement%!} $word_at_point${file_extension_replacement: -1}} && replacement=${replacement%[^!]}; } &&
|
||||
[[ $replacement ]] ||
|
||||
{ # The logic below preserved trailing exclamation points (`!`) or dollar signs (`$`) at the end,
|
||||
# which are special characters used for evaluating aliases.
|
||||
replacement=${file_extension_replacement:+${file_extension_replacement%[$\!]} $word_at_point${file_extension_replacement: -1}} &&
|
||||
replacement=${replacement%[^$\!]}
|
||||
} &&
|
||||
|
||||
[[ $replacement ]] &&
|
||||
|
||||
|
|
@ -144,24 +247,29 @@ _try_abbrev_internal () {
|
|||
# Strip special flags (or space) from the beginning of the replacement
|
||||
replacement=${replacement#[*$ -]}
|
||||
|
||||
# Account for Post Evaluating Aliases
|
||||
# shellcheck disable=SC2015
|
||||
[[ ${replacement: -1} = "!" ]] && declare -r eval_expansion=true || declare -r eval_expansion=false
|
||||
|
||||
[[ ${replacement: -1} = "$" ]] && replacement=$(eval "${replacement%$}")
|
||||
# Account for and potentially perform Pre Evaluating Alias expansion
|
||||
[[ ${replacement: -1} = "$" ]] && replacement=$(eval "${replacement%$}") # TODO use bash 5.3 `${}` command substitution syntax to avoid subshells
|
||||
|
||||
# Recursively expand replacement if we haven't expanded it already
|
||||
declare tmp=" $replacement"
|
||||
[[ $tmp =~ ^([[:space:]]*$is_first_word_prefix) ]] && tmp=${tmp#"${BASH_REMATCH[1]}"}
|
||||
declare tmp=" $replacement" # Prepend space, makes the logic easier
|
||||
[[ $tmp =~ ^([[:space:]]*$is_first_word_prefix) ]] && tmp=${tmp#"${BASH_REMATCH[1]}"} # Strip matching prefix
|
||||
declare -r word_to_expand=${tmp%%[<>&;()|[:space:]]*}
|
||||
if [[ -z ${_expanded_aliases[$word_to_expand]-} ]]; then
|
||||
declare -r point_for_replacement=$((${#BASH_REMATCH[1]}+${#word_to_expand}))
|
||||
declare -g "ret_$level"
|
||||
declare -n recursively_expanded_replacement="ret_$level"
|
||||
_try_abbrev_internal " $replacement" "$point_for_replacement" "" "ret_$level" "_" "_" ""
|
||||
replacement=${recursively_expanded_replacement# }
|
||||
replacement=${recursively_expanded_replacement# } # Strip the prepended space again
|
||||
fi
|
||||
# Eval if it has a trailing exclamation point and strip trailing \n and \r
|
||||
"$eval_expansion" && replacement=$(eval "${replacement%!}")
|
||||
# Perform Post Evaluating Alias expansion
|
||||
"$eval_expansion" && replacement=$(eval "${replacement%!}") # TODO use bash 5.3 `${}` command substitution syntax to avoid subshells
|
||||
|
||||
# Strip trailing space that might've been added to prevent evaluating aliases from being recognized
|
||||
replacement=${replacement% }
|
||||
|
||||
# Calculate point and mark offset.
|
||||
declare -ir offset=${#replacement}-${#word_at_point}+${#self_insertion}
|
||||
|
|
@ -209,7 +317,7 @@ bash_abbr () {
|
|||
for ch in ' ' '|' '&' ';' '(' ')' '<' '>'; do
|
||||
bind -x '"\e\C-a'"$ch"'": _try_abbrev "'"$ch"'"'
|
||||
bind '"'"$ch"'": "\e\C-a'"$ch"'"'
|
||||
# bind '"'"$ch"'": "\e\C-a'"$ch"'\e^"' # Moves point weirdly
|
||||
# bind '"'"$ch"'": "\e\C-a'"$ch"'\e^"' # TODO fix. Moves point weirdly atm.
|
||||
done
|
||||
|
||||
# TODO To get it fully working in all edge cases (as far as we can parse),
|
||||
|
|
@ -228,4 +336,9 @@ bash_abbr
|
|||
|
||||
# If the plugin is enabled, we usually don't want regular alias expansion,
|
||||
# since it can lead to undesirable "double expansions" if an alias is defined recursively.
|
||||
type bash_abbr &>/dev/null && shopt -u expand_aliases
|
||||
# fish solves this by treating aliases differently from abbreviations.
|
||||
# This, however, leads to the invonvenience of defining aliases/abbrevations twice,
|
||||
# or give up one of the two. This plugin prefers the disabling of normal aliases, since
|
||||
# it's more transparent to the user. The final command line is exactly what will be
|
||||
# executed, no hidden aliases that might add hidden flags to some of your commands.
|
||||
[[ $(type -t bash_abbr) = function ]] && shopt -u expand_aliases # TODO use bash 5.3 `${}` command substitution syntax to avoid subshells
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue