Bash $ PROMPT_COMMAND làm rối màn hình lịch sử cuộn


7

Tôi thiết lập một PROMPT_COMMANDđể hiển thị chi nhánh hiện tại trong khi tôi đang ở trong một repo git.

Phần có liên quan của .bashrc của tôi là:

export PS1=" \[\033[34m\]\$\[\033[0m\] "
export PROMPT_COMMAND="$HOME/bin/myprompt"

trong đó ~ / bin / myprompt là:

#!/usr/bin/env ruby
green = "\033[32m"
bold = "\033[1m"
underline = "\033[4m"
reset = "\033[0m"

home_regex = Regexp.new "^#{ENV["HOME"]}"
Dir.chdir ENV["PWD"]

out = 
  underline + bold + green +
  `pwd`.gsub(home_regex, "~").chomp +
  reset

if `git log 2>&1 | grep ^fatal`.chomp == ""
  out += "#{underline}#{green} (#{`git branch | grep ^\* | sed s/^..//g`.chomp})#{reset}"
end

print out

Nó hoạt động tốt với hầu hết các phần, vấn đề duy nhất là khi tôi sử dụng các phím mũi tên để cuộn qua lịch sử lệnh, đôi khi lệnh được ghi qua dấu nhắc của tôi. Giả sử phiên sau:

~ $ pwd
/Users/Adrian
~ $ cd sibilant
~/sibilant (master) $ pwd
/Users/Adrian/sibilant
~/sibilant (master) $

Sau đó, tôi nhấn mũi tên lên để cuộn qua lịch sử lệnh. mỗi dòng hiển thị kết quả của một lần nhấn mũi tên:

~/sibilant (master) $ pwd
~/sibilant (master) $ cd sibilant
~/spwd

như bạn có thể thấy, lần cuối cùng tôi nhấn mũi tên, lệnh được viết trên dấu nhắc của tôi.

Có ai có kinh nghiệm này và / hoặc biết cách khắc phục nó?

Câu trả lời:


11

Thay vì đặt nó vào PROMPT_COMMAND, hãy đặt nó vào PS1:

PS1='$($HOME/bin/myprompt) \[\033[34m\]\$\[\033[0m\] '

Khi vào PS1, bash đếm số lượng ký tự được in để nó có thể vẽ lại chính xác khi bạn cuộn qua lịch sử của mình. Đó là lý do tại sao bash có các ký tự đặc biệt \[\]họ nói với bash rằng các ký tự kèm theo không thể in được, điều này giúp bash tìm ra cách vẽ lại dấu nhắc khi cần thiết.

Lưu ý rằng sự thay thế lệnh nằm trong dấu ngoặc đơn. Điều này ngăn cản sự mở rộng tại thời điểm chuyển nhượng. Nếu thay thế lệnh là trong dấu ngoặc kép hoặc không trích dẫn, đầu ra của mypromptsẽ được ghi lại một lần tại thời điểm gán và duy trì trạng thái tĩnh. Để hỗ trợ các giá trị biến thay đổi theo thời gian, trình bao mở rộng giá trị của PS1mỗi lần dấu nhắc được hiển thị. Điều này có nghĩa là việc mở rộng nên được ngăn chặn tại thời điểm chuyển nhượng bằng cách trích dẫn. Điều đó cũng có nghĩa là bạn cần cẩn thận về tốc độ: nếu việc thay thế lệnh mất 1 giây để hoàn thành, thì lời nhắc của bạn sẽ mất 1 giây để hiển thị.


Cảm ơn, nhưng sẽ không gán tĩnh đầu ra mypromptcho PS1 chứ? Tôi nhớ đã cố gắng làm một cái gì đó như thế trước đây.

1
Rất tiếc, đó là một lỗi. Tôi sửa nó rồi. Việc thay thế lệnh phải nằm trong dấu ngoặc đơn. Tôi có thói quen mở rộng các biến và thay thế lệnh tại thời điểm gán vì đó là điều tôi muốn 99% thời gian. PS1là một trong những trường hợp ngoại lệ hiếm hoi.
Richard Hansen

Cảm ơn vì lời giải thích chi tiết; điều này đã giúp tôi sửa PS1 của tôi. Tôi đã PS1='\033]0;\u@\h\007[\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\]]\$ 'đặt tiêu đề cửa sổ và hiển thị 'user @ host full-path $' nhưng con trỏ đang quấn bất ngờ. Sau khi thêm \[\]để trông như thế này: PS1='\[\033]0;\u@\h\007\][\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\]]\$ 'nó hoạt động tốt!
Benjamin Goodacre

0

PROMPT_COMMAND có thể chứa một lệnh được thực thi trước khi dấu nhắc mới được in bằng bash (vì vậy trước khi PS1 được ước tính).

Với git 1.8.1, mã để thực hiện điều này một cách hiệu quả với PROMPT_COMMAND đã được phát hành. Xem bằng cách sử dụng git-prompt.sh với PROMPT_COMMAND . Mã có thể hoạt động với các phiên bản trước của git, chỉ cần sao chép tệp contrib / xong / git-prompt.sh đến một nơi mà bạn có thể lấy nguồn từ .bashrc của mình.

Chúc mừng

Simon

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.