mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +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 string_buffer_t *setlocale_buff=0;
|
||||
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
|
||||
/*
|
||||
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'$';
|
||||
}
|
||||
else
|
||||
{
|
||||
char *lang = getenv( "LANG" );
|
||||
if( lang )
|
||||
ellipsis_char = strstr( lang, ".UTF")?L'\u2026':L'$';
|
||||
else
|
||||
ellipsis_char = L'$';
|
||||
setlocale_buff = malloc( sizeof(string_buffer_t) );
|
||||
sb_init( setlocale_buff);
|
||||
}
|
||||
|
||||
sb_clear( setlocale_buff );
|
||||
sb_printf( setlocale_buff, L"%s", res );
|
||||
|
||||
return (wchar_t *)setlocale_buff->buff;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
/**
|
||||
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
|
||||
|
|
|
@ -655,6 +655,7 @@ values of these variables. They are:
|
|||
- \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 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
|
||||
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
|
||||
__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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
proper events are triggered when an event occurs.
|
||||
|
@ -224,6 +291,9 @@ static void universal_callback( int type,
|
|||
{
|
||||
wchar_t *str=0;
|
||||
|
||||
if( is_locale( name ) )
|
||||
handle_locale();
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case SET:
|
||||
|
@ -497,19 +567,6 @@ void env_set( const wchar_t *key,
|
|||
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)
|
||||
{
|
||||
wchar_t *end;
|
||||
|
@ -534,7 +591,6 @@ void env_set( const wchar_t *key,
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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 );
|
||||
}
|
||||
|
||||
if( is_locale( key ) )
|
||||
{
|
||||
handle_locale();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Attempt to remove/free the specified key/value pair from the
|
||||
specified hash table.
|
||||
|
@ -735,6 +799,10 @@ void env_remove( const wchar_t *key, int var_mode )
|
|||
{
|
||||
env_universal_remove( key );
|
||||
}
|
||||
|
||||
if( is_locale( key ) )
|
||||
handle_locale();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -845,8 +845,7 @@ static void init()
|
|||
{
|
||||
struct sigaction act;
|
||||
program_name = L"fish_pager";
|
||||
fish_setlocale( LC_ALL, L"" );
|
||||
|
||||
wsetlocale( LC_ALL, L"" );
|
||||
|
||||
int out = dup( 1 );
|
||||
close(1);
|
||||
|
|
2
fishd.c
2
fishd.c
|
@ -400,7 +400,7 @@ static void init()
|
|||
|
||||
sock = get_socket();
|
||||
daemonize();
|
||||
fish_setlocale( LC_ALL, L"" );
|
||||
wsetlocale( LC_ALL, L"" );
|
||||
env_universal_common_init( &broadcast );
|
||||
|
||||
load();
|
||||
|
|
2
parser.c
2
parser.c
|
@ -2114,7 +2114,7 @@ static void eval_job( tokenizer *tok )
|
|||
tok_get_desc( tok_last_type(tok) ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
case TOK_ERROR:
|
||||
|
|
Loading…
Reference in a new issue