bash_completion
613 lines
| 13.4 KiB
| application/x-sh
|
BashLexer
/ contrib / bash_completion
Bryan O'Sullivan
|
r18769 | # bash completion for the Mercurial distributed SCM -*- sh -*- | ||
Martin Geisler
|
r10028 | |||
# Docs: | ||||
# | ||||
# If you source this file from your .bashrc, bash should be able to | ||||
# complete a command line that uses hg with all the available commands | ||||
# and options and sometimes even arguments. | ||||
# | ||||
# Mercurial allows you to define additional commands through extensions. | ||||
# Bash should be able to automatically figure out the name of these new | ||||
# commands and their options. See below for how to define _hg_opt_foo | ||||
# and _hg_cmd_foo functions to fine-tune the completion for option and | ||||
# non-option arguments, respectively. | ||||
# | ||||
# | ||||
# Notes about completion for specific commands: | ||||
# | ||||
# - the completion function for the email command from the patchbomb | ||||
# extension will try to call _hg_emails to get a list of e-mail | ||||
# addresses. It's up to the user to define this function. For | ||||
# example, put the addresses of the lists that you usually patchbomb | ||||
# in ~/.patchbomb-to and the addresses that you usually use to send | ||||
# the patchbombs in ~/.patchbomb-from and use something like this: | ||||
# | ||||
# _hg_emails() | ||||
# { | ||||
# if [ -r ~/.patchbomb-$1 ]; then | ||||
# cat ~/.patchbomb-$1 | ||||
# fi | ||||
# } | ||||
# | ||||
# | ||||
# Writing completion functions for additional commands: | ||||
# | ||||
# If it exists, the function _hg_cmd_foo will be called without | ||||
# arguments to generate the completion candidates for the hg command | ||||
# "foo". If the command receives some arguments that aren't options | ||||
# even though they start with a "-", you can define a function called | ||||
# _hg_opt_foo to generate the completion candidates. If _hg_opt_foo | ||||
# doesn't return 0, regular completion for options is attempted. | ||||
# | ||||
# In addition to the regular completion variables provided by bash, | ||||
# the following variables are also set: | ||||
# - $hg - the hg program being used (e.g. /usr/bin/hg) | ||||
# - $cmd - the name of the hg command being completed | ||||
# - $cmd_index - the index of $cmd in $COMP_WORDS | ||||
# - $cur - the current argument being completed | ||||
# - $prev - the argument before $cur | ||||
# - $global_args - "|"-separated list of global options that accept | ||||
# an argument (e.g. '--cwd|-R|--repository') | ||||
# - $canonical - 1 if we canonicalized $cmd before calling the function | ||||
# 0 otherwise | ||||
# | ||||
shopt -s extglob | ||||
Brodie Rao
|
r11646 | _hg_cmd() | ||
{ | ||||
HGPLAIN=1 "$hg" "$@" 2>/dev/null | ||||
} | ||||
Martin Geisler
|
r10028 | _hg_commands() | ||
{ | ||||
local commands | ||||
"Yann E. MORIN"
|
r14374 | commands="$(HGPLAINEXCEPT=alias _hg_cmd debugcomplete "$cur")" || commands="" | ||
Martin Geisler
|
r10028 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$commands' -- "$cur")) | ||
} | ||||
_hg_paths() | ||||
{ | ||||
Thomas Arendsen Hein
|
r14332 | local paths="$(_hg_cmd paths -q)" | ||
Martin Geisler
|
r10028 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$paths' -- "$cur")) | ||
} | ||||
_hg_repos() | ||||
{ | ||||
local i | ||||
for i in $(compgen -d -- "$cur"); do | ||||
Sean Farley
|
r20123 | test ! -d "$i"/.hg || COMPREPLY=(${COMPREPLY[@]:-} "$i") | ||
Martin Geisler
|
r10028 | done | ||
} | ||||
Bryan O'Sullivan
|
r18793 | _hg_debugpathcomplete() | ||
{ | ||||
local files="$(_hg_cmd debugpathcomplete $1 "$cur")" | ||||
local IFS=$'\n' | ||||
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur")) | ||||
} | ||||
Martin Geisler
|
r10028 | _hg_status() | ||
{ | ||||
Bryan O'Sullivan
|
r18767 | local files="$(_hg_cmd status -n$1 "glob:$cur**")" | ||
Martin Geisler
|
r10028 | local IFS=$'\n' | ||
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur")) | ||||
} | ||||
Kevin Bullock
|
r13509 | _hg_bookmarks() | ||
{ | ||||
local bookmarks="$(_hg_cmd bookmarks -q)" | ||||
local IFS=$'\n' | ||||
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$bookmarks' -- "$cur")) | ||||
} | ||||
_hg_labels() | ||||
{ | ||||
Bryan O'Sullivan
|
r18790 | local labels="$(_hg_cmd debuglabelcomplete "$cur")" | ||
local IFS=$'\n' | ||||
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$labels' -- "$cur")) | ||||
Kevin Bullock
|
r13509 | } | ||
Martin Geisler
|
r10028 | # this is "kind of" ugly... | ||
_hg_count_non_option() | ||||
{ | ||||
local i count=0 | ||||
local filters="$1" | ||||
for ((i=1; $i<=$COMP_CWORD; i++)); do | ||||
Sean Farley
|
r20123 | if [[ "${COMP_WORDS[i]}" != -* ]]; then | ||
if [[ ${COMP_WORDS[i-1]} == @($filters|$global_args) ]]; then | ||||
continue | ||||
fi | ||||
count=$(($count + 1)) | ||||
fi | ||||
Martin Geisler
|
r10028 | done | ||
echo $(($count - 1)) | ||||
} | ||||
Sean Farley
|
r20126 | _hg_fix_wordlist() | ||
{ | ||||
local LASTCHAR=' ' | ||||
if [ ${#COMPREPLY[@]} = 1 ]; then | ||||
[ -d "$COMPREPLY" ] && LASTCHAR=/ | ||||
COMPREPLY=$(printf %q%s "$COMPREPLY" "$LASTCHAR") | ||||
else | ||||
for ((i=0; i < ${#COMPREPLY[@]}; i++)); do | ||||
[ -d "${COMPREPLY[$i]}" ] && COMPREPLY[$i]=${COMPREPLY[$i]}/ | ||||
done | ||||
fi | ||||
} | ||||
Martin Geisler
|
r10028 | _hg() | ||
{ | ||||
Sean Farley
|
r20125 | local cur prev cmd cmd_index opts i aliashg | ||
Martin Geisler
|
r10028 | # global options that receive an argument | ||
local global_args='--cwd|-R|--repository' | ||||
local hg="$1" | ||||
local canonical=0 | ||||
Sean Farley
|
r20125 | aliashg=$(alias $hg 2>/dev/null) | ||
if [[ -n "$aliashg" ]]; then | ||||
aliashg=${aliashg#"alias $hg='"} | ||||
aliashg=${aliashg%"'"} | ||||
hg=$aliashg | ||||
fi | ||||
Martin Geisler
|
r10028 | COMPREPLY=() | ||
cur="$2" | ||||
prev="$3" | ||||
# searching for the command | ||||
# (first non-option argument that doesn't follow a global option that | ||||
# receives an argument) | ||||
for ((i=1; $i<=$COMP_CWORD; i++)); do | ||||
Sean Farley
|
r20123 | if [[ ${COMP_WORDS[i]} != -* ]]; then | ||
if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then | ||||
cmd="${COMP_WORDS[i]}" | ||||
cmd_index=$i | ||||
break | ||||
fi | ||||
fi | ||||
Martin Geisler
|
r10028 | done | ||
if [[ "$cur" == -* ]]; then | ||||
Sean Farley
|
r20123 | if [ "$(type -t "_hg_opt_$cmd")" = function ] && "_hg_opt_$cmd"; then | ||
Sean Farley
|
r20126 | _hg_fix_wordlist | ||
Sean Farley
|
r20123 | return | ||
fi | ||||
Martin Geisler
|
r10028 | |||
Sean Farley
|
r20123 | opts=$(_hg_cmd debugcomplete --options "$cmd") | ||
Martin Geisler
|
r10028 | |||
Sean Farley
|
r20123 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur")) | ||
Sean Farley
|
r20126 | _hg_fix_wordlist | ||
Sean Farley
|
r20123 | return | ||
Martin Geisler
|
r10028 | fi | ||
# global options | ||||
case "$prev" in | ||||
Sean Farley
|
r20123 | -R|--repository) | ||
_hg_paths | ||||
_hg_repos | ||||
Sean Farley
|
r20126 | _hg_fix_wordlist | ||
Sean Farley
|
r20123 | return | ||
;; | ||||
--cwd) | ||||
# Stick with default bash completion | ||||
Sean Farley
|
r20126 | _hg_fix_wordlist | ||
Sean Farley
|
r20123 | return | ||
;; | ||||
Martin Geisler
|
r10028 | esac | ||
if [ -z "$cmd" ] || [ $COMP_CWORD -eq $i ]; then | ||||
Sean Farley
|
r20123 | _hg_commands | ||
Sean Farley
|
r20126 | _hg_fix_wordlist | ||
Sean Farley
|
r20123 | return | ||
Martin Geisler
|
r10028 | fi | ||
# try to generate completion candidates for whatever command the user typed | ||||
local help | ||||
if _hg_command_specific; then | ||||
Sean Farley
|
r20126 | _hg_fix_wordlist | ||
Sean Farley
|
r20123 | return | ||
Martin Geisler
|
r10028 | fi | ||
# canonicalize the command name and try again | ||||
Brodie Rao
|
r11646 | help=$(_hg_cmd help "$cmd") | ||
Martin Geisler
|
r10028 | if [ $? -ne 0 ]; then | ||
Sean Farley
|
r20123 | # Probably either the command doesn't exist or it's ambiguous | ||
return | ||||
Martin Geisler
|
r10028 | fi | ||
cmd=${help#hg } | ||||
cmd=${cmd%%[$' \n']*} | ||||
canonical=1 | ||||
_hg_command_specific | ||||
Sean Farley
|
r20126 | _hg_fix_wordlist | ||
Martin Geisler
|
r10028 | } | ||
_hg_command_specific() | ||||
{ | ||||
if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then | ||||
Sean Farley
|
r20123 | "_hg_cmd_$cmd" | ||
return 0 | ||||
Martin Geisler
|
r10028 | fi | ||
if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" == --rev ]; then | ||||
Sean Farley
|
r20123 | if [ $canonical = 1 ]; then | ||
_hg_labels | ||||
return 0 | ||||
elif [[ status != "$cmd"* ]]; then | ||||
Kevin Bullock
|
r13509 | _hg_labels | ||
Sean Farley
|
r20123 | return 0 | ||
else | ||||
return 1 | ||||
fi | ||||
Martin Geisler
|
r10028 | fi | ||
Sean Farley
|
r20124 | local aliascmd=$(_hg_cmd showconfig alias.$cmd | awk '{print $1}') | ||
[ -n "$aliascmd" ] && cmd=$aliascmd | ||||
Martin Geisler
|
r10028 | case "$cmd" in | ||
Sean Farley
|
r20123 | help) | ||
_hg_commands | ||||
;; | ||||
export) | ||||
if _hg_ext_mq_patchlist qapplied && [ "${COMPREPLY[*]}" ]; then | ||||
return 0 | ||||
fi | ||||
_hg_labels | ||||
;; | ||||
manifest|update|up|checkout|co) | ||||
_hg_labels | ||||
;; | ||||
pull|push|outgoing|incoming) | ||||
_hg_paths | ||||
_hg_repos | ||||
;; | ||||
paths) | ||||
_hg_paths | ||||
;; | ||||
add) | ||||
_hg_status "u" | ||||
;; | ||||
merge) | ||||
_hg_labels | ||||
;; | ||||
commit|ci|record) | ||||
_hg_status "mar" | ||||
;; | ||||
remove|rm) | ||||
_hg_debugpathcomplete -n | ||||
;; | ||||
forget) | ||||
_hg_debugpathcomplete -fa | ||||
;; | ||||
diff) | ||||
_hg_status "mar" | ||||
;; | ||||
revert) | ||||
_hg_debugpathcomplete | ||||
;; | ||||
clone) | ||||
local count=$(_hg_count_non_option) | ||||
if [ $count = 1 ]; then | ||||
_hg_paths | ||||
fi | ||||
_hg_repos | ||||
;; | ||||
debugindex|debugindexdot) | ||||
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.i" -- "$cur")) | ||||
;; | ||||
debugdata) | ||||
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.d" -- "$cur")) | ||||
;; | ||||
*) | ||||
return 1 | ||||
;; | ||||
Martin Geisler
|
r10028 | esac | ||
return 0 | ||||
} | ||||
Sean Farley
|
r20126 | complete -o bashdefault -o default -o nospace -F _hg hg \ | ||
|| complete -o default -o nospace -F _hg hg | ||||
Martin Geisler
|
r10028 | |||
# Completion for commands provided by extensions | ||||
# bookmarks | ||||
_hg_cmd_bookmarks() | ||||
{ | ||||
Sean Farley
|
r20127 | _hg_bookmarks | ||
return | ||||
Martin Geisler
|
r10028 | } | ||
# mq | ||||
_hg_ext_mq_patchlist() | ||||
{ | ||||
local patches | ||||
Brodie Rao
|
r11646 | patches=$(_hg_cmd $1) | ||
Martin Geisler
|
r10028 | if [ $? -eq 0 ] && [ "$patches" ]; then | ||
Sean Farley
|
r20123 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur")) | ||
return 0 | ||||
Martin Geisler
|
r10028 | fi | ||
return 1 | ||||
} | ||||
_hg_ext_mq_queues() | ||||
{ | ||||
Brodie Rao
|
r11646 | local root=$(_hg_cmd root) | ||
Martin Geisler
|
r10028 | local n | ||
for n in $(cd "$root"/.hg && compgen -d -- "$cur"); do | ||||
Sean Farley
|
r20123 | # I think we're usually not interested in the regular "patches" queue | ||
# so just filter it. | ||||
if [ "$n" != patches ] && [ -e "$root/.hg/$n/series" ]; then | ||||
COMPREPLY=(${COMPREPLY[@]:-} "$n") | ||||
fi | ||||
Martin Geisler
|
r10028 | done | ||
} | ||||
_hg_cmd_qpop() | ||||
{ | ||||
if [[ "$prev" = @(-n|--name) ]]; then | ||||
Sean Farley
|
r20123 | _hg_ext_mq_queues | ||
return | ||||
Martin Geisler
|
r10028 | fi | ||
_hg_ext_mq_patchlist qapplied | ||||
} | ||||
_hg_cmd_qpush() | ||||
{ | ||||
if [[ "$prev" = @(-n|--name) ]]; then | ||||
Sean Farley
|
r20123 | _hg_ext_mq_queues | ||
return | ||||
Martin Geisler
|
r10028 | fi | ||
_hg_ext_mq_patchlist qunapplied | ||||
} | ||||
_hg_cmd_qgoto() | ||||
{ | ||||
if [[ "$prev" = @(-n|--name) ]]; then | ||||
Sean Farley
|
r20123 | _hg_ext_mq_queues | ||
return | ||||
Martin Geisler
|
r10028 | fi | ||
_hg_ext_mq_patchlist qseries | ||||
} | ||||
_hg_cmd_qdelete() | ||||
{ | ||||
local qcmd=qunapplied | ||||
if [[ "$prev" = @(-r|--rev) ]]; then | ||||
Sean Farley
|
r20123 | qcmd=qapplied | ||
Martin Geisler
|
r10028 | fi | ||
_hg_ext_mq_patchlist $qcmd | ||||
} | ||||
_hg_cmd_qfinish() | ||||
{ | ||||
if [[ "$prev" = @(-a|--applied) ]]; then | ||||
Sean Farley
|
r20123 | return | ||
Martin Geisler
|
r10028 | fi | ||
_hg_ext_mq_patchlist qapplied | ||||
} | ||||
_hg_cmd_qsave() | ||||
{ | ||||
if [[ "$prev" = @(-n|--name) ]]; then | ||||
Sean Farley
|
r20123 | _hg_ext_mq_queues | ||
return | ||||
Martin Geisler
|
r10028 | fi | ||
} | ||||
Kevin Bullock
|
r17463 | _hg_cmd_rebase() { | ||
if [[ "$prev" = @(-s|--source|-d|--dest|-b|--base|-r|--rev) ]]; then | ||||
_hg_labels | ||||
return | ||||
fi | ||||
} | ||||
Martin Geisler
|
r10028 | _hg_cmd_strip() | ||
{ | ||||
Kevin Bullock
|
r13509 | _hg_labels | ||
Martin Geisler
|
r10028 | } | ||
_hg_cmd_qcommit() | ||||
{ | ||||
Brodie Rao
|
r11646 | local root=$(_hg_cmd root) | ||
Martin Geisler
|
r10028 | # this is run in a sub-shell, so we can't use _hg_status | ||
Brodie Rao
|
r11646 | local files=$(cd "$root/.hg/patches" && _hg_cmd status -nmar) | ||
Martin Geisler
|
r10028 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur")) | ||
} | ||||
_hg_cmd_qfold() | ||||
{ | ||||
_hg_ext_mq_patchlist qunapplied | ||||
} | ||||
_hg_cmd_qrename() | ||||
{ | ||||
_hg_ext_mq_patchlist qseries | ||||
} | ||||
_hg_cmd_qheader() | ||||
{ | ||||
_hg_ext_mq_patchlist qseries | ||||
} | ||||
_hg_cmd_qclone() | ||||
{ | ||||
local count=$(_hg_count_non_option) | ||||
if [ $count = 1 ]; then | ||||
Sean Farley
|
r20123 | _hg_paths | ||
Martin Geisler
|
r10028 | fi | ||
_hg_repos | ||||
} | ||||
_hg_ext_mq_guards() | ||||
{ | ||||
Brodie Rao
|
r11646 | _hg_cmd qselect --series | sed -e 's/^.//' | ||
Martin Geisler
|
r10028 | } | ||
_hg_cmd_qselect() | ||||
{ | ||||
local guards=$(_hg_ext_mq_guards) | ||||
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$guards' -- "$cur")) | ||||
} | ||||
_hg_cmd_qguard() | ||||
{ | ||||
local prefix='' | ||||
if [[ "$cur" == +* ]]; then | ||||
Sean Farley
|
r20123 | prefix=+ | ||
Martin Geisler
|
r10028 | elif [[ "$cur" == -* ]]; then | ||
Sean Farley
|
r20123 | prefix=- | ||
Martin Geisler
|
r10028 | fi | ||
local ncur=${cur#[-+]} | ||||
if ! [ "$prefix" ]; then | ||||
Sean Farley
|
r20123 | _hg_ext_mq_patchlist qseries | ||
return | ||||
Martin Geisler
|
r10028 | fi | ||
local guards=$(_hg_ext_mq_guards) | ||||
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -P $prefix -W '$guards' -- "$ncur")) | ||||
} | ||||
_hg_opt_qguard() | ||||
{ | ||||
local i | ||||
for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do | ||||
Sean Farley
|
r20123 | if [[ ${COMP_WORDS[i]} != -* ]]; then | ||
if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then | ||||
_hg_cmd_qguard | ||||
return 0 | ||||
fi | ||||
elif [ "${COMP_WORDS[i]}" = -- ]; then | ||||
_hg_cmd_qguard | ||||
return 0 | ||||
fi | ||||
Martin Geisler
|
r10028 | done | ||
return 1 | ||||
} | ||||
"Yann E. MORIN"
|
r11768 | _hg_cmd_qqueue() | ||
{ | ||||
local q | ||||
local queues | ||||
"Yann E. MORIN"
|
r11968 | local opts="--list --create --rename --delete --purge" | ||
"Yann E. MORIN"
|
r11768 | |||
queues=$( _hg_cmd qqueue --quiet ) | ||||
COMPREPLY=( $( compgen -W "${opts} ${queues}" "${cur}" ) ) | ||||
} | ||||
Martin Geisler
|
r10028 | |||
# hbisect | ||||
_hg_cmd_bisect() | ||||
{ | ||||
local i subcmd | ||||
# find the sub-command | ||||
for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do | ||||
Sean Farley
|
r20123 | if [[ ${COMP_WORDS[i]} != -* ]]; then | ||
if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then | ||||
subcmd="${COMP_WORDS[i]}" | ||||
break | ||||
fi | ||||
fi | ||||
Martin Geisler
|
r10028 | done | ||
if [ -z "$subcmd" ] || [ $COMP_CWORD -eq $i ] || [ "$subcmd" = help ]; then | ||||
Sean Farley
|
r20123 | COMPREPLY=(${COMPREPLY[@]:-} | ||
$(compgen -W 'bad good help init next reset' -- "$cur")) | ||||
return | ||||
Martin Geisler
|
r10028 | fi | ||
case "$subcmd" in | ||||
Sean Farley
|
r20123 | good|bad) | ||
_hg_labels | ||||
;; | ||||
Martin Geisler
|
r10028 | esac | ||
return | ||||
} | ||||
# patchbomb | ||||
_hg_cmd_email() | ||||
{ | ||||
case "$prev" in | ||||
Sean Farley
|
r20123 | -c|--cc|-t|--to|-f|--from|--bcc) | ||
# we need an e-mail address. let the user provide a function | ||||
# to get them | ||||
if [ "$(type -t _hg_emails)" = function ]; then | ||||
local arg=to | ||||
if [[ "$prev" == @(-f|--from) ]]; then | ||||
arg=from | ||||
fi | ||||
local addresses=$(_hg_emails $arg) | ||||
COMPREPLY=(${COMPREPLY[@]:-} | ||||
$(compgen -W '$addresses' -- "$cur")) | ||||
fi | ||||
return | ||||
;; | ||||
-m|--mbox) | ||||
# fallback to standard filename completion | ||||
return | ||||
;; | ||||
-s|--subject) | ||||
# free form string | ||||
return | ||||
;; | ||||
Martin Geisler
|
r10028 | esac | ||
Kevin Bullock
|
r13509 | _hg_labels | ||
Martin Geisler
|
r10028 | return | ||
} | ||||
# gpg | ||||
_hg_cmd_sign() | ||||
{ | ||||
Kevin Bullock
|
r13509 | _hg_labels | ||
Martin Geisler
|
r10028 | } | ||
# transplant | ||||
_hg_cmd_transplant() | ||||
{ | ||||
case "$prev" in | ||||
Sean Farley
|
r20123 | -s|--source) | ||
_hg_paths | ||||
_hg_repos | ||||
return | ||||
;; | ||||
--filter) | ||||
# standard filename completion | ||||
return | ||||
;; | ||||
Martin Geisler
|
r10028 | esac | ||
# all other transplant options values and command parameters are revisions | ||||
Kevin Bullock
|
r13509 | _hg_labels | ||
Martin Geisler
|
r10028 | return | ||
} | ||||
# shelve | ||||
_hg_shelves() | ||||
{ | ||||
Sean Farley
|
r20128 | local shelves="$(_hg_cmd shelve -ql)" | ||
Martin Geisler
|
r10028 | local IFS=$'\n' | ||
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$shelves' -- "$cur")) | ||||
} | ||||
_hg_cmd_shelve() | ||||
{ | ||||
_hg_status "mard" | ||||
} | ||||
_hg_cmd_unshelve() | ||||
{ | ||||
_hg_shelves | ||||
} | ||||