2012-01-10 8 views
6

Sto lavorando con la colorizzazione di alcuni output usando readline in Ruby, ma non ho alcuna fortuna che il ritorno a capo funzioni correttamente. Per esempio:L'output colorizzato interrompe l'incartonamento con readline

"\e[01;32mThis prompt is green and bold\e[00m > " 

Il risultato desiderato sarebbe:

This prompt is green and bold > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 

Quello che in realtà ottengo è:

aaaaaaaaaaa is green and bold > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 

Se rimuovo i codici colore, linea di confezionamento funziona correttamente. So che con bash, questo può accadere se i codici colore sono terminati in modo errato, ma ho provato tutto quello che riesco a pensare, tra cui alcune gemme diverse, e il comportamento è lo stesso. Si verifica anche su più sistemi con diverse versioni di Readline. Questo particolare progetto utilizza rb-readline anziché C readline.

+1

Hai provato a utilizzare https://rubygems.org/gems/colored per colorare l'output? – Maher4Ever

+0

Sì, ho provato anche quello e colorizzo. L'output funziona bene, ma quando lo si utilizza con un prompt di readline, interrompe il ritorno a capo. – Eugene

risposta

5

Io lancio sempre questa estensione di stringa quando ho bisogno di colorare le stringhe per console. Il problema nel tuo codice sembra essere il terminatore, dovrebbe esserci solo uno zero "\ e [0m".

# encoding: utf-8 
class String 
    def console_red;   colorize(self, "\e[1m\e[31m"); end 
    def console_dark_red;  colorize(self, "\e[31m");  end 
    def console_green;  colorize(self, "\e[1m\e[32m"); end 
    def console_dark_green; colorize(self, "\e[32m");  end 
    def console_yellow;  colorize(self, "\e[1m\e[33m"); end 
    def console_dark_yellow; colorize(self, "\e[33m");  end 
    def console_blue;   colorize(self, "\e[1m\e[34m"); end 
    def console_dark_blue; colorize(self, "\e[34m");  end 
    def console_purple;  colorize(self, "\e[1m\e[35m"); end 

    def console_def;   colorize(self, "\e[1m"); end 
    def console_bold;   colorize(self, "\e[1m"); end 
    def console_blink;  colorize(self, "\e[5m"); end 

    def colorize(text, color_code) "#{color_code}#{text}\e[0m" end 
end 

puts "foo\nbar".console_dark_red 
+0

Grazie. 2 0 o 1, non importa, fa la stessa cosa. Questo mi sembra un bug in readline. – Eugene

+0

Hm, hai "\ e [01; 32m" all'inizio ho "\ e [1m \ e [32m". – sunkencity

+0

Controlla questo: http://hintsforums.macworld.com/showthread.php?t=17068 a quanto pare puoi aggiungere altri escape per far sì che la shell ignori i codici colore quando calcola la lunghezza della linea. – sunkencity

3

Questo problema non è specifico del ruby, ma si verifica anche in bash. Se inserisci una shell bash

PS1="\e[01;32mThis prompt is green and bold\e[00m > " 

vedrai lo stesso risultato di sopra. Ma se inserisci

PS1="\[\e[01;32m\]This prompt is green and bold\[\e[00m\] > " 

otterrai il risultato desiderato.

+0

BTW, se sei curioso di sapere come funziona: sembra che [[blah \\] dica bash/readline/qualunque cosa, per stimare il numero di caratteri nella riga, dovresti ignorare qualsiasi cosa tra \\[ e \\]. Per un determinato terminale, il numero di caratteri in una riga viene calcolato/calcolato/inserito, e si spinge verso il basso fino alla riga successiva una volta che tutti i caratteri non ignorati sono stati compilati. – user208769

+0

Concordo sul fatto che questa dovrebbe essere la soluzione, ma quando lo faccio, il mio output si trasforma in: "[] Questo prompt è verde e grassetto []>" e il ritorno a capo è ancora un problema. Questo può essere dimostrato con il semplice script di test qui: https: //gist.github.it/1622119 – Eugene

+4

"Le specifiche di bash \ [e \] sono infatti tradotte in \ 001 e \ 002 ..." - [risposta da SuperUser] (http://superuser.com/questions/301353/escape- non-printing-caratteri-in-a-funzione-per-un-bash-pronta). –

18

Ok, sunkencity ottiene il segno di spunta, perché ho finito per usare la maggior parte della sua soluzione, ma ho dovuto modificarlo come segue:

# encoding: utf-8 
class String 
    def console_red;   colorize(self, "\001\e[1m\e[31m\002"); end 
    def console_dark_red;  colorize(self, "\001\e[31m\002");  end 
    def console_green;  colorize(self, "\001\e[1m\e[32m\002"); end 
    def console_dark_green; colorize(self, "\001\e[32m\002");  end 
    def console_yellow;  colorize(self, "\001\e[1m\e[33m\002"); end 
    def console_dark_yellow; colorize(self, "\001\e[33m\002");  end 
    def console_blue;   colorize(self, "\001\e[1m\e[34m\002"); end 
    def console_dark_blue; colorize(self, "\001\e[34m\002");  end 
    def console_purple;  colorize(self, "\001\e[1m\e[35m\002"); end 

    def console_def;   colorize(self, "\001\e[1m\002"); end 
    def console_bold;   colorize(self, "\001\e[1m\002"); end 
    def console_blink;  colorize(self, "\001\e[5m\002"); end 

    def colorize(text, color_code) "#{color_code}#{text}\001\e[0m\002" end 
end 

Ogni sequenza ha bisogno di essere avvolto in \ 001 .. \ 002 in modo che Readline sappia ignorare i caratteri non stampabili.

+0

Eccellente, grazie! Risolto problema con Pry prompt via https://github.com/pry/pry/issues/493#issuecomment-8799007 –

Problemi correlati