From e66af50a984b9b693fd6bbbf5f806612cdd03b66 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 24 Nov 2005 10:25:33 +0000 Subject: 22014: argument-base, insert-unicode-char --- ChangeLog | 9 ++++ Doc/Zsh/contrib.yo | 14 +++++++ Doc/Zsh/zle.yo | 17 ++++++++ Functions/Zle/.distfiles | 1 + Functions/Zle/insert-unicode-char | 17 ++++++++ Src/Zle/iwidgets.list | 1 + Src/Zle/zle.h | 1 + Src/Zle/zle_main.c | 1 + Src/Zle/zle_misc.c | 88 ++++++++++++++++++++++++++++++++------- 9 files changed, 133 insertions(+), 16 deletions(-) create mode 100644 Functions/Zle/insert-unicode-char diff --git a/ChangeLog b/ChangeLog index 4a8d74d3b..4ab7ceea9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2005-11-24 Peter Stephenson + + * 22014: Doc/Zsh/Contrib.yo, Doc/Zsh/zle.yo, + Functions/Zle/.distfiles, Functions/Zle/insert-unicode-char, + Src/Zle/iwidgets.list, Src/Zle/zle.h, Src/Zle/zle_main.c, + Src/Zle/zle_misc.c: internal widget argument-base sets + numeric base for next prefix argument, widget insert-unicode-char + uses this to insert Unicode character by \U........ + 2005-11-23 Peter Stephenson * 22013: INSTALL, NEWS, Completion/compinstall, diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 5a70880ee..43d2812ff 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -693,6 +693,9 @@ The function may be run outside zle in which case it prints the character (together with a newline) to standard output. Input is still read from keystrokes. +See tt(insert-unicode-char) for an alternative way of inserting Unicode +characters using their hexadecimal character number. + The set of accented characters is reasonably complete up to Unicode character U+0180, the set of special characters less so. However, it it is very sporadic from that point. Adding new characters is easy, @@ -917,6 +920,17 @@ narrow-to-region -p $'Editing restricted region\n' \ zle recursive-edit narrow-to-region -R state) ) +tindex(insert-unicode-char) +item(tt(insert-unicode-char))( +When first executed, the user inputs a set of hexadecimal digits. +This is terminated with another call to tt(insert-unicode-char). +The digits are then turned into the corresponding Unicode character. +For example, if the widget is bound to tt(^XU), the character sequence +`tt(^XU 4 c ^XU)' inserts tt(L) (Unicode U+004c). + +See tt(insert-composed-char) for a way of inserting characters +using a two-character mnemonic. +) tindex(predict-on) tindex(predict-off) item(tt(predict-on))( diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 1daffde00..40bc24988 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -1519,6 +1519,23 @@ Inside a widget function, if passed an argument, i.e. `tt(zle universal-argument) var(num)', the numerical argument will be set to var(num); this is equivalent to `tt(NUMERIC=)var(num)'. ) +tindex(argument-base) +item(tt(argument-base))( +Use the existing numeric argument as a numeric base, which must be in the +range 2 to 36 inclusive. Subsequent use of tt(digit-argument) and +tt(universal-argument) will input a new prefix in the given base. +The usual hexadecimal convention is used: the letter tt(a) or tt(A) +corresponds to 10, and so on. Arguments in bases requiring digits from 10 +upwards are more conveniently input with tt(universal-argument), since +tt(ESC-a) etc. are not usually bound to tt(digit-argument). + +The function can be used with a command argument inside a user-defined +widget. The following code sets the base to 16 and lets the user input a +hexadecimal argument until a key out of the digit range is typed: + +example(zle argument-base 16 +zle universal-argument) +) enditem() texinode(Completion)(Miscellaneous)(Arguments)(Zle Widgets) subsect(Completion) diff --git a/Functions/Zle/.distfiles b/Functions/Zle/.distfiles index e6d1cf3d6..5bce7ce04 100644 --- a/Functions/Zle/.distfiles +++ b/Functions/Zle/.distfiles @@ -9,6 +9,7 @@ edit-command-line forward-word-match history-pattern-search history-search-end incarg incremental-complete-word insert-composed-char insert-files +insert-unicode-char keeper kill-word-match match-words-by-style narrow-to-region narrow-to-region-invisible predict-on diff --git a/Functions/Zle/insert-unicode-char b/Functions/Zle/insert-unicode-char new file mode 100644 index 000000000..0ffd29418 --- /dev/null +++ b/Functions/Zle/insert-unicode-char @@ -0,0 +1,17 @@ +# Make hex integers appear as 0x... +setopt localoptions cbases + +if [[ $LASTWIDGET = insert-unicode-char ]]; then + # Second call; we should have a usable prefix. + # If we don't, give up. + (( ${+NUMERIC} )) || return 1 + # Convert it back to hex, padded with zeroes to 8 digits plus the 0x... + local -i 16 -Z 10 arg=$NUMERIC + # ...and use print to turn this into a Unicode character. + LBUFFER+="$(print -n "\U${arg##0x}")" +else + # Set the base to 16... + zle argument-base 16 + # ...wait for user to type hex keys then call this widget again. + zle universal-argument +fi diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list index bf1abdadc..cc9ef20f9 100644 --- a/Src/Zle/iwidgets.list +++ b/Src/Zle/iwidgets.list @@ -13,6 +13,7 @@ "accept-and-menu-complete", acceptandmenucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX "accept-line", acceptline, 0 "accept-line-and-down-history", acceptlineanddownhistory, 0 +"argument-base", argumentbase, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND "backward-char", backwardchar, 0 "backward-delete-char", backwarddeletechar, ZLE_KEEPSUFFIX "backward-delete-word", backwarddeleteword, ZLE_KEEPSUFFIX diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index c47efae9a..2981f9a83 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -205,6 +205,7 @@ struct modifier { int mult; /* repeat count */ int tmult; /* repeat count actually being edited */ int vibuf; /* vi cut buffer */ + int base; /* numeric base for digit arguments (usually 10) */ }; #define MOD_MULT (1<<0) /* a repeat count has been selected */ diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index abcd06221..4f1079747 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -1153,6 +1153,7 @@ initmodifier(struct modifier *mp) mp->mult = 1; mp->tmult = 1; mp->vibuf = 0; + mp->base = 10; } /* Reset command modifiers, unless the command just executed was a prefix. * diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index b3706f2d0..869e0a435 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -518,12 +518,9 @@ quotedinsert(char **args) return selfinsert(args); } -/**/ -int -digitargument(UNUSED(char **args)) +static int +parsedigit(int inkey) { - int sign = (zmult < 0) ? -1 : 1; - #ifdef MULTIBYTE_SUPPORT /* * It's too dangerous to allow metafied input. See @@ -531,23 +528,48 @@ digitargument(UNUSED(char **args)) * of digits. We are assuming ASCII is a subset of the multibyte * encoding. */ - if (!idigit(lastchar)) - return 1; #else /* allow metafied as well as ordinary digits */ - if (!idigit(lastchar & 0x7f)) - return 1; + inkey &= 0x7f; #endif + /* remember lastchar is not a wide character */ + if (zmod.base > 10) + { + if (lastchar >= 'a' && lastchar < 'a' + zmod.base - 10) + return lastchar - 'a' + 10; + else if (lastchar >= 'A' && lastchar < 'A' + zmod.base - 10) + return lastchar - 'A' + 10; + else if (idigit(lastchar)) + return lastchar - '0'; + else + return -1; + } + else if (lastchar >= '0' && lastchar < '0' + zmod.base) + return lastchar - '0'; + else + return -1; +} + +/**/ +int +digitargument(UNUSED(char **args)) +{ + int sign = (zmult < 0) ? -1 : 1; + int newdigit = parsedigit(lastchar); + + if (newdigit < 0) + return 1; + if (!(zmod.flags & MOD_TMULT)) zmod.tmult = 0; if (zmod.flags & MOD_NEG) { /* If we just had a negative argument, this is the digit, * * rather than the -1 assumed by negargument() */ - zmod.tmult = sign * (lastchar & 0xf); + zmod.tmult = sign * newdigit; zmod.flags &= ~MOD_NEG; } else - zmod.tmult = zmod.tmult * 10 + sign * (lastchar & 0xf); + zmod.tmult = zmod.tmult * zmod.base + sign * newdigit; zmod.flags |= MOD_TMULT; prefixflag = 1; return 0; @@ -594,12 +616,16 @@ universalargument(char **args) if (gotk == '-' && !digcnt) { minus = -1; digcnt++; - } else if (idigit(gotk)) { - pref = pref * 10 + (gotk & 0xf); - digcnt++; } else { - ungetbyte(gotk); - break; + int newdigit = parsedigit(gotk); + + if (newdigit >= 0) { + pref = pref * zmod.base + newdigit; + digcnt++; + } else { + ungetbyte(gotk); + break; + } } } if (digcnt) @@ -611,6 +637,36 @@ universalargument(char **args) return 0; } +/* Set the base for a digit argument. */ + +/**/ +int +argumentbase(char **args) +{ + int multbase; + + if (*args) + multbase = (int)zstrtol(*args, NULL, 0); + else + multbase = zmod.mult; + + if (multbase < 2 || multbase > ('9' - '0' + 1) + ('z' - 'a' + 1)) + return 1; + + zmod.base = multbase; + + /* reset modifier, apart from base... */ + zmod.flags = 0; + zmod.mult = 1; + zmod.tmult = 1; + zmod.vibuf = 0; + + /* ...but indicate we are still operating on a prefix argument. */ + prefixflag = 1; + + return 0; +} + /**/ int copyprevword(UNUSED(char **args)) -- cgit 1.4.1