Terminal prompt tidak membungkus dengan benar

172

Saya memiliki masalah di mana jika saya mengetikkan perintah yang sangat panjang di bash terminal tidak akan membuat apa yang saya ketikkan dengan benar. Saya berharap jika saya memiliki perintah seperti berikut:

username@someserver ~/somepath $ ssh -i /path/to/private/key
myusername@something.someserver.com

Perintah harus ditampilkan pada dua baris. Sebaliknya ia akan sering membungkus dan mulai menulis di atas prompt saya, agak seperti ini:

myreallylongusername@something.somelongserver.comh -i /path/to/private/key

Jika saya memutuskan untuk kembali dan mengubah beberapa argumen, tidak ada yang tahu di mana kursor akan muncul, kadang-kadang di tengah prompt, tetapi biasanya pada baris di atas di mana saya mengetik.

Kegembiraan tambahan terjadi ketika ketika saya Upke perintah sebelumnya. Saya sudah mencoba ini di gnome-terminal dan terminator dan di i3 dan Cinnamon. Seseorang menyarankan itu prompt saya, jadi di sini adalah:

\[\033[01;32m\]\u:\[\033[01;34m\] \W\033[01;34m \$\[\033[00m\]

Ctrll,, resetdan clearsemua melakukan apa yang mereka katakan, tetapi ketika saya mengetik perintah kembali atau Uphal yang sama terjadi.

Saya memeriksa dan checkwinsizediaktifkan di bash. Ini terjadi pada 80x24 dan ukuran jendela lainnya.

Apakah ini hanya sesuatu yang saya pelajari untuk hidup? Apakah ada sihir yang harus saya ketahui? Saya sudah puas hanya menggunakan prompt yang sangat singkat, tetapi itu tidak memperbaiki masalah.

Muricula
sumber
1
Jadi, gunakan perintah untuk env -i bash --norcmemperbaikinya. Pertandingan $ COLUMNS dan $ LINES. Apakah itu berarti ada sesuatu yang lucu dengan .bashrc saya?
Muricula
Jadi saya berkomentar .bashrc saya dan akhirnya mengisolasi prompt saya sebagai bagian yang bermasalah, khususnya sintaksis warna yang terlibat. Apa yang salah dengan PS1 di atas?
Muricula
1
\[\033[01;32m\]\u: \[\033[01;34m\]\W \[\033[01;34m\] \$ \[\033[0m\]tampaknya menghindari keanehan dalam perilaku - tetapi tidak tahu apakah itu benar-benar menghargai prompt asli Anda ...
1
Sesuai jawaban ini di serverfault , gunakantput smam
Samveen

Jawaban:

189

Urutan yang tidak dapat dicetak harus disertakan dalam \[dan\] . Melihat PS1 Anda memiliki urutan yang tidak tertutup setelah \W. Tapi, entri kedua berlebihan dan mengulangi pernyataan sebelumnya "1; 34" .

\[\033[01;32m\]\u:\[\033[01;34m\] \W\033[01;34m \$\[\033[00m\]
                  |_____________|               |_|
                         |                       |
                         +--- Let this apply to this as well.

Dengan demikian ini seharusnya dimaksudkan pewarnaan:

\[\033[1;32m\]\u:\[\033[1;34m\] \W \$\[\033[0m\]
                               |_____|
                                  |
                                  +---- Bold blue.

Menjaga "asli" ini juga berfungsi:

\[\033[1;32m\]\u:\[\033[1;34m\] \W\[\033[1;34m\] \$\[\033[0m\]
                                  |_|         |_|
                                   |           |
                                   +-----------+-- Enclose in \[ \]

Sunting:

Alasan perilakunya adalah karena bashmeyakini bahwa dorongan itu lebih lama dari yang sebenarnya. Sebagai contoh sederhana, jika digunakan:

PS1="\033[0;34m$"
       1 2345678

Prompt diyakini 8 karakter dan bukan 1. Karena itu jika jendela terminal adalah 20 kolom, setelah mengetik 12 karakter, itu diyakini 20 karakter dan membungkus sekitar. Ini juga terbukti jika seseorang kemudian mencoba melakukan backspace atau Ctrl+u. Itu berhenti di kolom 9.

Namun itu juga tidak memulai baris baru kecuali ada di kolom terakhir, akibatnya baris pertama ditimpa.

Jika seseorang terus mengetik baris harus membungkus ke baris berikutnya setelah 32 karakter.

Runium
sumber
Jika Anda memiliki - atau siapa pun - memiliki penjelasan tentang apa sebenarnya dalam urutan asli menyebabkan garis terulang kembali, saya akan tertarik mengetahui hal itu. Juga memberi +1 untuk cara Anda menunjukkan ini secara visual.
1
@ illuminÉ: Belum melihat sumbernya, tetapi menambahkan pembaruan dengan catatan tentang perilaku dari pengamatan.
Runium
Jika Anda menghadapi masalah, Anda dapat menggunakan situs web ini untuk membuat yang baru - bashrcgenerator.com
divinedragon
Ini luar biasa, terima kasih @unium - maukah Anda berbagi bagaimana Anda tahu ini? Saya ingin mencari dokumentasi tentang hal ini.
nycynik
2
@nycynik: Pengamatan. Saya kira yang paling dekat dengan dokumentasi tentang ini adalah kode sumber ...
Runium
84

Hal ini sebagian besar berkaitan dengan ukuran jendela yang diasumsikan oleh terminal tidak sama dengan ukuran jendela Anda yang sebenarnya. Jika Anda menggunakan bash, Anda dapat mencoba ini.

$ shopt checkwinsize

Jika Anda tidak mengerti

checkwinsize    on

Kemudian aktifkan dengan

$ shopt -s checkwinsize

Kemudian coba jalankan perintah lain (seperti ls) atau mengubah ukuran jendela sekali, di atas berfungsi untuk saya setiap waktu.

Untuk sistem Redhat khususnya, masalah ini sering disebabkan oleh konfigurasi yang salah ~/.bashrcuntuk tidak menelepon /etc/bashrc. Biasanya, bash memuat ~/.bashrcyang diharapkan untuk dipanggil /etc/bashrc, yang secara default berisi shopt -s checkwinsize.

saketrp
sumber
Memiliki masalah yang sama dengan OS X, tampaknya jika Anda memanggil "login" untuk memulai terminal Anda, ia mulai bash dengan cara yang bertuliskan / etc / bashrc, tetapi jika Anda hanya memanggil langsung ke bash, ~ / .bashrc tidak sumber hal-hal secara default sehingga Anda mendapatkan efek pembungkus aneh. Terima kasih!
rogerdpack
Ini juga bekerja untuk saya. Warna tidak menyala di server khusus ini, memanggil dengan benar /etc/bashrc, segalanya baik untuk pergi ... ternyata ini adalah penyebab masalah pembungkus.
dhaupin
Lihat juga unix.stackexchange.com/a/61608/2221
astrojuanlu
1
Sepertinya solusi yang bagus. Tapi itu tidak berhasil di sesi ssh saya. Tidak yakin kenapa. Saya telah menjalankan perintah shopt -s checkwinsizedi sesi ssh. Tapi bungkusnya tetap ada.
Qiang Xu
Ini justru masalah saya - pengguna .bashrc tidak memanggil / etc / bashrc, dan membuat berantakan.
Sobrique
9

Seperti disebutkan dalam jawaban lain, urutan yang tidak dapat dicetak seperti \e[0;30mharus dibungkus \[...\].

Selain itu (dan apa yang saya tidak melihat disebutkan belum) adalah tampaknya \r\nharus luar dari \[...\]jika Anda memiliki prompt multi-line. Butuh beberapa percobaan dan kesalahan untuk akhirnya mengetahui hal itu.

Geraden
sumber
8

Saya pernah membaca di suatu tempat (tidak tahu lagi di mana) yang menggunakan \001dan \002bukannya \[dan \]dapat memecahkan masalah ini. Itu untuk saya.

Omong-omong, mendefinisikan PS1 tidak harus terlihat jelek.

green="\001$(tput setaf 2)\002"
blue="\001$(tput setaf 4)\002"
dim="\001$(tput dim)\002"
reset="\001$(tput sgr0)\002"

PS1="$dim[\t] " # [hh:mm:ss]
PS1+="$green\u@\h" # user@host
PS1+="$blue\w\$$reset " # workingdir$

export PS1
unset green blue dim reset
phil294
sumber
2
PS1 saya memanggil perintah printf escape sequence yang menyebabkan masalah OP. Hanya solusi ini yang memperbaiki masalah bagi saya.
RickMeasham
7

Ini terdengar seperti masalah dengan pengaturan variabel COLUMNS& LINESlingkungan Anda. Ketika Anda mengubah ukuran jendela, mereka biasanya diatur secara otomatis oleh gnome-terminal (saya percaya) Anda bisa memaksa mereka untuk secara manual diatur dengan mengeluarkan perintah resize.

Contoh

Jika saya mengubah ukuran terminal gnome saya menjadi 79x17, variabel saya muncul seperti ini:

$ echo $COLUMNS; echo $LINES
79
17

Saya bisa memaksanya seperti ini:

$ resize
COLUMNS=79;
LINES=17;
export COLUMNS LINES;
slm
sumber
1
Menarik, tetapi tidak membantu.
Muricula
1
Ini memperbaiki masalah saya itu tidak membungkus baris dengan benar setelah saya menjalankan perintah "layar". Terima kasih!!
nukeguy
5

Untuk mencegah pembungkus, Anda juga dapat menambah jumlah kolom menggunakan, mis

stty columns 120
Ismail
sumber
1
bukan ide yang sangat baik, itu mengacaukan vim secara brutal
phil294
3

Juga masalah yang sama dapat disebabkan dengan menggunakan simbol unicode lebar (seperti dari https://stackoverflow.com/a/34812608/1657819 ). Berikut ini cuplikan yang menyebabkan masalah (perhatikan $Greendan $Redstring warna yang lolos dengan benar):

FancyX='\342\234\227'
Checkmark='\342\234\223'


# Add a bright white exit status for the last command
PS1="$White\$? "
# If it was successful, print a green check mark. Otherwise, print
# a red X.
if [[ $Last_Command == 0 ]]; then
    PS1+="$Green$Checkmark "
else
    PS1+="$Red$FancyX "
fi

Bash tidak dapat menghitung panjangnya dengan benar, jadi cara termudah adalah melarikan diri 2 dari tiga bagian dari simbol lebar itu.

FancyX='\[\342\234\]\227'
Checkmark='\[\342\234\]\223'
Bapak baptis
sumber
Masuk akal. Yang saya duga adalah bahwa bash menghitung karakter. Karena X mengambil satu karakter tetapi ditulis sebagai 3, maka seseorang harus menyertakan 2 untuk memperbaiki penghitungan. @blauhirn jawaban juga menjelaskan bagaimana melakukan fungsi dengan \001dan \002.
akostadinov
FYI, ini adalah bagaimana Anda mencari cara untuk menghasilkan karakter unicode multi-byte dalam format ini: stackoverflow.com/a/602924/520567
akostadinov