Làm thế nào để bắt đầu XTerm với dấu nhắc ở phía dưới?


12

Khi bắt đầu XTerm, dấu nhắc bắt đầu ở dòng đầu tiên của thiết bị đầu cuối. Khi chạy lệnh, dấu nhắc di chuyển xuống cho đến khi chạm đáy, và từ đó trở đi nó vẫn ở đó (thậm chí không Shift- Page Downhoặc chuột có thể thay đổi điều này). Thay vì bắt đầu vòng đời của thiết bị đầu cuối là "đặc biệt" , dấu nhắc phải luôn luôn ở dưới cùng của thiết bị đầu cuối. Xin lưu ý rằng tôi có một dấu nhắc nhiều dòng .

Tất nhiên, nó nên hoạt động như trước đây (có thể thay đổi, có thể cuộn, không có dòng mới không cần thiết trong đầu ra và không có đầu ra biến mất một cách bí ẩn), vì vậy PROMPT_COMMAND='echo;echo;...'hoặc tương tự không phải là một tùy chọn. Các giải pháp lý tưởng không nên là vỏ cụ thể.

Chỉnh sửa: Các giải pháp hiện tại , trong khi làm việc trong các trường hợp đơn giản, có một vài vấn đề:

  • Đó là Bash cụ thể . Một giải pháp lý tưởng nên được di chuyển đến các vỏ khác.
  • thất bại nếu các quá trình khác sửa đổiPS1 . Một ví dụ là virtualenv, mà thêm (virtualenv)vào khởi đầu của PS1, sau đó luôn luôn biến mất ngay trên nếp gấp.
  • Ctrl- lbây giờ xóa trang cuối cùng của lịch sử.

Có cách nào để tránh những vấn đề này, không cần phải sử dụng XTerm?


Bằng cách nào đó, chúng ta cần giới thiệu các ký tự trống trong bộ đệm thanh cuộn của Xterm.
SHW

3
Trên thực tế, lời nhắc có thể dễ dàng di chuyển trở lại đầu trang bất cứ lúc nào bằng cách thực hiện clearlệnh.
werediver

@SHW Tôi đã hy vọng có một thiết lập cho việc này hơn là hack. Hack đầu cuối có xu hướng giới thiệu các lỗi rất tinh tế trong kinh nghiệm của tôi.
l0b0

@werediver Nhưng tôi không bao giờ muốn nó đứng đầu.
l0b0

1
Vì chỉ shell mới biết khi nào nó đưa ra lời nhắc, nên bất kỳ giải pháp nào cũng phải nằm trong ngữ cảnh của shell. Ngay cả việc yêu cầu XTerm cũng không giúp được gì vì XTerm không biết liệu những gì nó được yêu cầu xuất ra có phải là một dấu nhắc hay không. Đối với thiết bị đầu cuối, dấu nhắc shell chỉ là một chuỗi ký tự khác, không khác với bất kỳ chuỗi ký tự nào khác mà nó có thể nhận được.
celtschk

Câu trả lời:


11

Nếu sử dụng bash, sau đây nên thực hiện các mẹo:

TOLASTLINE=$(tput cup "$LINES")
PS1="\[$TOLASTLINE\]$PS1"

Hoặc (kém hiệu quả hơn khi nó chạy một tputlệnh trước mỗi dấu nhắc, nhưng hoạt động sau khi cửa sổ đầu cuối đã được thay đổi kích thước):

PS1='\[$(tput cup "$LINES")\]'$PS1

Để ngăn tputviệc thay đổi mã thoát, bạn có thể lưu và đặt lại một cách rõ ràng:

PS1='\[$(retval=$?;tput cup "$LINES";exit $retval)\]'$PS1

Lưu ý rằng biến retvallà cục bộ; nó không ảnh hưởng đến bất kỳ retvalbiến nào mà bạn có thể đã định nghĩa trong shell.

Vì hầu hết các cupkhả năng của thiết bị đầu cuối là như nhau \e[y;xH, bạn cũng có thể mã hóa nó:

PS1='\[\e[$LINES;1H\]'$PS1

Nếu bạn muốn nó an toàn trước việc đặt lại PS1 sau này, bạn cũng có thể sử dụng PROMPT_COMMANDbiến. Nếu được đặt, nó được chạy dưới dạng lệnh trước khi dấu nhắc được xuất. Vì vậy, hiệu quả cũng có thể đạt được bằng cách

PROMPT_COMMAND='(retval=$?;tput cup "$LINES";exit $retval)'

Tất nhiên, trong khi đặt lại PS1sẽ không ảnh hưởng đến điều này, một số phần mềm khác cũng có thể thay đổi PROMPT_COMMAND.


Làm thế nào tputkhác với nhiều echolệnh? (Hỏi về sự tò mò)
SHW

@ l0b0, có lẽ không xứng đáng có câu trả lời riêng. Tôi hy vọng celtschk sẽ không phiền nếu tôi chỉnh sửa câu trả lời của anh ấy / cô ấy.
Stéphane Chazelas

'\[$(tput cup "$LINES")\]' hoạt động rất đẹp . Cảm ơn!
l0b0

Có một vấn đề với tput: Nó dường như để thiết lập lại $exit_code. Đã sửa bằng cách sử dụng \[\e[$LINES;1H\].
l0b0

1
@ l0b0: Bây giờ tôi đã thêm một phiên bản sử dụng tputmã bảo vệ đó.
celtschk

4

Để đơn giản hóa câu trả lời trước, tôi thấy việc chạy dễ dàng hơn:

tput cup $LINES

vào đầu .bashrchoặc .zshrc. Nó chỉ làm công việc.

Ưu điểm:

  • nó chỉ in một lần, khi bạn khởi động vỏ

Nhược điểm:

  • khi xóa màn hình bằng ^ L, nó không in và khử răng cưa clearđể clear; tput ...không giúp đỡ;
  • nhắc nhở di chuyển nơi khác khi thiết bị đầu cuối được thay đổi kích thước

2

Các câu trả lời sử dụng $LINESlà không cần thiết di động. Như đã hoàn tất resize, bạn chỉ cần yêu cầu xtermđặt vị trí thành một số dòng lớn tùy ý, ví dụ:

tput cup 9999 0

(giả sử rằng bạn có một cửa sổ nhỏ hơn 10 nghìn dòng, bỏ qua cuộn ngược lại ).

Vì chuỗi sẽ không thay đổi dưới dạng hiệu ứng phụ của việc thay đổi kích thước cửa sổ, bạn có thể tính toán chuỗi này một lần và dán chuỗi vào chuỗi nhắc của bạn dưới dạng hằng số, ví dụ:

TPUT_END=$(tput cup 9999 0)

và sau đó

PS1="${TPUT_END} myprompt: "

theo sở thích của bạn.

Đối với các quy trình khác sửa đổi PS1: bạn sẽ phải tính toán lại PS1sau những thay đổi đó, để đảm bảo rằng nó trông như bạn muốn. Nhưng không đủ chi tiết trong câu hỏi để chỉ ra nơi cần thực hiện các thay đổi.

Và cuối cùng: hành vi hoàn thành tab không phù hợp với loại thay đổi này, do các giả định của bash.


Bạn có ý nghĩa gì bởi "hành vi hoàn thành tab không phù hợp với loại thay đổi này"?
l0b0

Tôi nghĩ bạn có nghĩa là PS1="${TPUT_END} myprompt: ", hoặc thậm chíPS1="${TPUT_END}${PS1}"
l0b0

Đối với cái sau - đúng (lỗi đánh máy từ suy nghĩ của makefiles). Trước đây, tôi nhớ rằng việc chỉnh sửa lệnh của bash phụ thuộc vào việc có thể in lại dòng (có dấu nhắc) và bạn có thể có một số hành vi kỳ lạ khi kết hợp với cuộn do hoàn thành lệnh.
Thomas Dickey
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.