Monit terminala nie jest poprawnie zawijany

171

Mam problem polegający na tym, że jeśli wpisuję bardzo długie polecenia w bash, terminal nie wyświetla poprawnie tego, co wpisuję. Spodziewałbym się tego, gdybym miał takie polecenie:

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

Polecenie powinno być renderowane w dwóch wierszach. Zamiast tego często się zawija i zaczyna pisać na górze mojego monitu, trochę tak:

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

Jeśli zdecyduję się wrócić i zmienić jakiś argument, nie będzie wiadomo, gdzie pojawi się kursor, czasem w środku monitu, ale zwykle w wierszu powyżej, w którym piszę.

Dodatkowa zabawa dzieje się, gdy wykonuję Uppoprzednie polecenie. Próbowałem tego w gnome-terminalu i terminatorze oraz na i3 i Cinnamon. Ktoś zasugerował, że to moja zachęta, więc oto:

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

Ctrll, reseti clearwszyscy robią to, co mówią, ale kiedy ponownie wpisuję polecenie lub Updzieje się to samo.

Sprawdziłem i checkwinsizejest włączony w bash. Dzieje się tak w przypadku okien o rozmiarze 80x24 i innych.

Czy to jest coś, z czym uczę się żyć? Czy jest jakaś magia, którą powinienem znać? Postanowiłem skorzystać z bardzo krótkiego monitu, ale to nie rozwiązuje problemu.

Muricula
źródło
1
Tak więc użycie polecenia env -i bash --norcnaprawia to. $ COLUMNS i $ LINES pasują do siebie. Czy to oznacza, że ​​w moim .bashrc jest coś śmiesznego?
Muricula,
Więc skomentowałem mój .bashrc i zakończyłem izolowanie mojego monitu jako części problematycznej, w szczególności składni kolorowania. Co jest nie tak z PS1 powyżej?
Muricula,
1
\[\033[01;32m\]\u: \[\033[01;34m\]\W \[\033[01;34m\] \$ \[\033[0m\]wydaje się unikać dziwności w zachowaniu - ale nie wiem, czy całkowicie szanuje twoje pierwotne
1
Zgodnie z odpowiedzią natput smam
błąd serwera

Odpowiedzi:

189

Sekwencje niedrukowalne powinny być ujęte w \[i\] . Patrząc na twój PS1 , ma on potem niezamkniętą sekwencję \W. Ale drugi wpis jest zbędny, a także powtarza poprzednie zdanie „1; 34” .

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

Jako taki powinien mieć zamierzony kolor:

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

Zachowanie „oryginału” powinno również działać:

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

Edytować:

Przyczyną takiego zachowania jest bashprzekonanie, że podpowiedź jest dłuższa niż w rzeczywistości. Jako prosty przykład, jeśli użyjesz:

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

Podpowiada się, że ma 8 znaków, a nie 1. W związku z tym, jeśli okno terminala ma 20 kolumn, po wpisaniu 12 znaków uważa się, że ma 20 znaków i jest zawijanych. Jest to również widoczne, jeśli następnie spróbujesz zrobić backspace lub Ctrl+u. Zatrzymuje się w kolumnie 9.

Jednak nie rozpoczyna także nowego wiersza, chyba że jeden znajduje się w ostatniej kolumnie, w wyniku czego pierwszy wiersz zostaje nadpisany.

Jeśli ktoś nadal pisze, wiersz powinien zawijać się do następnego wiersza po 32 znakach.

Runium
źródło
Jeśli masz - lub kogokolwiek - wyjaśnienie, co dokładnie w oryginalnej sekwencji spowodowało, że linia powtórzyła się sama, chciałbym to wiedzieć. Również +1 za sposób, w jaki pokazałeś to wizualnie.
1
@ illuminÉ: Nie patrzyłem na źródło, ale dodałem aktualizację z uwagą na temat zachowania z obserwacji.
Runium,
Na wypadek, gdybyś napotkał
divinedragon
To niesamowite, dziękuję @Runium - czy mógłbyś podzielić się tym, skąd to wiesz? Chciałbym znaleźć trochę dokumentacji na ten temat.
nycynik
2
@nycynik: Obserwacja.
Wydaje
83

Ma to głównie związek z tym, że rozmiar okna przyjęty przez terminal nie jest taki sam, jak rzeczywisty rozmiar okna. Jeśli używasz bash, możesz spróbować tego.

$ shopt checkwinsize

Jeśli nie dostaniesz

checkwinsize    on

Następnie aktywuj go za pomocą

$ shopt -s checkwinsize

Następnie po prostu spróbuj uruchomić inne polecenie (jak ls) lub zmienić rozmiar okna raz, powyższe działa dla mnie za każdym razem.

Szczególnie w przypadku systemów Redhat problem jest często spowodowany błędną konfiguracją, ~/.bashrcaby nie dzwonić /etc/bashrc. Zwykle ładowanie bash, ~/.bashrcktóre ma wywołać /etc/bashrc, które domyślnie zawiera shopt -s checkwinsize.

saketrp
źródło
Miał ten sam problem z OS X, najwyraźniej jeśli wywołasz „login”, aby uruchomić swój terminal, uruchamia bash w sposób, który czyta / etc / bashrc, ale jeśli po prostu wywołujesz bezpośrednio bash, ~ / .bashrc nie źródłowe rzeczy domyślnie, aby uzyskać dziwny efekt zawijania. Dzięki!
rogerdpack,
To również działało dla mnie. Kolory nie były włączone na tym konkretnym serwerze, dzwoniąc poprawnie /etc/bashrc, wszystko inne było dobre do zrobienia ... okazuje się, że jest to przyczyną problemów z opakowaniem.
dhaupin,
Zobacz także unix.stackexchange.com/a/61608/2221
astrojuanlu
Wygląda na dobre rozwiązanie. Ale to nie działa w mojej sesji ssh. Nie pewny dlaczego. Uruchomiłem polecenie shopt -s checkwinsizew sesji ssh. Ale opakowanie nadal trwa.
Qiang Xu,
To był właśnie mój problem - użytkownik .bashrc nie dzwonił do / etc / bashrc, a więc robił bałagan.
Sobrique
9

Jak wspomniano w innych odpowiedziach, sekwencje niedrukowalne, takie jak \e[0;30mpowinny być owinięte \[...\].

Dodatkowo (i o czym jeszcze nie wspomniałem) wydaje się, że \r\npowinno być poza tym, \[...\]jeśli masz wieloliniowy monit. Zajęło mi trochę prób i błędów, aby w końcu to zrozumieć.

Geraden
źródło
8

Kiedyś czytałem gdzieś (nie wiem już gdzie), że używając \001i \002zamiast \[i \]mogę rozwiązać ten problem. To mi zrobiło.

Nawiasem mówiąc, definiowanie PS1 nie musi wyglądać brzydko.

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
Blauhirn
źródło
2
Mój PS1 wywołuje polecenie, że sekwencje specjalne printf powodują problem z OP. Tylko to rozwiązanie rozwiązuje problem dla mnie.
RickMeasham
6

To brzmi jak problem z twoimi ustawieniami COLUMNSi LINESzmiennymi środowiskowymi. Kiedy zmieniasz rozmiar okna, zazwyczaj są one ustawiane automatycznie przez terminal gnome (uważam), możesz zmusić je do ręcznego ustawienia, wydając polecenie resize.

Przykład

Jeśli zmienię rozmiar mojego terminalu gnome na 79x17, moje zmienne pojawią się w następujący sposób:

$ echo $COLUMNS; echo $LINES
79
17

Mogę to tak wymusić:

$ resize
COLUMNS=79;
LINES=17;
export COLUMNS LINES;
slm
źródło
1
Ciekawe, ale nie pomaga.
Muricula,
1
To rozwiązało mój problem polegający na tym, że po uruchomieniu polecenia „screen” nie było poprawnie zawijane wiersze. Dzięki!!
nukeguy
5

Aby zapobiec zawijaniu, możesz również zwiększyć liczbę kolumn, używając np

stty columns 120
izmael
źródło
1
niezbyt dobry pomysł, brutalnie pomieszał vima
Blauhirn,
3

Ten sam problem może być również spowodowany użyciem szerokich symboli Unicode (np. Https://stackoverflow.com/a/34812608/1657819 ). Oto fragment kodu, który powoduje problem (zwróć uwagę na ciągi kolorów $Greeni $Redsą one odpowiednio usuwane):

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 nie może poprawnie obliczyć długości, więc najprostszym sposobem może być ucieczka 2 z trzech części tych szerokich symboli.

FancyX='\[\342\234\]\227'
Checkmark='\[\342\234\]\223'
Ojciec chrzestny
źródło
Ma sens. Myślę, że bash liczy znaki. Ponieważ X zajmuje jeden znak, ale jest zapisany jako 3, należy dołączyć 2 z nich, aby naprawić liczenie. Odpowiedź @blauhirn wyjaśnia również, jak zrobić w funkcji za pomocą \001i \002.
akostadinov
Do Twojej wiadomości, jak
wymyślisz