zsh phải chứng minh trong ps1


21

Tôi muốn một dấu nhắc zsh nhiều dòng với phần bên phải, nó sẽ trông giống như thế này:

2.nate@host:/current/dir                                               16:00
->

Tôi biết về RPROMPT trong zsh, nhưng nó có một dấu nhắc được căn phải đối diện với dấu nhắc thông thường của bạn, nằm trên cùng một dòng văn bản khi bạn gõ.

Có cách nào để có một phần được căn phải cho dòng đầu tiên của dấu nhắc lệnh nhiều dòng không? Tôi đang tìm kiếm một chỉ thị trong biến PS1 có nội dung 'căn chỉnh ngay bây giờ' hoặc một biến có trong PS1 RPROMPT là gì để KHUYẾN MÃI.

Cảm ơn!

Câu trả lời:


12

Bạn sẽ tìm thấy một câu trả lời chi tiết và một ví dụ ở đây . Ý tưởng là viết dòng trước PS1 bằng cách sử dụng precmdgọi lại, sử dụng $COLUMNSvà một chút toán học để tính toán vị trí của văn bản ở phía bên phải màn hình. Kiến thức về các chuỗi thoát cũng sẽ giúp bạn định vị con trỏ và tô màu.

Một giải pháp khác có thể là sử dụng một chủ đề từ Oh My ZSH .


10

Tôi cũng đang tìm kiếm cái này Đối với tôi, việc các precmd()đường được vẽ không vẽ lại khi thay đổi kích thước hoặc khi ^Lđược sử dụng để xóa màn hình là điều khiến tôi ngứa ngáy. Những gì tôi đang làm bây giờ là sử dụng các chuỗi thoát ANSI để di chuyển con trỏ xung quanh một chút. Mặc dù tôi nghi ngờ có một cách thanh lịch hơn để phát hành chúng, nhưng điều này hiệu quả với tôi:

_newline=$'\n'
_lineup=$'\e[1A'
_linedown=$'\e[1B'

PROMPT=...whatever...${_newline}...whatever...
RPROMPT=%{${_lineup}%}...whatever...%{${_linedown}%}

Hãy nhớ rằng hướng dẫn sử dụng zsh nói rằng% {...%} dành cho các chuỗi thoát theo nghĩa đen không di chuyển con trỏ . Mặc dù vậy, tôi đang sử dụng chúng vì chúng cho phép bỏ qua độ dài của nội dung của nó (không thể tìm ra cách phát hành lối thoát di chuyển con trỏ bằng cách sử dụng chúng)


Sau khi chơi xung quanh với điều này một thời gian, nó thỉnh thoảng làm rối và đặt con trỏ hoặc ngày sai dòng. Không phải là một vấn đề lớn mặc dù; chỉ có thể nhấn enter để sửa nó.
mpen

3

Đây là cách tôi đã cấu hình thứ này ngay bây giờ. Cách tiếp cận này không yêu cầu bất kỳ thao tác chuỗi thoát nào, nhưng sẽ khiến bạn có hai biến khác nhau cho dấu nhắc chính: PS1có màu và NPS1không có.

# Here NPS1 stands for "naked PS1" and isn't a built-in shell variable. I've
# defined it myself for PS1-PS2 alignment to operate properly.
PS1='%S%F{red}[%l]%f%s %F{green}%n@%m%f %B%#%b '
NPS1='[%l] %n@%m # '
RPS1='%B%F{green}(%~)%f%b'

# Hook function which gets executed right before shell prints prompt.
function precmd() {
    local expandedPrompt="$(print -P "$NPS1")"
    local promptLength="${#expandedPrompt}"
    PS2="> "
    PS2="$(printf "%${promptLength}s" "$PS2")"
}

Lưu ý việc sử dụng print -Pđể mở rộng nhanh chóng, ${#variable}để có được độ dài của chuỗi được lưu trữ trong biến và printf "%Nd"cho phần đệm bên trái có Nkhoảng trắng. Cả hai printprintfđều là các lệnh tích hợp, do đó sẽ không có hiệu năng.


1

Hãy xác định lời nhắc với bố cục này:

top_left              top_right
bottom_left        bottom_right

Để làm điều này, chúng ta sẽ cần một hàm cho chúng ta biết có bao nhiêu ký tự mà một chuỗi đã cho khi được in.

# Usage: prompt-length TEXT [COLUMNS]
#
# If you run `print -P TEXT`, how many characters will be printed
# on the last line?
#
# Or, equivalently, if you set PROMPT=TEXT with prompt_subst
# option unset, on which column will the cursor be?
#
# The second argument specifies terminal width. Defaults to the
# real terminal width.
#
# Assumes that `%{%}` and `%G` don't lie.
#
# Examples:
#
#   prompt-length ''            => 0
#   prompt-length 'abc'         => 3
#   prompt-length $'abc\nxy'    => 2
#   prompt-length '❎'          => 2
#   prompt-length $'\t'         => 8
#   prompt-length $'\u274E'     => 2
#   prompt-length '%F{red}abc'  => 3
#   prompt-length $'%{a\b%Gb%}' => 1
#   prompt-length '%D'          => 8
#   prompt-length '%1(l..ab)'   => 2
#   prompt-length '%(!.a.)'     => 1 if root, 0 if not
function prompt-length() {
  emulate -L zsh
  local COLUMNS=${2:-$COLUMNS}
  local -i x y=$#1 m
  if (( y )); then
    while (( ${${(%):-$1%$y(l.1.0)}[-1]} )); do
      x=y
      (( y *= 2 ));
    done
    local xy
    while (( y > x + 1 )); do
      m=$(( x + (y - x) / 2 ))
      typeset ${${(%):-$1%$m(l.x.y)}[-1]}=$m
    done
  fi
  echo $x
}

Chúng ta sẽ cần một hàm khác có hai đối số và in hoàn toàn tốt với các đối số này ở các cạnh đối diện của màn hình.

# Usage: fill-line LEFT RIGHT
#
# Prints LEFT<spaces>RIGHT with enough spaces in the middle
# to fill a terminal line.
function fill-line() {
  emulate -L zsh
  local left_len=$(prompt-length $1)
  local right_len=$(prompt-length $2 9999)
  local pad_len=$((COLUMNS - left_len - right_len - ${ZLE_RPROMPT_INDENT:-1}))
  if (( pad_len < 1 )); then
    # Not enough space for the right part. Drop it.
    echo -E - ${1}
  else
    local pad=${(pl.$pad_len.. .)}  # pad_len spaces
    echo -E - ${1}${pad}${2}
  fi
}

Cuối cùng, chúng ta có thể định nghĩa một hàm đặt PROMPTRPROMPThướng dẫn ZSH gọi hàm đó trước mỗi dấu nhắc và đặt các tùy chọn mở rộng dấu nhắc phù hợp:

# Sets PROMPT and RPROMPT.
#
# Requires: prompt_percent and no_prompt_subst.
function set-prompt() {
  emulate -L zsh
  local git_branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
  git_branch=${${git_branch//\%/%%}/\\/\\\\\\}  # escape '%' and '\'

  local top_left='%F{blue}%~%f'
  local top_right="%F{green}${git_branch}%f"
  local bottom_left='%B%F{%(?.green.red)}%#%f%b '
  local bottom_right='%F{yellow}%T%f'

  PROMPT="$(fill-line "$top_left" "$top_right")"$'\n'$bottom_left
  RPROMPT=$bottom_right
}

autoload -Uz add-zsh-hook
add-zsh-hook precmd set-prompt
setopt noprompt{bang,subst} prompt{cr,percent,sp}

Điều này tạo ra lời nhắc sau:

~/foo/bar                     master
%                             10:51
  • Trên cùng bên trái: Thư mục hiện tại màu xanh.
  • Trên cùng bên phải: Chi nhánh Git xanh.
  • Dưới cùng bên trái: #nếu root, %nếu không; xanh thành công, đỏ lỗi.
  • Dưới cùng bên phải: Thời gian hiện tại màu vàng.

Bạn có thể tìm thấy chi tiết bổ sung trong lời nhắc nhiều dòng: Thành phần còn thiếu và mã hoàn chỉnh trong ý chính này .


1
Chào mừng bạn đến với Siêu người dùng! Trong khi về mặt lý thuyết có thể trả lời câu hỏi, tốt hơn là nên bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo.
CaldeiraG

1
@CaldeiraG Tôi viết lại câu trả lời của mình theo đề nghị của bạn. FWIW, hình dạng của câu trả lời ban đầu của tôi đã được thông báo bởi câu trả lời được bình chọn cao nhất và được chấp nhận cho câu hỏi này.
Roman Perepelitsa

Có vẻ tốt hơn! : p Tận hưởng kỳ nghỉ của bạn ở đây
CaldeiraG
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.