ฉันจะได้รับการทุบตีเสร็จสิ้นเพื่อทำงานกับนามแฝงได้อย่างไร


195

กรณีในจุด:

ฉันเป็น mac ที่มี bash v3.2.17 ฉันใช้ git ติดตั้งผ่าน macports กับตัวแปร bash_completion

git checkout m<tab>เมื่อฉันพิมพ์ masterสำหรับตัวอย่างเช่นผมได้รับมันเสร็จสิ้นการ

แต่ผมได้มีชื่อแทน,git checkout gcoเมื่อฉันพิมพ์gco m<tab>ฉันจะไม่ได้รับชื่อสาขาที่เติมข้อความอัตโนมัติ

เป็นการดีที่ฉันต้องการการเติมข้อความอัตโนมัติเพื่อทำงานแทนนามแฝงทั้งหมดของฉันอย่างน่าอัศจรรย์ เป็นไปได้ไหม? ความล้มเหลวนั้นฉันต้องการกำหนดค่าด้วยตนเองสำหรับแต่ละนามแฝง ดังนั้นฉันจะไปเกี่ยวกับวิธีใด


3
เสร็จสมบูรณ์ -o เริ่มต้น -o nospace -F ไม่ทำงานในปัจจุบัน
eighteyes

5
คำถามที่มี upvotes มากกว่าคำตอบด้านบนมักจะหมายความถึงการที่ดีในการร้องขอคุณสมบัติ
Ciro Santilli郝海东冠状病六四事件法轮功

2
อีกคำตอบจาก superuser เป็นคนชี้ให้ฉันเห็นว่าคำถามของฉันมีล่อคู่ของนี้ superuser.com/questions/436314/…
dstarh

คำตอบ:


183

ตามที่ระบุไว้ในความคิดเห็นข้างต้น

complete -o default -o nospace -F _git_checkout gco

จะไม่ทำงานอีกต่อไป อย่างไรก็ตามมี__git_completeฟังก์ชั่นใน git-completion.bash ซึ่งสามารถใช้ในการตั้งค่าความสมบูรณ์สำหรับนามแฝงดังนี้

__git_complete gco _git_checkout

6
นี่เป็นคำตอบที่ถูกต้องเพียงข้อเดียวที่ฉันเคยเห็นในหลาย ๆ ข้อผิดพลาด
eighteyes

45
หากคุณใช้นามแฝงส่วนกลาง "g" สำหรับ git คุณสามารถเพิ่ม__git_complete g __git_mainเพื่อให้การเติมโค้ดทำงานกับคำสั่ง git ทั้งหมดได้
Ondrej Machulda

5
^^ สำหรับผู้ที่ยังใหม่ต่อคอมไพล์ / เชลล์ / bash ความคิดเห็นข้างต้นหมายถึงนามแฝงเชลล์ทั่วโลกไม่ใช่นามแฝง git ดั้งเดิม
Elijah Lynn

14
ฉันควรใส่สิ่งนี้ที่ไหน
benregn

15
ในที่สุดคิดวิธีการทำอย่างถูกต้อง! ขั้นตอนที่ 1) คัดลอกgit-completion.bashจาก<your git install folder>/etc/bash-completion.d/ไปยัง~/.git-completion.bash ขั้นตอนที่ 2) เพิ่มsource ~/.git-completion.bashไปยัง.bash_profile ขั้นตอนที่ 3) เพิ่ม__git_complete gco _git_checkoutที่ใดก็ได้หลังจากบรรทัดด้านบนใน. bash_profile ของคุณ ขั้นตอนที่ 4) รีบูตเชลล์และเพลิดเพลินไปกับนามแฝงอัตโนมัติของคุณ! :)
kpsfoo

54

ฉันพบปัญหานี้เช่นกันและเกิดขึ้นกับข้อมูลโค้ดนี้ สิ่งนี้จะทำให้คุณทำนามแฝงทั้งหมดโดยอัตโนมัติ เรียกใช้หลังจากประกาศนามแฝงทั้งหมด (หรือใด ๆ )

# wrap_alias takes three arguments:
# $1: The name of the alias
# $2: The command used in the alias
# $3: The arguments in the alias all in one string
# Generate a wrapper completion function (completer) for an alias
# based on the command and the given arguments, if there is a
# completer for the command, and set the wrapper as the completer for
# the alias.
function wrap_alias() {
  [[ "$#" == 3 ]] || return 1

  local alias_name="$1"
  local aliased_command="$2"
  local alias_arguments="$3"
  local num_alias_arguments=$(echo "$alias_arguments" | wc -w)

  # The completion currently being used for the aliased command.
  local completion=$(complete -p $aliased_command 2> /dev/null)

  # Only a completer based on a function can be wrapped so look for -F
  # in the current completion. This check will also catch commands
  # with no completer for which $completion will be empty.
  echo $completion | grep -q -- -F || return 0

  local namespace=alias_completion::

  # Extract the name of the completion function from a string that
  # looks like: something -F function_name something
  # First strip the beginning of the string up to the function name by
  # removing "* -F " from the front.
  local completion_function=${completion##* -F }
  # Then strip " *" from the end, leaving only the function name.
  completion_function=${completion_function%% *}

  # Try to prevent an infinite loop by not wrapping a function
  # generated by this function. This can happen when the user runs
  # this twice for an alias like ls='ls --color=auto' or alias l='ls'
  # and alias ls='l foo'
  [[ "${completion_function#$namespace}" != $completion_function ]] && return 0

  local wrapper_name="${namespace}${alias_name}"

  eval "
function ${wrapper_name}() {
  let COMP_CWORD+=$num_alias_arguments
  args=( \"${alias_arguments}\" )
  COMP_WORDS=( $aliased_command \${args[@]} \${COMP_WORDS[@]:1} )
  $completion_function
  }
"

  # To create the new completion we use the old one with two
  # replacements:
  # 1) Replace the function with the wrapper.
  local new_completion=${completion/-F * /-F $wrapper_name }
  # 2) Replace the command being completed with the alias.
  new_completion="${new_completion% *} $alias_name"

  eval "$new_completion"
}

# For each defined alias, extract the necessary elements and use them
# to call wrap_alias.
eval "$(alias -p | sed -e 's/alias \([^=][^=]*\)='\''\([^ ][^ ]*\) *\(.*\)'\''/wrap_alias \1 \2 '\''\3'\'' /')"

unset wrap_alias

6
บรรทัดlet COMP_CWORD+=$num_alias_argumentsไม่ทำงานบน Mac OS X ด้วยเหตุผลบางประการ แทนที่ด้วยการ((COMP_CWORD+=$num_alias_arguments))แก้ไขแม้ว่า
Mario F

5
ว้าวเยี่ยมมาก - ขอบคุณ! wrap_aliasฉายาในราคาคู่ในความหมายนามแฝงและผมคิดว่ามันไม่ได้ทำให้ความรู้สึกมากสำหรับนามแฝงหลายคำสั่ง ( alias 'foo=bar; baz') ดังนั้นฉันวางเป็นพิเศษหลังจากที่| grep -v '[";|&]' alias -pนอกจากนี้มันจะช้าลงเล็กน้อยสำหรับคำจำกัดความของนามแฝงหลายร้อยคำ แต่ฉันยินดีที่จะยืนยันว่าการใช้echoแทนevalและไพพ์เอาต์พุตลงในไฟล์แคช (ซึ่งสามารถeval'ed ในครั้งเดียว) ทำงานได้ดีและเร็วมาก .
Jo Liss

2
คำแนะนำอื่น ๆ : wrap_aliasต้องสำเร็จที่จะตั้งขึ้นเพื่อให้ฉันได้ย้ายsource /etc/bash_completionในด้านหน้าของwrap_aliasรหัส
Jo Liss

2
นี้ทำงานสำหรับฉันใน OS X 10.7.2 หลังจากเปลี่ยนสายไปlet COMP_CWORD+=$num_alias_arguments let \"COMP_CWORD+=$num_alias_arguments\"
irh

7
ดูเวอร์ชันล่าสุดของสคริปต์นี้ที่superuser.com/a/437508/102281 (ตัวอย่างเช่นฉันเพิ่มการสนับสนุนสำหรับ COMP_LINE และ COMP_POINT ซึ่งจำเป็นสำหรับการคอมไพล์บางส่วน)
John Mellor

18

ในgit-completion.bashบรรทัดมี:

complete -o default -o nospace -F _git git

ดูที่บรรทัดนั้น (และฟังก์ชัน _git) คุณสามารถเพิ่มบรรทัดนี้ใน.bash_profile:

complete -o default -o nospace -F _git_checkout gco

4
บางฟังก์ชั่นgit * bash ไม่สามารถใช้งานได้โดยใช้วิธีนี้อีกต่อไป
cmcginty

ใช่สิ่งนี้เคยทำงานได้ดีจนกระทั่งมีบางสิ่งเปลี่ยนไปใน git_completion.bash ... ตอนนี้มันใช้ได้กับคำสั่งแบบเต็ม แต่ไม่ใช่กับนามแฝง
Michael Smith

ดูตอนท้ายของหน้านี้สำหรับคำตอบที่ทำงานในคอมไพล์สมัยใหม่
eighteyes

เราไม่ควรเปลี่ยนคำตอบที่ยอมรับให้เป็น "คำตอบที่ถูกต้อง" หรืออย่างน้อยอัปเดตคำตอบที่ยอมรับเพื่อให้สอดคล้องกับการเปลี่ยนแปลง?
Tony K.

ใช้งานได้ดี - เพิ่มสิ่งนี้ลงใน. bash_profile ของฉันและใช้งานได้ดีกับและไม่มีนามแฝง: github.com/larrybotha/dotfiles/blob/master/ ......
Larry

15

ฉันมีนามแฝง g = 'git' และรวมกับนามแฝง git ของฉันฉันพิมพ์สิ่งต่าง ๆ เช่น

$ g co <branchname>

การแก้ไขที่ง่ายกว่าสำหรับกรณีการใช้งานเฉพาะของฉันคือการเพิ่มหนึ่งบรรทัดในการเติมคอมไพล์

ด้านล่างบรรทัดนี้:

__git_complete git _git

ฉันเพิ่มบรรทัดนี้เพื่อจัดการนามแฝง 'g' เดียวของฉัน:

__git_complete g _git

2
(ฉันใช้ Cygwin) ฉันหาไฟล์git-completionหรือบรรทัดนั้นไม่พบ/etc/bash_completion.d/gitแต่ฉันเพิ่มcomplete -o default -o nospace -F _git gหลังจากนามแฝงของฉัน.bash_aliasesแล้วก็ใช้งานได้!
idbrii

ระวังว่าถ้าคุณแก้ไขไฟล์ใน/etc/bash-completion.d/หรือใหม่/usr/share/bash-completion/คุณจะสูญเสียการเปลี่ยนแปลงเมื่อใดก็ตามที่ไฟล์นั้นได้รับการอัพเดตโดยใช้แพ็คเกจผู้จัดการ
kub1x

14

เป็นการดีที่ฉันต้องการเติมข้อความอัตโนมัติเพื่อทำงานแทนนามแฝงทั้งหมดของฉันอย่างน่าอัศจรรย์ เป็นไปได้ไหม?

ใช่เป็นไปได้ด้วยโครงการนามแฝง (บน Linux) การสนับสนุนสำหรับ Mac เป็นการทดลอง แต่ผู้ใช้รายงานความสำเร็จแล้ว


4
ขอบคุณมากนี่เป็นสิ่งที่ดีกว่าการหาว่ายูทิลิตี้ทุกอย่างในโลกใช้การทุบตีเสร็จสิ้นอย่างไร
artm

2
ที่จริงช่วยฉันสักครู่การกำหนดค่าความสำเร็จสำหรับนามแฝง
Samir Alajmovic

2
ทำงานได้อย่างมีเสน่ห์บน Linux (ไม่ได้ทดสอบบน Mac) ขอบคุณที่เขียนมัน!
bitmask

1
นี่มันยอดเยี่ยมมาก! มันใช้งานได้ไม่ยุ่งยากมากขึ้นดีกว่า! ขอบคุณ!
emi

5

คุณสามารถลองใช้นามแฝง Git ตัวอย่างเช่นใน~/.gitconfigไฟล์ของฉันฉันมีส่วนที่มีลักษณะเช่นนี้:

[alias]
        co = checkout

ดังนั้นคุณสามารถพิมพ์git co m<TAB>และควรขยายไปgit co masterซึ่งเป็นgit checkoutคำสั่ง


5

หน้าฟอรัมนี้แสดงวิธีแก้ไข

ใส่บรรทัดเหล่านี้ในของคุณ.bashrcหรือ.bash_profile:

# Author.: Ole J
# Date...: 23.03.2008
# License: Whatever

# Wraps a completion function
# make-completion-wrapper <actual completion function> <name of new func.>
#                         <command name> <list supplied arguments>
# eg.
#   alias agi='apt-get install'
#   make-completion-wrapper _apt_get _apt_get_install apt-get install
# defines a function called _apt_get_install (that's $2) that will complete
# the 'agi' alias. (complete -F _apt_get_install agi)
#
function make-completion-wrapper () {
    local function_name="$2"
    local arg_count=$(($#-3))
    local comp_function_name="$1"
    shift 2
    local function="
function $function_name {
    ((COMP_CWORD+=$arg_count))
    COMP_WORDS=( "$@" \${COMP_WORDS[@]:1} )
    "$comp_function_name"
    return 0
}"
    eval "$function"
}

# and now the commands that are specific to this SO question

alias gco='git checkout'

# we create a _git_checkout_mine function that will do the completion for "gco"
# using the completion function "_git"
make-completion-wrapper _git _git_checkout_mine git checkout

# we tell bash to actually use _git_checkout_mine to complete "gco"
complete -o bashdefault -o default -o nospace -F _git_checkout_mine gco

วิธีนี้คล้ายกับสคริปต์ของ balshetzerแต่มีเพียงอันเดียวที่ใช้งานได้จริงสำหรับฉัน (สคริปต์ของ balshetzer มีปัญหากับนามแฝงของฉัน)


เกือบจะใช้ได้ - ฉันได้รับข้อผิดพลาดสองสามอย่าง มีอะไรอีกที่ฉันสามารถทำได้? -bash: eval: line 28: unexpected EOF while looking for matching ''' -bash: eval: line 29: syntax error: unexpected end of file
pforhan

@pforhan ฉันสามารถดู quoting ปัญหาดังกล่าวข้างต้นที่ ... "คำพูดภายในสตริงควรจะยกมาเป็นfunction \"นี่อาจกินหนึ่งใน'คำพูดของคุณที่ใดที่หนึ่งในบรรทัด
Tom Hale

5

อีกทางเลือกหนึ่งคือการใช้~/.bash_completionไฟล์ หากต้องการสร้างgcoนามแฝงสำหรับgit checkoutใส่สิ่งนี้ใน:

_xfunc git __git_complete gco _git_checkout

จากนั้นใน~/.bashrcคุณจะต้องใส่นามแฝงตัวเอง:

alias gco='git checkout'

สองเส้น แค่นั้นแหละ.

คำอธิบาย:

~/bash_completionได้รับมาในตอนท้ายของสคริปต์ bash_completion หลัก ใน gentoo ฉันพบสคริปต์หลักใน/usr/share/bash-completion/bash_completionมา

_xfunc gitบิตดูแลจัดหาไฟล์สำหรับคุณเพื่อให้คุณไม่จำเป็นที่จะนำสิ่งอื่นใดในgit-completion~/.bashrc

คำตอบที่ได้รับการยอมรับต้องการให้คุณคัดลอก.git-completion.shและแหล่งที่มาจาก~/.bashrcไฟล์ที่ฉันพบว่าง่อย


PS: ฉันยังคงพยายามหาวิธีที่จะไม่ให้git-completionสคริปต์ทั้งหมดในสภาพแวดล้อมทุบตีของฉัน กรุณาแสดงความคิดเห็นหรือแก้ไขหากคุณหาวิธี


ทำไม_xfunc gitต้องมี?
Tom Hale

@ TomHale ฉันพยายามปรับปรุงคำตอบ แทนที่จะsource ~/.git-completion.shปล่อยให้ฉัน_xfuncทำเพื่อฉัน มันก็ให้ความรู้สึกที่ดีกว่าและทำความสะอาดที่จะทำมัน ~/.bash_completionแต่เพียงผู้เดียวใน หากไม่มี_xfunc(หรือการจัดหา) __git_completeฟังก์ชันจะไม่มีอยู่
kub1x

1
ไม่มีความจำเป็นในการ~/.bash_completionแฟ้ม - The เส้นการทำงานสำหรับฉันใน_xfunc .bashrc
Tom Hale

2

คุณเพียงแค่ต้องค้นหาcompleteคำสั่งและทำซ้ำบรรทัดที่มีชื่อนามแฝงแทน

alias d-m="docker-machine"ฉันมี ในคำพูดจะเป็นนามแฝงสำหรับ d-mdocker-machine

ดังนั้นบน Mac (ผ่านการชง), cd `brew --prefix`/etc/bash_completion.d/ไฟล์เสร็จอยู่ใน สำหรับกรณีของฉันฉันแก้ไขไฟล์ที่เรียกว่า
ตลอดทางที่ด้านล่างมี:docker-machine

complete -F _docker_machine docker-machine

ดังนั้นฉันเพิ่งเพิ่มอีกบรรทัดด้วยนามแฝงของฉัน:

complete -F _docker_machine docker-machine
complete -F _docker_machine d-m

นี่คือทางออกที่ดีที่สุดสำหรับง่าย (1-1) นามแฝงเช่นนามแฝงdocker dแม้ว่าตัวอย่างในคำถามgit checkoutจะgcoมีความซับซ้อนมากกว่าก็ตาม
wisbucky

1

ก่อนอื่นให้ค้นหาคำสั่งเสร็จสิ้นต้นฉบับ ตัวอย่าง:

$ complete | grep git

complete -o bashdefault -o default -o nospace -F __git_wrap__git_main git

ตอนนี้เพิ่มสิ่งเหล่านี้ในสคริปต์เริ่มต้นของคุณ (เช่น ~ / .bashrc):

# copy the original statement, but replace the last command (git) with your alias (g)
complete -o bashdefault -o default -o nospace -F __git_wrap__git_main g

# load dynamically loaded completion functions (may not be required)
_completion_loader git

_completion_loaderบรรทัดอาจไม่จำเป็นต้อง แต่สำหรับบางสถานการณ์ฟังก์ชั่นเสร็จจะโหลดแบบไดนามิกหลังจากคุณพิมพ์คำสั่งและกดTABครั้งแรกเท่านั้น ดังนั้นหากคุณไม่ได้ใช้คำสั่งดั้งเดิมและลองใช้นามแฝง + TABคุณอาจได้รับข้อผิดพลาดเช่น "bash: complete: function '_docker' not found"


1

มีคำตอบมากมายสำหรับคำถามนี้และชอบตัวเองฉันเดิมพันผู้อ่านที่สับสนมากมาย สำหรับกรณีของฉันฉันมีข้อกำหนดที่จะให้ dotfiles ของฉันทำงานบนหลายแพลตฟอร์มด้วย Git รุ่นต่างๆ ฉันยังไม่ได้alias g=gitแต่มีgกำหนดไว้เป็นฟังก์ชั่น

เพื่อให้บรรลุสิ่งนี้ฉันต้องตบคำตอบที่แตกต่างกันที่นี่ไว้ในโซลูชันเดียว แม้ว่าสิ่งนี้จะย้ำคำตอบแล้วฉันคิดว่าบางคนในเรือของฉันอาจพบว่าการรวบรวมนี้มีประโยชน์อย่างที่ฉันจะได้เมื่อฉันมาถึงคำถามนี้ครั้งแรก

สิ่งนี้จะถือว่า Git ที่เก่าและใหม่กว่าเป็นค่าเริ่มต้นของ Ubuntu และbrew install gitใน MacOS ในกรณีต่อมาการต้มเบียร์ที่ติดตั้งเสร็จแล้วไม่ได้รับการประมวลผลโดยการทุบตี (สิ่งที่ฉันจะวินิจฉัยในภายหลัง)

# Alias g to git

g() {
  if [[ $# > 0 ]]; then
    git "$@"
  else
    git status -sb
  fi
}

# Preload git completion in Ubuntu which is normally lazy loaded but we need
# the __git_wrap__git_main function available for our completion.
if [[ -e /usr/share/bash-completion/completions/git ]]; then
  source /usr/share/bash-completion/completions/git
elif [[ -e /usr/local/etc/bash_completion.d/git-completion.bash ]]; then
  source /usr/local/etc/bash_completion.d/git-completion.bash
fi

if command_exists __git_complete; then
  __git_complete g _git
elif command_exists __git_wrap__git_main; then
  complete -o bashdefault -o default -o nospace -F __git_wrap__git_main g
fi

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.