mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-14 08:58:01 +00:00
400 lines
7.6 KiB
C++
400 lines
7.6 KiB
C++
#include "config.h"
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <termios.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <locale.h>
|
|
|
|
#if HAVE_NCURSES_H
|
|
#include <ncurses.h>
|
|
#else
|
|
#include <curses.h>
|
|
#endif
|
|
|
|
#if HAVE_TERMIO_H
|
|
#include <termio.h>
|
|
#endif
|
|
|
|
#if HAVE_TERM_H
|
|
#include <term.h>
|
|
#elif HAVE_NCURSES_TERM_H
|
|
#include <ncurses/term.h>
|
|
#endif
|
|
|
|
#include <errno.h>
|
|
|
|
#ifdef HAVE_GETOPT_H
|
|
#include <getopt.h>
|
|
#endif
|
|
|
|
#if HAVE_LIBINTL_H
|
|
#include <libintl.h>
|
|
#endif
|
|
|
|
#include "fallback.h"
|
|
#include "print_help.h"
|
|
#include "color.h"
|
|
|
|
/*
|
|
Small utility for setting the color.
|
|
Usage: set_color COLOR
|
|
where COLOR is either an integer from 0 to seven or one of the strings in the col array.
|
|
*/
|
|
|
|
#define COLORS (sizeof(col)/sizeof(char *))
|
|
|
|
/**
|
|
Program name
|
|
*/
|
|
#define SET_COLOR "set_color"
|
|
|
|
/**
|
|
Getopt short switches for set_color
|
|
*/
|
|
#define GETOPT_STRING "b:hvocu"
|
|
|
|
#ifdef _
|
|
#undef _
|
|
#endif
|
|
|
|
#ifdef USE_GETTEXT
|
|
#define _(string) gettext(string)
|
|
#else
|
|
#define _(string) (string)
|
|
#endif
|
|
|
|
const char *col[]=
|
|
{
|
|
"black",
|
|
"red",
|
|
"green",
|
|
"brown",
|
|
"yellow",
|
|
"blue",
|
|
"magenta",
|
|
"purple",
|
|
"cyan",
|
|
"white",
|
|
"normal"
|
|
};
|
|
|
|
const int col_idx[]=
|
|
{
|
|
0,
|
|
1,
|
|
2,
|
|
3,
|
|
3,
|
|
4,
|
|
5,
|
|
5,
|
|
6,
|
|
7,
|
|
8
|
|
};
|
|
|
|
void print_colors()
|
|
{
|
|
size_t i;
|
|
for (i=0; i<COLORS; i++)
|
|
{
|
|
printf("%s\n", col[i]);
|
|
}
|
|
}
|
|
|
|
static void check_locale_init()
|
|
{
|
|
static int is_init = 0;
|
|
if (is_init)
|
|
return;
|
|
|
|
is_init = 1;
|
|
setlocale(LC_ALL, "");
|
|
bindtextdomain(PACKAGE_NAME, LOCALEDIR);
|
|
textdomain(PACKAGE_NAME);
|
|
}
|
|
|
|
/* A lot of this code is taken straight from output.cpp; it sure would be nice to factor these together. */
|
|
|
|
static bool support_term256;
|
|
static bool output_get_supports_term256(void)
|
|
{
|
|
return support_term256;
|
|
}
|
|
|
|
static bool term256_support_is_native(void)
|
|
{
|
|
/* Return YES if we think the term256 support is "native" as opposed to forced. */
|
|
return max_colors == 256;
|
|
}
|
|
|
|
static bool write_color(char *todo, unsigned char idx, bool is_fg)
|
|
{
|
|
bool result = false;
|
|
if (idx < 16 || term256_support_is_native())
|
|
{
|
|
/* Use tparm */
|
|
putp(tparm(todo, idx));
|
|
result = true;
|
|
}
|
|
else
|
|
{
|
|
/* We are attempting to bypass the term here. Generate the ANSI escape sequence ourself. */
|
|
char stridx[128];
|
|
format_long_safe(stridx, (long)idx);
|
|
char buff[128] = "\x1b[";
|
|
strcat(buff, is_fg ? "38;5;" : "48;5;");
|
|
strcat(buff, stridx);
|
|
strcat(buff, "m");
|
|
write_loop(STDOUT_FILENO, buff, strlen(buff));
|
|
result = true;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static bool write_foreground_color(unsigned char idx)
|
|
{
|
|
if (set_a_foreground && set_a_foreground[0])
|
|
{
|
|
return write_color(set_a_foreground, idx, true);
|
|
}
|
|
else if (set_foreground && set_foreground[0])
|
|
{
|
|
return write_color(set_foreground, idx, true);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static bool write_background_color(unsigned char idx)
|
|
{
|
|
if (set_a_background && set_a_background[0])
|
|
{
|
|
return write_color(set_a_background, idx, false);
|
|
}
|
|
else if (set_background && set_background[0])
|
|
{
|
|
return write_color(set_background, idx, false);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static unsigned char index_for_color(rgb_color_t c)
|
|
{
|
|
if (c.is_named() || ! output_get_supports_term256())
|
|
{
|
|
return c.to_name_index();
|
|
}
|
|
else
|
|
{
|
|
return c.to_term256_index();
|
|
}
|
|
}
|
|
|
|
|
|
int main(int argc, char **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;
|
|
|
|
char *bgcolor=0;
|
|
char *fgcolor=0;
|
|
bool bold=false;
|
|
bool underline=false;
|
|
|
|
while (1)
|
|
{
|
|
static struct option
|
|
long_options[] =
|
|
{
|
|
{
|
|
"background", required_argument, 0, 'b'
|
|
}
|
|
,
|
|
{
|
|
"help", no_argument, 0, 'h'
|
|
}
|
|
,
|
|
{
|
|
"bold", no_argument, 0, 'o'
|
|
}
|
|
,
|
|
{
|
|
"underline", no_argument, 0, 'u'
|
|
}
|
|
,
|
|
{
|
|
"version", no_argument, 0, 'v'
|
|
}
|
|
,
|
|
{
|
|
"print-colors", no_argument, 0, 'c'
|
|
}
|
|
,
|
|
{
|
|
0, 0, 0, 0
|
|
}
|
|
}
|
|
;
|
|
|
|
int opt_index = 0;
|
|
|
|
int opt = getopt_long(argc,
|
|
argv,
|
|
GETOPT_STRING,
|
|
long_options,
|
|
&opt_index);
|
|
|
|
if (opt == -1)
|
|
break;
|
|
|
|
switch (opt)
|
|
{
|
|
case 0:
|
|
break;
|
|
|
|
case 'b':
|
|
bgcolor = optarg;
|
|
break;
|
|
case 'h':
|
|
print_help(argv[0], 1);
|
|
exit(0);
|
|
|
|
case 'o':
|
|
bold=true;
|
|
break;
|
|
|
|
case 'u':
|
|
underline=true;
|
|
break;
|
|
|
|
case 'v':
|
|
check_locale_init();
|
|
fprintf(stderr, _("%s, version %s\n"), SET_COLOR, PACKAGE_VERSION);
|
|
exit(0);
|
|
|
|
case 'c':
|
|
print_colors();
|
|
exit(0);
|
|
|
|
case '?':
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (argc-optind)
|
|
{
|
|
case 0:
|
|
// printf( "no fg\n" );
|
|
break;
|
|
|
|
case 1:
|
|
fgcolor=argv[optind];
|
|
// printf( "fg %s\n", fgcolor );
|
|
break;
|
|
|
|
default:
|
|
check_locale_init();
|
|
printf(_("%s: Too many arguments\n"), SET_COLOR);
|
|
return 1;
|
|
}
|
|
|
|
/* Infer term256 support */
|
|
char *fish_term256 = getenv("fish_term256");
|
|
if (fish_term256)
|
|
{
|
|
support_term256 = from_string<bool>(fish_term256);
|
|
}
|
|
else
|
|
{
|
|
const char *term = getenv("TERM");
|
|
support_term256 = term && strstr(term, "256color");
|
|
}
|
|
|
|
if (!fgcolor && !bgcolor && !bold && !underline)
|
|
{
|
|
check_locale_init();
|
|
fprintf(stderr, _("%s: Expected an argument\n"), SET_COLOR);
|
|
print_help(argv[0], 2);
|
|
return 1;
|
|
}
|
|
|
|
rgb_color_t fg = rgb_color_t(fgcolor ? fgcolor : "");
|
|
if (fgcolor && fg.is_none())
|
|
{
|
|
check_locale_init();
|
|
fprintf(stderr, _("%s: Unknown color '%s'\n"), SET_COLOR, fgcolor);
|
|
return 1;
|
|
}
|
|
|
|
rgb_color_t bg = rgb_color_t(bgcolor ? bgcolor : "");
|
|
if (bgcolor && bg.is_none())
|
|
{
|
|
check_locale_init();
|
|
fprintf(stderr, _("%s: Unknown color '%s'\n"), SET_COLOR, bgcolor);
|
|
return 1;
|
|
}
|
|
|
|
setupterm(0, STDOUT_FILENO, 0);
|
|
|
|
if (bold)
|
|
{
|
|
if (enter_bold_mode)
|
|
putp(enter_bold_mode);
|
|
}
|
|
|
|
if (underline)
|
|
{
|
|
if (enter_underline_mode)
|
|
putp(enter_underline_mode);
|
|
}
|
|
|
|
if (bgcolor)
|
|
{
|
|
if (bg.is_normal())
|
|
{
|
|
write_background_color(0);
|
|
putp(tparm(exit_attribute_mode));
|
|
}
|
|
}
|
|
|
|
if (fgcolor)
|
|
{
|
|
if (fg.is_normal())
|
|
{
|
|
write_foreground_color(0);
|
|
putp(tparm(exit_attribute_mode));
|
|
}
|
|
else
|
|
{
|
|
write_foreground_color(index_for_color(fg));
|
|
}
|
|
}
|
|
|
|
if (bgcolor)
|
|
{
|
|
if (! bg.is_normal())
|
|
{
|
|
write_background_color(index_for_color(bg));
|
|
}
|
|
}
|
|
|
|
if (del_curterm(cur_term) == ERR)
|
|
{
|
|
fprintf(stderr, "%s", _("Error while closing terminfo"));
|
|
}
|
|
|
|
}
|