mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
Improve locale implementation (should now behave identically to bash) and document locale variables behaviour
darcs-hash:20060108230049-ac50b-403f1d00c8483fc4fecc275b62e40b1c3d51bfc1.gz
This commit is contained in:
parent
690648e1b0
commit
906495d713
7 changed files with 138 additions and 36 deletions
41
common.c
41
common.c
|
@ -104,8 +104,17 @@ static struct winsize termsize;
|
||||||
*/
|
*/
|
||||||
static int block_count=0;
|
static int block_count=0;
|
||||||
|
|
||||||
|
static string_buffer_t *setlocale_buff=0;
|
||||||
|
|
||||||
|
|
||||||
void common_destroy()
|
void common_destroy()
|
||||||
{
|
{
|
||||||
|
if( setlocale_buff )
|
||||||
|
{
|
||||||
|
sb_destroy( setlocale_buff );
|
||||||
|
free( setlocale_buff );
|
||||||
|
}
|
||||||
|
|
||||||
debug( 3, L"Calls: wcsdupcat %d, wcsdupcat2 %d, wcsndup %d, str2wcs %d, wcs2str %d", c1, c2, c3, c4, c5 );
|
debug( 3, L"Calls: wcsdupcat %d, wcsdupcat2 %d, wcsndup %d, str2wcs %d, wcs2str %d", c1, c2, c3, c4, c5 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,27 +728,33 @@ wchar_t *quote_end( const wchar_t *in )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void fish_setlocale(int category, const wchar_t *locale)
|
const wchar_t *wsetlocale(int category, const wchar_t *locale)
|
||||||
{
|
{
|
||||||
char *lang = wcs2str( locale );
|
|
||||||
setlocale(category,lang);
|
char *lang = locale?wcs2str( locale ):0;
|
||||||
|
char * res = setlocale(category,lang);
|
||||||
|
|
||||||
free( lang );
|
free( lang );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Use ellipsis if on known unicode system, otherwise use $
|
Use ellipsis if on known unicode system, otherwise use $
|
||||||
*/
|
*/
|
||||||
if( wcslen( locale ) )
|
char *ctype = setlocale( LC_CTYPE, (void *)0 );
|
||||||
|
ellipsis_char = (strstr( ctype, ".UTF")||strstr( ctype, ".utf") )?L'\u2026':L'$';
|
||||||
|
|
||||||
|
if( !res )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if( !setlocale_buff )
|
||||||
{
|
{
|
||||||
ellipsis_char = wcsstr( locale, L".UTF")?L'\u2026':L'$';
|
setlocale_buff = malloc( sizeof(string_buffer_t) );
|
||||||
}
|
sb_init( setlocale_buff);
|
||||||
else
|
|
||||||
{
|
|
||||||
char *lang = getenv( "LANG" );
|
|
||||||
if( lang )
|
|
||||||
ellipsis_char = strstr( lang, ".UTF")?L'\u2026':L'$';
|
|
||||||
else
|
|
||||||
ellipsis_char = L'$';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sb_clear( setlocale_buff );
|
||||||
|
sb_printf( setlocale_buff, L"%s", res );
|
||||||
|
|
||||||
|
return (wchar_t *)setlocale_buff->buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
int contains_str( const wchar_t *a, ... )
|
int contains_str( const wchar_t *a, ... )
|
||||||
|
|
7
common.h
7
common.h
|
@ -256,9 +256,12 @@ wchar_t *quote_end( const wchar_t *in );
|
||||||
void error_reset();
|
void error_reset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set the locale, also change the ellipsis character
|
This function behaves exactly like a wide character equivalent of
|
||||||
|
the C function setlocale, except that it will also try to detect if
|
||||||
|
the user is using a Unicode character set, and if so, use the
|
||||||
|
unicode ellipsis character as ellipsis, instead of '$'.
|
||||||
*/
|
*/
|
||||||
void fish_setlocale( int category, const wchar_t *locale );
|
const wchar_t *wsetlocale( int category, const wchar_t *locale );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks if \c needle is included in the list of strings specified
|
Checks if \c needle is included in the list of strings specified
|
||||||
|
|
|
@ -655,6 +655,7 @@ values of these variables. They are:
|
||||||
- \c PWD, which is the current working directory.
|
- \c PWD, which is the current working directory.
|
||||||
- \c status, which is the exit status of the last foreground job to exit. If a job contains pipelines, the status of the last command in the pipeline is the status for the job.
|
- \c status, which is the exit status of the last foreground job to exit. If a job contains pipelines, the status of the last command in the pipeline is the status for the job.
|
||||||
- \c USER, which is the username. This variable can only be changed by the root user.
|
- \c USER, which is the username. This variable can only be changed by the root user.
|
||||||
|
- \c LANG, \cLC_ALL, \c LC_COLLATE, \c LC_CTYPE, \cLC_MESSAGES, \c LC_MONETARY, \c LC_NUMERIC and LC_TIME set the language option for the shell and subprograms. See the section <a href='#variables-locale'>Locale variables</a> for more information.
|
||||||
|
|
||||||
Variables whose name are in uppercase are exported to the commands
|
Variables whose name are in uppercase are exported to the commands
|
||||||
started by fish. This rule is not enforced by fish, but it is good
|
started by fish. This rule is not enforced by fish, but it is good
|
||||||
|
@ -663,6 +664,22 @@ unexported variables. \c fish also uses several variables
|
||||||
internally. Such variables are prefixed with the string __FISH or
|
internally. Such variables are prefixed with the string __FISH or
|
||||||
__fish. These should be ignored by the user.
|
__fish. These should be ignored by the user.
|
||||||
|
|
||||||
|
\subsection variables-locale Locale variables
|
||||||
|
|
||||||
|
The most common way to set the locale to use a command like 'set -x
|
||||||
|
LANG en_GB.utf8', which sets the current locale to be the english
|
||||||
|
language, adapted to great britain, using the UTF-8 character set. For
|
||||||
|
a list of available locales, use 'locale -a'.
|
||||||
|
|
||||||
|
\c LANG, \cLC_ALL, \c LC_COLLATE, \c LC_CTYPE, \cLC_MESSAGES, \c
|
||||||
|
LC_MONETARY, \c LC_NUMERIC and LC_TIME set the language option for the
|
||||||
|
shell and subprograms. These variables work as follows: \c LC_ALL
|
||||||
|
forces all the aspects of the locale to the specified value. If LC_ALL
|
||||||
|
is set, all other locale variables will be ignored. The other LC_
|
||||||
|
variables set the specified aspect of the locale information. . LANG
|
||||||
|
is a fallback value, it will be used if none of the LC_ variables are
|
||||||
|
specified.
|
||||||
|
|
||||||
\section builtin-overview Builtins
|
\section builtin-overview Builtins
|
||||||
|
|
||||||
Many other shells have a large library of builtin commands. Most of
|
Many other shells have a large library of builtin commands. Most of
|
||||||
|
|
96
env.c
96
env.c
|
@ -214,6 +214,73 @@ static mode_t get_umask()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Checks if the specified variable is a locale variable
|
||||||
|
*/
|
||||||
|
static int is_locale( const wchar_t *key )
|
||||||
|
{
|
||||||
|
return contains_str( key, L"LANG", L"LC_ALL", L"LC_COLLATE", L"LC_CTYPE", L"LC_MESSAGES", L"LC_MONETARY", L"LC_NUMERIC", L"LC_TIME", (void *)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Properly sets all locale information
|
||||||
|
*/
|
||||||
|
static void handle_locale()
|
||||||
|
{
|
||||||
|
const wchar_t *lc_all = env_get( L"LC_ALL" );
|
||||||
|
const wchar_t *lang;
|
||||||
|
int i;
|
||||||
|
wchar_t *old = wcsdup(wsetlocale( LC_MESSAGES, (void *)0 ));
|
||||||
|
|
||||||
|
static const wchar_t *lc[] =
|
||||||
|
{
|
||||||
|
L"LC_COLLATE", L"LC_CTYPE", L"LC_MESSAGES", L"LC_MONETARY", L"LC_NUMERIC", L"LC_TIME", (void *)0
|
||||||
|
}
|
||||||
|
;
|
||||||
|
static const int cat[] =
|
||||||
|
{
|
||||||
|
LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC, LC_TIME
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
if( lc_all )
|
||||||
|
{
|
||||||
|
wsetlocale( LC_ALL, lc_all );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lang = env_get( L"LANG" );
|
||||||
|
if( lang )
|
||||||
|
{
|
||||||
|
wsetlocale( LC_ALL, lang );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i=0; lc[i]; i++ )
|
||||||
|
{
|
||||||
|
const wchar_t *val = env_get( lc[i] );
|
||||||
|
if( val )
|
||||||
|
wsetlocale( cat[i], val );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( wcscmp( wsetlocale( LC_MESSAGES, (void *)0 ), old ) != 0 )
|
||||||
|
{
|
||||||
|
/* Make change known to gettext. */
|
||||||
|
{
|
||||||
|
extern int _nl_msg_cat_cntr;
|
||||||
|
++_nl_msg_cat_cntr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( is_interactive )
|
||||||
|
{
|
||||||
|
debug( 0, _(L"Changing language to english") );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free( old );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Universal variable callback function. This function makes sure the
|
Universal variable callback function. This function makes sure the
|
||||||
proper events are triggered when an event occurs.
|
proper events are triggered when an event occurs.
|
||||||
|
@ -224,6 +291,9 @@ static void universal_callback( int type,
|
||||||
{
|
{
|
||||||
wchar_t *str=0;
|
wchar_t *str=0;
|
||||||
|
|
||||||
|
if( is_locale( name ) )
|
||||||
|
handle_locale();
|
||||||
|
|
||||||
switch( type )
|
switch( type )
|
||||||
{
|
{
|
||||||
case SET:
|
case SET:
|
||||||
|
@ -497,19 +567,6 @@ void env_set( const wchar_t *key,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( wcscmp(key, L"LANG" )==0 )
|
|
||||||
{
|
|
||||||
fish_setlocale(LC_ALL,val);
|
|
||||||
/* Make change known to gettext. */
|
|
||||||
{
|
|
||||||
extern int _nl_msg_cat_cntr;
|
|
||||||
++_nl_msg_cat_cntr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( is_interactive )
|
|
||||||
debug( 0, _(L"Changing language to english") );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( wcscmp( key, L"umask" ) == 0)
|
if( wcscmp( key, L"umask" ) == 0)
|
||||||
{
|
{
|
||||||
wchar_t *end;
|
wchar_t *end;
|
||||||
|
@ -534,7 +591,6 @@ void env_set( const wchar_t *key,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Zero element arrays are internaly not coded as null but as this placeholder string
|
Zero element arrays are internaly not coded as null but as this placeholder string
|
||||||
*/
|
*/
|
||||||
|
@ -686,8 +742,16 @@ void env_set( const wchar_t *key,
|
||||||
al_destroy( &ev.arguments );
|
al_destroy( &ev.arguments );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( is_locale( key ) )
|
||||||
|
{
|
||||||
|
handle_locale();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Attempt to remove/free the specified key/value pair from the
|
Attempt to remove/free the specified key/value pair from the
|
||||||
specified hash table.
|
specified hash table.
|
||||||
|
@ -735,6 +799,10 @@ void env_remove( const wchar_t *key, int var_mode )
|
||||||
{
|
{
|
||||||
env_universal_remove( key );
|
env_universal_remove( key );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( is_locale( key ) )
|
||||||
|
handle_locale();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -845,8 +845,7 @@ static void init()
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
program_name = L"fish_pager";
|
program_name = L"fish_pager";
|
||||||
fish_setlocale( LC_ALL, L"" );
|
wsetlocale( LC_ALL, L"" );
|
||||||
|
|
||||||
|
|
||||||
int out = dup( 1 );
|
int out = dup( 1 );
|
||||||
close(1);
|
close(1);
|
||||||
|
|
2
fishd.c
2
fishd.c
|
@ -400,7 +400,7 @@ static void init()
|
||||||
|
|
||||||
sock = get_socket();
|
sock = get_socket();
|
||||||
daemonize();
|
daemonize();
|
||||||
fish_setlocale( LC_ALL, L"" );
|
wsetlocale( LC_ALL, L"" );
|
||||||
env_universal_common_init( &broadcast );
|
env_universal_common_init( &broadcast );
|
||||||
|
|
||||||
load();
|
load();
|
||||||
|
|
2
parser.c
2
parser.c
|
@ -2114,7 +2114,7 @@ static void eval_job( tokenizer *tok )
|
||||||
tok_get_desc( tok_last_type(tok) ) );
|
tok_get_desc( tok_last_type(tok) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOK_ERROR:
|
case TOK_ERROR:
|
||||||
|
|
Loading…
Reference in a new issue