Colorized output breaks linewrapping with readline
I always throw this string extension in when I need to colorize strings for console. The problem in your code seems to be the terminator, there should be just one 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
Colorized readline prompt breaks control-a
Mac OS X uses the NetBSD editline
library, which includes a partial compatibility implementation of readline
.
It appears that an attempt was made to add readline's feature of allowing the user to bracket terminal control sequences in the prompt using the characters RL_PROMPT_START_IGNORE
and RL_PROMPT_END_IGNORE
(defined as '\1'
and '\2'
respectively in readline.h
). Unfortunately, due to a small typo, the feature is never enabled in rl_initialize
.
As I read the code (I haven't tested this), the fix would be to change line 327 of readline.c
[see note 1] from:
el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE);
to:
el_set(e, EL_PROMPT_ESC, _get_prompt, RL_PROMPT_START_IGNORE);
That would require you to find the source code for libedit
, make that trivial change, reconfigure and recompile it, and then install it. I don't have a Mac so I can't guide you through that process. (See Note 1 for links to source repositories which might be useful.)
Another solution would be to use the GNU readline library in your project. It's apparently available in MacPorts, so if you use that, it should be easy enough to install.
Notes:
- I got that line number from this OS X source repository. In the head revision of the NetBSD distribution, it's at line 337. But it should be easy enough to find by searching for
EL_PROMPT
. Just make sure that the symbolEL_PROMPT_ESC
is defined inhistedit.h
; if it isn't, the version of the editline library you've found is probably too old.
Bash PS1 prompt breaks line wrapping when generating ANSI escapes by an external program
Note first that \[
and \]
are interpreted by Bash itself, not the console, so they must be explicitly present in the PS1
value, not in the output of the program generating actual prompt.
Now, you want the non-escape chars to count, while colors are not to be counted. For this, you can modify your program to have two modes:
- Colored output (for actual prompt)
- Text-only output (for character counting)
Then you can use something like
PS1='$(/tmp/test)\[\r$(/tmp/test c)\]'
which would work for code modified to the following:
void PrintPrompt(string cwd, string hostname, string username, bool colors){
string cwdString = cwd;
cout << (colors ? WHITEDGRAY : "") << username <<
(colors ? DGRAYORANGE : "") << ARROW << " " <<
(colors ? WHITEORANGE : "") << hostname <<
(colors ? ORANGEDGRAY : "") << ARROW << " " <<
(colors ? WHITEDGRAY : "") << cwd << (colors ? DGRAYDEFAULT : "") <<
ARROW << (colors ? RESET : "") << endl;
}
with colors
being passed as e.g. argc>1
.
We use the \r
escape sequence to go to the beginning of the line, enabling us to overwrite our already printed non-colored text with the fancy-colored one, making Bash think that the additional text and escape sequences (including the carriage return) don't take any space.
Screenshot:
Related Topics
Sort a List of Objects by Using Their Attributes in Ruby
Need Help Maximizing 3 Factors in Multiple, Similar Objects and Ordering Appropriately
Configuration in Allure to Cucumber in Ruby
Custom Filtering of Parameters in Rails 3 Using Config.Filter_Parameters
Ruby Tcpsocket: Find Out How Much Data Is Available
Is This the Best Way to Grab Common Elements from a Hash of Arrays
Could Not Find Rake-10.1.0 in Any of the Sources
Detecting Overlapping Ranges in Ruby
Alphabetize Arabic and Japanese Text That Is in Unicode
Yielding in an Anonymous Block
Trying to Set Up Amazon's S3 Bucket: 403 Forbidden Error & Setting Permissions
Clicking Link with JavaScript in Mechanize
How to Share State Between Scenarios Using Cucumber
How to Split a String into Consecutive Substrings of Length at Most 3 in All Possible Ways
Trying to Compare Two Text Files, and Create a Third Based on Information
Grabbing Snapshots from Webcams in Ruby