Bagaimana cara mendapatkan baris perintah panjang untuk membungkus ke baris berikutnya?

108

Sesuatu yang saya perhatikan di Ubuntu untuk waktu yang lama yang membuat saya frustasi adalah ketika saya mengetik perintah di baris perintah yang lebih panjang (lebih lebar) dari lebar terminal, alih-alih membungkus ke baris baru, itu kembali ke kolom 1 pada baris yang sama dan mulai menulis awal baris perintah saya. (Ini sebenarnya tidak menimpa perintah yang sebenarnya, tetapi secara visual, itu menimpa teks yang ditampilkan).

Sulit untuk dijelaskan tanpa melihatnya, tetapi katakanlah terminal saya memiliki lebar 20 karakter (Milik saya lebih seperti 120 karakter - tetapi sebagai contoh), dan saya ingin mengulangi alfabet bahasa Inggris. Apa yang saya ketik adalah ini:

echo abcdefghijklmnopqrstuvwxyz

Tapi seperti apa terminal saya sebelum saya menekan kunci adalah:

pqrstuvwxyzghijklmno

Ketika saya menekan enter, itu bergema

abcdefghijklmnopqrstuvwxyz

jadi saya tahu perintah itu diterima dengan baik. Itu hanya membungkus pengetikan saya setelah "o" dan mulai lagi pada baris yang sama.

Apa yang saya harapkan terjadi, jika saya mengetik perintah ini pada terminal yang lebarnya hanya 20 karakter adalah ini:

echo abcdefghijklmno
pqrstuvwxyz

Latar Belakang: Saya menggunakan bash sebagai shell saya, dan saya memiliki baris ini di ~ / .bashrc saya:

set -o vi

untuk dapat menavigasi baris perintah dengan perintah VI. Saat ini saya menggunakan server Ubuntu 10.10, dan menghubungkan ke server dengan Putty.

Di lingkungan lain yang pernah saya gunakan, jika saya mengetikkan baris perintah yang panjang, itu akan menambah baris baru di bawah baris yang saya kerjakan ketika perintah saya lebih panjang dari lebar terminal dan ketika saya terus mengetik saya bisa melihat perintah saya di 2 garis yang berbeda. Tapi selama saya bisa ingat menggunakan Ubuntu, perintah panjang saya hanya menempati 1 baris.

Ini juga terjadi ketika saya akan kembali ke perintah sebelumnya dalam sejarah (saya menekan Esc, lalu 'K' untuk kembali ke perintah sebelumnya) - ketika saya mendapatkan perintah sebelumnya yang lebih panjang dari lebar terminal, baris perintah mendapat hancur dan saya tidak tahu di mana saya berada di dalam perintah.

Satu-satunya cara yang saya temukan untuk melihat seluruh perintah panjang adalah dengan menekan "Esc-V", yang membuka perintah saat ini dalam editor VI.

Saya rasa saya tidak memiliki sesuatu yang aneh di file .bashrc saya. Saya berkomentar di baris "set -o vi", dan saya masih punya masalah.

Saya mengunduh salinan baru Putty dan tidak membuat perubahan apa pun pada konfigurasi - Saya hanya mengetikkan nama host saya untuk terhubung, dan saya masih memiliki masalah, jadi saya tidak berpikir itu apa-apa dengan Putty (kecuali saya perlu buat beberapa perubahan konfigurasi)

Adakah orang lain yang mengalami masalah ini, dan adakah yang bisa memikirkan cara memperbaikinya?

Sunting

Itu adalah file .bashrc saya. Saya telah menyalin profil yang sama dari mesin ke mesin, dan saya menggunakan karakter khusus di $ PS1 saya yang entah bagaimana membuangnya. Saya sekarang bertahan dengan variabel standar bash untuk $ PS1 saya.

Terima kasih kepada @ ændrük untuk tipnya di .bashrc!

... Akhiri Edit ...

BrianH
sumber
1
Untuk memastikan bahwa masalahnya bukan disebabkan oleh file .bashrc Anda, saya sarankan untuk sementara waktu menggantinya dengan salinan /etc/skel/.bashrc. Ingatlah bahwa Anda harus menyambung kembali agar perubahan diterapkan, dan pastikan untuk menyimpan cadangan .bashrc Anda sendiri.
ændrük
1
Aplikasi terminal apa yang Anda gunakan? Perilaku yang Anda gambarkan tidak biasa, tentu saja bukan default.
João Pinto
Dalam shell yang telah saya kerjakan (dan di Cisco CLI) Anda juga dapat mengetik Ctrl-L untuk menampilkan kembali baris yang Anda ketikkan, meskipun itu offscreen. Dalam situasi Anda, itu mungkin masih menghasilkan output rusak yang Anda bicarakan, tapi saya ingin tahu.
belacqua
3
Jangan ragu untuk membuat "jawaban" yang menjelaskan solusi dan tandai sebagai diterima. Ini mungkin tampak sedikit konyol, tetapi memiliki jawaban yang tepat membantu menjaga situs tetap terorganisir dan mungkin lebih efektif membimbing orang lain yang memiliki masalah serupa di masa depan.
ændrük
Sesuai jawaban ini di serverfault , gunakantput smam
Samveen

Jawaban:

136

Pastikan semua byte yang tidak dapat dicetak di PS1 Anda terkandung di dalamnya \[ \]. Jika tidak, bash akan menghitungnya dalam panjang prompt. Ini menggunakan panjang prompt untuk menentukan kapan harus membungkus garis.

Sebagai contoh, di sini bash menghitung prompt sebagai lebar 19 kolom, sedangkan prompt yang ditampilkan oleh terminal hanya 10 kolom lebar ( My promptditulis dalam cyan, dan >ditulis dalam warna default):

PS1='\e[36mMy prompt\e[0m>'         # bash count: 19, actual: 10

sementara di sini ia hanya menghitung prompt sebagai lebar 10 kolom karena mengabaikan byte antara spesial \[dan \]lolos:

PS1='\[\e[36m\]My prompt\[\e[0m\]>' # bash count: 10, actual: 10

Namun untuk praktik yang baik, gunakan tputuntuk membuat terminal keluar daripada mengkodekannya dengan keras:

cyan=$(tput setaf 6) # \e[36m
reset=$(tput sgr0)   # \e[0m
PS1='\[$cyan\]My prompt\[$reset\]>'

Lihat http://mywiki.wooledge.org/BashFAQ/053 , dan juga http://wiki.bash-hackers.org/scripting/terminalcodes untuk informasi lebih lanjut tput.

geirha
sumber
3
Itu penjelasan yang bagus tentang masalah yang tidak diberikan jawaban yang diterima
Jamie Cook
Di baris kode terakhir PS1='...': mengapa tanda kutip tunggal tidak mencegah $cyandan $resetdari penggantian?
andrybak
2
@andrybak, mereka mencegah $cyandan $resettidak digantikan, tetapi PS1dievaluasi setiap kali prompt dicetak. Anda dapat melihat ini dengan mencoba PS1='$var> 'dan kemudian memberikan varberbagai nilai dan melihat bagaimana perubahan cepat. Kemudian coba PS1="$var> " dan perhatikan bahwa prompt tetap statis; $vardiperluas selama penugasan, tidak setiap waktu PS1dievaluasi.
geirha
1
Ini luar biasa. Terima kasih banyak telah memposting ini! Itu membuat keluar kurung persegi lebih mudah dan lebih mudah dibaca.
phyatt
Bagaimana saya membuat ini bekerja PS1=${PS1}"\e]2;$@\a". Saya mencobaPS1=${PS1}"\[\e]2;\]$@\[\a\]"
Ramana Reddy
59

Saya kira Anda telah mengkonfigurasi PS1warna Anda, bukan?

Pastikan Anda memiliki \[di dalam PS1kutipan Anda sebelum set warna Anda

Sebagai contoh:

PS1='\[\e[0;32m\u@\w/:\[\e[m '
wjandrea
sumber
PS1 saya adalah export PS1='^[[96m'$(hostname)'<^[[92m${PWD}^[[96m>^[[97m '- Saya sudah menggunakan yang itu untuk waktu yang lama - ini kompatibel dengan KSH ...
BrianH
2
Wow. Saya telah menggunakan permintaan terminal sejak selamanya dan tidak pernah memiliki masalah ini sebelumnya. Tidak akan pernah tahu itu. Terima kasih.
bchurchill
3
menggunakan \ [sambil menggunakan kutipan sederhana menghasilkan garis miring yang tidak diinginkan. juga, harus ada digunakan] di akhir chars ajaib, seperti yang tercantum dalam jawaban pilihan terbaik
igorsantos07
2
-1 Tidak berfungsi. Anda harus membungkus bagian non-cetak dengan \[di awal dan \]di akhir.
wjandrea
@ igorsantos07 Double-backslash in \\[adalah kesalahan ketik yang disebabkan oleh sunting. Saya sudah memperbaikinya.
wjandrea
11

Saya memiliki masalah serupa, dan akhirnya menemukan solusi sederhana.

Tambahkan baris berikut di .bashrcfile Anda :

COLUMNS=250

Kemudian ketik source ~/.bashrcuntuk mendapatkan efek yang diinginkan.

Deboshree
sumber
Dalam beberapa kasus, seperti subdivisi terminator sempit, masalahnya bukan pada karakter warna promt tetapi hanya pada nilai COLUMNS yang salah. Jawaban ini membuat saya keluar dari lubang yang sangat mengganggu!
Carles Sala
1
Logout tidak perlu dilakukan. Lakukan source .bashrc. Permintaan Anda akan segera diperbarui
Sergiy Kolodyazhnyy
1
Saya menemukan bahwa karena saya tidak memiliki setwinsizeset shopt untuk bash saya, jadi itu tidak memperbarui COLUMNS benar, lihat unix.stackexchange.com/a/167911/8337
rogerdpack
1
Saya memang export COLUMNS=250diikuti oleh export TERM=xtermdan itu senang.
Philip Kearns
5

Saya memiliki masalah yang sama dengan prompt berwarna kustom, meskipun saya mengandung kode warna di dalam \[dan \]pembatas. Ternyata bash memiliki masalah untuk menggemakan warna dari dalam suatu fungsi . Saya akhirnya hanya menggunakan variabel untuk prompt saya, dan meskipun .bashrc saya sedikit kurang elegan, semuanya berfungsi dengan baik sekarang.

reentim
sumber
Jika ada yang masih membaca ini, sebenarnya dimungkinkan untuk lepas dari warna dalam suatu fungsi. Lihat jawaban ini pada pertanyaan terkait.
wjandrea
3

Hal sederhana yang harus dilakukan adalah menambahkan baris berikut sebelum mengatur PS1:

stty columns 1000

Sebagai contoh,

stty columns 1000
PS1='\[\e[0;32m\u@\w/:[\e[m '

Namun ini tidak mempengaruhi perintah unix lainnya seperti ls dan man.

Gennady
sumber
1
Itu bekerja di OSX.
raskhadafi
4
Ini juga mempengaruhi vim buruk. Tolong jangan gunakan ini.
justhalf
0

Saya punya masalah ini ketika terhubung di tmux. Masalahnya adalah bahwa saya memiliki ipythonsesi di latar belakang ( ctrl + z) dan yang entah bagaimana memecahkan pembungkus baris. Segera setelah saya menghentikannya ( fg, ctrl+d+d) terminal saya mulai berfungsi dengan baik

Jadi periksa untuk setiap prompt interaktif yang dihentikan.

Ciprian Tomoiagă
sumber
0

Jadi saya hanya memiliki masalah yang sama dengan sedikit twist di atasnya dan saya pikir saya akan membagikan solusi saya juga, hanya untuk menambahkan nuansa kecil saya: D

PS1 awal saya adalah

PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$"

Masalah yang saya miliki adalah bahwa saya mencoba untuk mengubah judul terminal saya serta command prompt. Cara saya melakukan ini adalah dengan menambahkan \[\033]0;\]Title\ake variabel PS1 .

Jadi sekarang PS1 saya adalah:

PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$\[\033]0;\]Title\a"

Ini mengacaukan garis pembungkus untuk saya. Saya akhirnya menemukan bahwa bash sepertinya tidak suka memiliki \adi akhir. Untuk menghindari ini, saya menempatkan judul dalam variabel, yang sepertinya memperbaikinya.

TITLE="\033]0;Title\a"
PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$\[$TITLE\]"
Ciarán J. Hagen
sumber
0

\[dan \]tidak bekerja untuk saya. Saya kira ada sesuatu yang berbeda tentang bagaimana saya menghasilkan prompt (dari program eksternal), atau karena prompt saya "dinamis".

Setelah membaca ini saya menemukan bahwa Anda benar-benar dapat melarikan diri dari kode warna dengan 0x01dan 0x02byte.

misalnya saya menggunakan versi khusus dari Chalk dan saya membungkus warna menggunakan ini:

const Chalk = require('@nasc/chalk');

const chalk = new Chalk.constructor({
  wrapper: {
    pre: '\1',
    post: '\2',
  }
});
Mpen
sumber