/* Given a string and list of colors of the same size, return the string with ANSI escape sequences representing the colors. */ static std::string ansi_colorize(const wcstring &text, const std::vector<highlight_spec_t> &colors) { assert(colors.size() == text.size()); assert(output_receiver.empty()); int (*saved)(char) = output_get_writer(); output_set_writer(write_to_output_receiver); highlight_spec_t last_color = highlight_spec_normal; for (size_t i=0; i < text.size(); i++) { highlight_spec_t color = colors.at(i); if (color != last_color) { set_color(highlight_get_color(color, false), rgb_color_t::normal()); last_color = color; } writech(text.at(i)); } output_set_writer(saved); std::string result; result.swap(output_receiver); return result; }
/** set_color builtin */ static int builtin_set_color(parser_t &parser, wchar_t **argv) { /** Variables used for parsing the argument list */ const struct woption long_options[] = { { L"background", required_argument, 0, 'b'}, { L"help", no_argument, 0, 'h' }, { L"bold", no_argument, 0, 'o' }, { L"underline", no_argument, 0, 'u' }, { L"version", no_argument, 0, 'v' }, { L"print-colors", no_argument, 0, 'c' }, { 0, 0, 0, 0 } }; const wchar_t *short_options = L"b:hvocu"; int argc = builtin_count_args(argv); /* Some code passes variables to set_color that don't exist, like $fish_user_whatever. As a hack, quietly return failure. */ if (argc <= 1) { return EXIT_FAILURE; } const wchar_t *bgcolor = NULL; bool bold = false, underline=false; int errret; /* Parse options to obtain the requested operation and the modifiers */ woptind = 0; while (1) { int c = wgetopt_long(argc, argv, short_options, long_options, 0); if (c == -1) { break; } switch (c) { case 0: break; case 'b': bgcolor = woptarg; break; case 'h': builtin_print_help(parser, argv[0], stdout_buffer); return STATUS_BUILTIN_OK; case 'o': bold = true; break; case 'u': underline = true; break; case 'c': print_colors(); return STATUS_BUILTIN_OK; case '?': return STATUS_BUILTIN_ERROR; } } /* Remaining argument is foreground color */ const wchar_t *fgcolor = NULL; if (woptind < argc) { if (woptind + 1 == argc) { fgcolor = argv[woptind]; } else { append_format(stderr_buffer, _(L"%ls: Too many arguments\n"), argv[0]); return STATUS_BUILTIN_ERROR; } } if (fgcolor == NULL && bgcolor == NULL && !bold && !underline) { append_format(stderr_buffer, _(L"%ls: Expected an argument\n"), argv[0]); return STATUS_BUILTIN_ERROR; } const rgb_color_t fg = rgb_color_t(fgcolor ? fgcolor : L""); if (fgcolor && (fg.is_none() || fg.is_ignore())) { append_format(stderr_buffer, _(L"%ls: Unknown color '%ls'\n"), argv[0], fgcolor); return STATUS_BUILTIN_ERROR; } const rgb_color_t bg = rgb_color_t(bgcolor ? bgcolor : L""); if (bgcolor && (bg.is_none() || bg.is_ignore())) { append_format(stderr_buffer, _(L"%ls: Unknown color '%ls'\n"), argv[0], bgcolor); return STATUS_BUILTIN_ERROR; } /* Make sure that the term exists */ if (cur_term == NULL && setupterm(0, STDOUT_FILENO, &errret) == ERR) { append_format(stderr_buffer, _(L"%ls: Could not set up terminal\n"), argv[0]); return STATUS_BUILTIN_ERROR; } /* Test if we have at least basic support for setting fonts, colors and related bits - otherwise just give up... */ if (! exit_attribute_mode) { return STATUS_BUILTIN_ERROR; } /* Save old output function so we can restore it */ int (* const saved_writer_func)(char) = output_get_writer(); /* Set our output function, which writes to a std::string */ builtin_set_color_output.clear(); output_set_writer(set_color_builtin_outputter); if (bold) { if (enter_bold_mode) writembs(tparm(enter_bold_mode)); } if (underline) { if (enter_underline_mode) writembs(enter_underline_mode); } if (bgcolor != NULL) { if (bg.is_normal()) { write_color(rgb_color_t::black(), false /* not is_fg */); writembs(tparm(exit_attribute_mode)); } } if (fgcolor != NULL) { if (fg.is_normal() || fg.is_reset()) { write_color(rgb_color_t::black(), true /* is_fg */); writembs(tparm(exit_attribute_mode)); } else { write_color(fg, true /* is_fg */); } } if (bgcolor != NULL) { if (! bg.is_normal() && ! bg.is_reset()) { write_color(bg, false /* not is_fg */); } } /* Restore saved writer function */ output_set_writer(saved_writer_func); /* Output the collected string */ stdout_buffer.append(str2wcstring(builtin_set_color_output)); builtin_set_color_output.clear(); return STATUS_BUILTIN_OK; }
/** Initialize various subsystems. This also closes stdin and replaces it with a copy of stderr, so the reading of completion strings must be done before init is called. */ static void init( int mangle_descriptors, int out ) { struct sigaction act; static struct termios pager_modes; char *term; if( mangle_descriptors ) { /* Make fd 1 output to screen, and use some other fd for writing the resulting output back to the caller */ int in; out = dup( 1 ); close(1); close(0); /* OK to not use CLO_EXEC here because fish_pager is single threaded */ if( (in = open( ttyname(2), O_RDWR )) != -1 ) { if( dup2( 2, 1 ) == -1 ) { debug( 0, _(L"Could not set up output file descriptors for pager") ); exit( 1 ); } if( dup2( in, 0 ) == -1 ) { debug( 0, _(L"Could not set up input file descriptors for pager") ); exit( 1 ); } } else { debug( 0, _(L"Could not open tty for pager") ); exit( 1 ); } } if( !(out_file = fdopen( out, "w" )) ) { debug( 0, _(L"Could not initialize result pipe" ) ); exit( 1 ); } env_universal_init( 0, 0, 0, 0); input_common_init( &interrupt_handler ); output_set_writer( &pager_buffered_writer ); sigemptyset( & act.sa_mask ); act.sa_flags=0; act.sa_handler=SIG_DFL; act.sa_flags = 0; act.sa_handler= &handle_winch; if( sigaction( SIGWINCH, &act, 0 ) ) { wperror( L"sigaction" ); exit(1); } handle_winch( 0 ); /* Set handler for window change events */ tcgetattr(0,&pager_modes); /* get the current terminal modes */ memcpy( &saved_modes, &pager_modes, sizeof(saved_modes)); /* save a copy so we can reset the terminal later */ pager_modes.c_lflag &= ~ICANON; /* turn off canonical mode */ pager_modes.c_lflag &= ~ECHO; /* turn off echo mode */ pager_modes.c_cc[VMIN]=1; pager_modes.c_cc[VTIME]=0; /* */ if( tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */ { wperror(L"tcsetattr"); exit(1); } if( setupterm( 0, STDOUT_FILENO, 0) == ERR ) { debug( 0, _(L"Could not set up terminal") ); exit(1); } term = getenv("TERM"); if( term ) { wchar_t *wterm = str2wcs(term); output_set_term( wterm ); free( wterm ); } /* Infer term256 support */ char *fish_term256 = getenv("fish_term256"); bool support_term256; if (fish_term256) { support_term256 = from_string<bool>(fish_term256); } else { support_term256 = term && strstr(term, "256color"); } output_set_supports_term256(support_term256); }
~scoped_buffer_t() { s_writeb_buffer = old_buff; output_set_writer(old_writer); }
scoped_buffer_t(data_buffer_t *buff) : old_buff(s_writeb_buffer), old_writer(output_get_writer()) { s_writeb_buffer = buff; output_set_writer(s_writeb); }
/// set_color builtin. int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **argv) { wgetopter_t w; // Variables used for parsing the argument list. const struct woption long_options[] = {{L"background", required_argument, 0, 'b'}, {L"help", no_argument, 0, 'h'}, {L"bold", no_argument, 0, 'o'}, {L"underline", no_argument, 0, 'u'}, {L"version", no_argument, 0, 'v'}, {L"print-colors", no_argument, 0, 'c'}, {0, 0, 0, 0}}; const wchar_t *short_options = L"b:hvocu"; int argc = builtin_count_args(argv); // Some code passes variables to set_color that don't exist, like $fish_user_whatever. As a // hack, quietly return failure. if (argc <= 1) { return EXIT_FAILURE; } const wchar_t *bgcolor = NULL; bool bold = false, underline = false; int errret; // Parse options to obtain the requested operation and the modifiers. w.woptind = 0; while (1) { int c = w.wgetopt_long(argc, argv, short_options, long_options, 0); if (c == -1) { break; } switch (c) { case 0: { break; } case 'b': { bgcolor = w.woptarg; break; } case 'h': { builtin_print_help(parser, streams, argv[0], streams.out); return STATUS_BUILTIN_OK; } case 'o': { bold = true; break; } case 'u': { underline = true; break; } case 'c': { print_colors(streams); return STATUS_BUILTIN_OK; } case '?': { return STATUS_BUILTIN_ERROR; } } } // Remaining arguments are foreground color. std::vector<rgb_color_t> fgcolors; for (; w.woptind < argc; w.woptind++) { rgb_color_t fg = rgb_color_t(argv[w.woptind]); if (fg.is_none()) { streams.err.append_format(_(L"%ls: Unknown color '%ls'\n"), argv[0], argv[w.woptind]); return STATUS_BUILTIN_ERROR; } fgcolors.push_back(fg); } if (fgcolors.empty() && bgcolor == NULL && !bold && !underline) { streams.err.append_format(_(L"%ls: Expected an argument\n"), argv[0]); return STATUS_BUILTIN_ERROR; } // #1323: We may have multiple foreground colors. Choose the best one. If we had no foreground // color, we'll get none(); if we have at least one we expect not-none. const rgb_color_t fg = best_color(fgcolors, output_get_color_support()); assert(fgcolors.empty() || !fg.is_none()); const rgb_color_t bg = rgb_color_t(bgcolor ? bgcolor : L""); if (bgcolor && bg.is_none()) { streams.err.append_format(_(L"%ls: Unknown color '%ls'\n"), argv[0], bgcolor); return STATUS_BUILTIN_ERROR; } // Make sure that the term exists. if (cur_term == NULL && setupterm(0, STDOUT_FILENO, &errret) == ERR) { streams.err.append_format(_(L"%ls: Could not set up terminal\n"), argv[0]); return STATUS_BUILTIN_ERROR; } // Test if we have at least basic support for setting fonts, colors and related bits - otherwise // just give up... if (!exit_attribute_mode) { return STATUS_BUILTIN_ERROR; } // Save old output function so we can restore it. int (*const saved_writer_func)(char) = output_get_writer(); // Set our output function, which writes to a std::string. builtin_set_color_output.clear(); output_set_writer(set_color_builtin_outputter); if (bold) { if (enter_bold_mode) writembs(tparm(enter_bold_mode)); } if (underline) { if (enter_underline_mode) writembs(enter_underline_mode); } if (bgcolor != NULL) { if (bg.is_normal()) { write_color(rgb_color_t::black(), false /* not is_fg */); writembs(tparm(exit_attribute_mode)); } } if (!fg.is_none()) { if (fg.is_normal() || fg.is_reset()) { write_color(rgb_color_t::black(), true /* is_fg */); writembs(tparm(exit_attribute_mode)); } else { write_color(fg, true /* is_fg */); } } if (bgcolor != NULL) { if (!bg.is_normal() && !bg.is_reset()) { write_color(bg, false /* not is_fg */); } } // Restore saved writer function. output_set_writer(saved_writer_func); // Output the collected string. streams.out.append(str2wcstring(builtin_set_color_output)); builtin_set_color_output.clear(); return STATUS_BUILTIN_OK; }