2013-02-14 15:50:24 -08:00
/** \file builtin_set_color.cpp Functions defining the set_color builtin
Functions used for implementing the set_color builtin .
*/
# include "config.h"
# include "builtin.h"
# include "color.h"
# include "output.h"
2013-02-15 14:00:25 -08:00
# if HAVE_NCURSES_H
# include <ncurses.h>
# else
# include <curses.h>
# endif
2013-02-14 15:50:24 -08:00
# if HAVE_TERM_H
# include <term.h>
# elif HAVE_NCURSES_TERM_H
# include <ncurses/term.h>
# endif
/* We know about these buffers */
extern wcstring stdout_buffer , stderr_buffer ;
/**
Error message for invalid path operations
*/
# define BUILTIN_SET_PATH_ERROR L"%ls: Warning: path component %ls may not be valid in %ls.\n"
/**
Hint for invalid path operation with a colon
*/
# define BUILTIN_SET_PATH_HINT L"%ls: Did you mean 'set %ls $%ls %ls'?\n"
/**
Error for mismatch between index count and elements
*/
# define BUILTIN_SET_ARG_COUNT L"%ls: The number of variable indexes does not match the number of values\n"
static void print_colors ( void )
{
const wcstring_list_t result = rgb_color_t : : named_color_names ( ) ;
size_t i ;
for ( i = 0 ; i < result . size ( ) ; i + + )
{
stdout_buffer . append ( result . at ( i ) ) ;
stdout_buffer . push_back ( L ' \n ' ) ;
}
}
2013-02-14 16:46:54 -08:00
/* function we set as the output writer */
static std : : string builtin_set_color_output ;
static int set_color_builtin_outputter ( char c )
{
ASSERT_IS_MAIN_THREAD ( ) ;
builtin_set_color_output . push_back ( c ) ;
return 0 ;
}
2013-02-14 15:50:24 -08:00
/**
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 ) ;
2014-03-27 13:46:33 -07:00
/* 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 ;
}
2013-02-14 15:50:24 -08:00
const wchar_t * bgcolor = NULL ;
bool bold = false , underline = false ;
2013-05-09 22:37:28 +10:00
int errret ;
2013-02-14 15:50:24 -08:00
/* 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 " " ) ;
2013-09-21 15:15:06 -07:00
if ( fgcolor & & ( fg . is_none ( ) | | fg . is_ignore ( ) ) )
2013-02-14 15:50:24 -08:00
{
2013-03-24 15:33:45 -07:00
append_format ( stderr_buffer , _ ( L " %ls: Unknown color '%ls' \n " ) , argv [ 0 ] , fgcolor ) ;
2013-02-14 15:50:24 -08:00
return STATUS_BUILTIN_ERROR ;
}
const rgb_color_t bg = rgb_color_t ( bgcolor ? bgcolor : L " " ) ;
2013-09-21 15:15:06 -07:00
if ( bgcolor & & ( bg . is_none ( ) | | bg . is_ignore ( ) ) )
2013-02-14 15:50:24 -08:00
{
2013-03-24 15:33:45 -07:00
append_format ( stderr_buffer , _ ( L " %ls: Unknown color '%ls' \n " ) , argv [ 0 ] , bgcolor ) ;
2013-02-14 15:50:24 -08:00
return STATUS_BUILTIN_ERROR ;
}
2013-02-19 17:48:51 -08:00
2013-02-15 14:00:25 -08:00
/* Make sure that the term exists */
2013-05-09 22:37:28 +10:00
if ( cur_term = = NULL & & setupterm ( 0 , STDOUT_FILENO , & errret ) = = ERR )
2013-02-15 14:00:25 -08:00
{
2013-03-24 15:33:45 -07:00
append_format ( stderr_buffer , _ ( L " %ls: Could not set up terminal \n " ) , argv [ 0 ] ) ;
2013-02-15 14:00:25 -08:00
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 ;
}
2013-02-14 15:50:24 -08:00
2013-02-14 16:46:54 -08:00
/* Save old output function so we can restore it */
int ( * const saved_writer_func ) ( char ) = output_get_writer ( ) ;
2013-02-19 17:48:51 -08:00
2013-02-14 16:46:54 -08:00
/* Set our output function, which writes to a std::string */
builtin_set_color_output . clear ( ) ;
output_set_writer ( set_color_builtin_outputter ) ;
2013-02-14 15:50:24 -08:00
if ( bold )
{
if ( enter_bold_mode )
2013-02-14 16:46:54 -08:00
writembs ( tparm ( enter_bold_mode ) ) ;
2013-02-14 15:50:24 -08:00
}
if ( underline )
{
if ( enter_underline_mode )
2013-02-14 16:46:54 -08:00
writembs ( enter_underline_mode ) ;
2013-02-14 15:50:24 -08:00
}
if ( bgcolor ! = NULL )
{
if ( bg . is_normal ( ) )
{
write_background_color ( 0 ) ;
2013-02-14 16:46:54 -08:00
writembs ( tparm ( exit_attribute_mode ) ) ;
2013-02-14 15:50:24 -08:00
}
}
if ( fgcolor ! = NULL )
{
2013-09-21 15:15:06 -07:00
if ( fg . is_normal ( ) | | fg . is_reset ( ) )
2013-02-14 15:50:24 -08:00
{
write_foreground_color ( 0 ) ;
2013-02-14 16:46:54 -08:00
writembs ( tparm ( exit_attribute_mode ) ) ;
2013-02-14 15:50:24 -08:00
}
else
{
write_foreground_color ( index_for_color ( fg ) ) ;
}
}
if ( bgcolor ! = NULL )
{
2013-09-21 15:15:06 -07:00
if ( ! bg . is_normal ( ) & & ! bg . is_reset ( ) )
2013-02-14 15:50:24 -08:00
{
write_background_color ( index_for_color ( bg ) ) ;
}
}
2013-02-19 17:48:51 -08:00
2013-02-14 16:46:54 -08:00
/* Restore saved writer function */
output_set_writer ( saved_writer_func ) ;
2013-02-19 17:48:51 -08:00
2013-02-14 16:46:54 -08:00
/* Output the collected string */
2014-03-25 12:44:21 -07:00
stdout_buffer . append ( str2wcstring ( builtin_set_color_output ) ) ;
builtin_set_color_output . clear ( ) ;
2013-02-19 17:48:51 -08:00
2013-02-14 15:50:24 -08:00
return STATUS_BUILTIN_OK ;
}