2012-01-10 1 views
6

Я работаю с раскрашиванием некоторого вывода с использованием readline в Ruby, но мне не повезло, что обработка строк корректно работает. Например:Раскрашенный вывод ломается с линкером с readline

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

Желаемый результат будет:

This prompt is green and bold > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 

То, что я на самом деле получаю:

aaaaaaaaaaa is green and bold > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 

Если удалить цветовые коды, перенос строк работает правильно. Я знаю, что с bash это может произойти, если цветовые коды некорректно прекращены, но я пробовал все, о чем я могу думать, включая несколько разных драгоценных камней, и поведение такое же. Это также происходит в нескольких системах с различными версиями Readline. Этот конкретный проект использует rb-readline, а не C readline.

+1

Вы пробовали использовать https://rubygems.org/gems/colored для цветного вывода? – Maher4Ever

+0

Да, я попробовал это, а также раскрасил. Выход работает отлично, но при использовании его с подсказкой readline он прерывает перенос строк. – Eugene

ответ

5

Я всегда бросаю это расширение строки, когда мне нужно раскрасить строки для консоли. Проблема в вашем коде, кажется, является терминатором, должен быть только один нуль «\ 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

Спасибо. 2 0s или 1, не имеет значения, он делает то же самое. Это похоже на ошибку в readline для меня. – Eugene

+0

Хм, у вас есть «\ e [01; 32m» в начале, я «\ e [1m \ e [32m». – sunkencity

+0

Оформить заказ: http://hintsforums.macworld.com/showthread.php?t=17068, по-видимому, вы можете добавить дополнительные экраны, чтобы заставить оболочку игнорировать цветовые коды при расчете длины строки. – sunkencity

3

Эта проблема не связана с рубином - она ​​встречается и в bash. Если вы положили в раковину bash

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

вы увидите тот же результат, что и выше. Но если вы положите

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

вы получите желаемый результат.

+0

Кстати, если вам интересно, как это работает: похоже, что \\ [blah \\] сообщает bash/readline/что бы это ни было, для оценки количества символов в строке вы должны игнорировать что-либо между \\[ а также \\]. Для данного терминала количество символов в строке угадывается/вычисляется/равномерно и только толкается до следующей строки после того, как все незанятые символы заполнены. – user208769

+0

Я согласен, что это должно быть исправление, но когда я это делаю, мой вывод превращается в это: «[] Это приглашение зеленое и полужирное []>», и перенос строк по-прежнему является проблемой. Это можно проверить с помощью простого тестового сценария: https: //gist.github.com/1622119 – Eugene

+4

«Баш-специфические \ [и \] на самом деле переведены в \ 001 и \ 002 ..." - [ответ от SuperUser] (http://superuser.com/questions/301353/escape- Непечатаемые символы--в-функции-на-а-Баш-приглашение). –

18

Ok, sunkencity получает отметку, потому что я в конечном итоге использовала большую часть своего решения, но мне пришлось изменить его следующим образом:

# 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 

Каждая последовательность должна быть обернута в \ 001 .. \ 002 так что Readline знает, чтобы игнорировать непечатаемые символы.

+0

Отлично, спасибо! Исправлена ​​проблема с вызовом Pry через https://github.com/pry/pry/issues/493#issuecomment-8799007 –