On Sat, Mar 26, 2016 at 04:52:47PM +0100, Bram Moolenaar wrote: > > Anton Lindqvist wrote: > > > > > Hi, > > > > This patch adds a function with the declaration optiontype({option}) > > > > which returns the type of the given option. I'm currently using it to > > > > achieve the following option toggle mapping: > > > > > > > > " :NMapChangeOption[!] {letter} {option} [enable] > > > > " > > > > " Create a normal mode option toggle mapping for {option}. The > > > > mapping key > > > > " sequence will be prefixed with 'co' followed by {letter}. > > > > " > > > > " By default the option will only be changed in the current buffer. > > > > Using [!] > > > > " will change the option globally. > > > > " > > > > " Boolean option example: > > > > " > > > > " :NMapChangeOption s spell > > > > " > > > > " Pressing 'cos' will toggle the spell option on and off. > > > > " > > > > " Non boolean option example: > > > > " > > > > " :NMapChangeOption y syntax ON > > > > " > > > > " The optional [enable] argument can be used for string and comma > > > > separated > > > > " list options. Pressing 'coy' will add/remove 'ON' from the syntax > > > > option. > > > > " > > > > " This functionality is borrowed from Tim Pope's unimpaired.vim > > > > plugin. > > > > command! -bang -complete=option -nargs=+ NMapChangeOption > > > > \ call s:NMapChangeOption(<bang>0, <f-args>) > > > > func! s:NMapChangeOption(global, letter, option, ...) abort > > > > let set = a:global ? 'set' : 'setlocal' > > > > let type = optiontype(a:option) > > > > if type == 0 " boolean > > > > let rhs = printf(':%s <C-R>=&%s ? "no" : ""<CR>%s<CR>', > > > > \ set, a:option, a:option) > > > > elseif type == 2 " comma separated list > > > > let rhs = printf(':%s %s<C-R>=&%s !~# "%s" ? "+=" : > > > > "-="<CR>%s<CR>', > > > > \ set, a:option, a:option, a:1, a:1) > > > > elseif type == 4 " string > > > > let rhs = printf(':%s %s<C-R>=&%s == "%s" ? "&" : "=%s"<CR><CR>', > > > > \ set, a:option, a:option, a:1, a:1) > > > > endif > > > > exe 'nnoremap co' . a:letter rhs > > > > endfunc > > > > > > > > NMapChangeOption c colorcolumn +1 > > > > NMapChangeOption! h hlsearch > > > > NMapChangeOption l list > > > > NMapChangeOption! p paste > > > > NMapChangeOption s spell > > > > NMapChangeOption w wrap > > > > NMapChangeOption y syntax ON > > > > > > > > The patch includes tests and docs. > > > > > > I can see how this would be useful. But returning just a number is > > > limited. There are many more properties of an option, such as whether > > > it is window-local, was set or not, can be set from a modeline, etc. > > > Not that we need to add all those properties now, but I'm sure someone > > > will want to add them later. Perhaps using "optionproperties()" and > > > returning a Dictionary? > > > > Great feedback. Attached is a revised patch with you ideas applied. > > For now the 'optionproperties()' function returns a Dictionary with only > > one entry called 'type'. > > Thanks. I wonder if "type" would just return bool/number/string. Then > for a string type there would be a subtype for comma/flaglist. > I suppose it depends on what you want to do if you want to know what > kind of string option it is. Also, if we later add another kind (colon > separate?) that is also a string, it would still be possible to > recognize the string if you don't care about the subtype.
It guess it makes sense to assume that in the general use-case one is only interested of the primitive type of a option, therefore bool/number/string is sufficient. The attached patch adds two new entries to the returned dictionary: 'comma' and 'flaglist'. -- :wq -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 642f0ad..a6df0cf 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2023,6 +2023,7 @@ mode( [expr]) String current editing mode mzeval( {expr}) any evaluate |MzScheme| expression nextnonblank( {lnum}) Number line nr of non-blank line >= {lnum} nr2char( {expr}[, {utf8}]) String single char with ASCII/UTF8 value {expr} +optionproperties( {option}) Dict properties of option {option} or( {expr}, {expr}) Number bitwise OR pathshorten( {expr}) String shorten directory names in a path perleval( {expr}) any evaluate |Perl| expression @@ -5316,6 +5317,21 @@ nr2char({expr}[, {utf8}]) *nr2char()* characters. nr2char(0) is a real NUL and terminates the string, thus results in an empty string. + *E518* +optionproperties({option}) *optionproperties()* + Return the properties of {option} as a dictionary with the + following entries: + + comma 1 if {option} is a comma separated list, 0 + otherwise + flaglist 1 if {option} is a list of single-char flags, + 0 otherwise + type Boolean: 0 + Number: 1 + String: 2 + + If {option} does not exist, a empty dictionary is returned. + or({expr}, {expr}) *or()* Bitwise OR on the two arguments. The arguments are converted to a number. A List, Dict or Float argument causes an error. diff --git a/src/eval.c b/src/eval.c index 2256589..0fecf0a 100644 --- a/src/eval.c +++ b/src/eval.c @@ -683,6 +683,7 @@ static void f_mzeval(typval_T *argvars, typval_T *rettv); static void f_nextnonblank(typval_T *argvars, typval_T *rettv); static void f_nr2char(typval_T *argvars, typval_T *rettv); static void f_or(typval_T *argvars, typval_T *rettv); +static void f_optionproperties(typval_T *argvars, typval_T *rettv); static void f_pathshorten(typval_T *argvars, typval_T *rettv); #ifdef FEAT_PERL static void f_perleval(typval_T *argvars, typval_T *rettv); @@ -8367,6 +8368,7 @@ static struct fst {"nextnonblank", 1, 1, f_nextnonblank}, {"nr2char", 1, 2, f_nr2char}, {"or", 2, 2, f_or}, + {"optionproperties",1, 1, f_optionproperties}, {"pathshorten", 1, 1, f_pathshorten}, #ifdef FEAT_PERL {"perleval", 1, 1, f_perleval}, @@ -15917,6 +15919,46 @@ f_or(typval_T *argvars, typval_T *rettv) } /* + * "optionproperties(option)" function + */ + static void +f_optionproperties(typval_T *argvars, typval_T *rettv) +{ + char_u *p; + int flags; + int type; + + if (rettv_dict_alloc(rettv) == FAIL) + return; + + p = get_tv_string_chk(&argvars[0]); + flags = get_option_flags(p); + if (flags == -1) { + EMSG(_("E518: Unknown option")); + return; + } + + if (flags & P_BOOL) + type = 0; + else if (flags & P_NUM) + type = 1; + else if (flags & P_STRING) + type = 2; + else + type = 2; /* type unknown, assume string */ + if (dict_add_nr_str(rettv->vval.v_dict, "type", type, NULL) == FAIL) + return; + + if (dict_add_nr_str(rettv->vval.v_dict, "comma", + flags & P_COMMA || flags & P_ONECOMMA, NULL) == FAIL) + return; + + if (dict_add_nr_str(rettv->vval.v_dict, "flaglist", + (flags & P_FLAGLIST) == P_FLAGLIST, NULL) == FAIL) + return; +} + +/* * "pathshorten()" function */ static void diff --git a/src/option.c b/src/option.c index 8a706af..58727a2 100644 --- a/src/option.c +++ b/src/option.c @@ -410,50 +410,6 @@ struct vimoption #define VI_DEFAULT 0 /* def_val[VI_DEFAULT] is Vi default value */ #define VIM_DEFAULT 1 /* def_val[VIM_DEFAULT] is Vim default value */ -/* - * Flags - */ -#define P_BOOL 0x01 /* the option is boolean */ -#define P_NUM 0x02 /* the option is numeric */ -#define P_STRING 0x04 /* the option is a string */ -#define P_ALLOCED 0x08 /* the string option is in allocated memory, - must use free_string_option() when - assigning new value. Not set if default is - the same. */ -#define P_EXPAND 0x10 /* environment expansion. NOTE: P_EXPAND can - never be used for local or hidden options! */ -#define P_NODEFAULT 0x40 /* don't set to default value */ -#define P_DEF_ALLOCED 0x80 /* default value is in allocated memory, must - use vim_free() when assigning new value */ -#define P_WAS_SET 0x100 /* option has been set/reset */ -#define P_NO_MKRC 0x200 /* don't include in :mkvimrc output */ -#define P_VI_DEF 0x400 /* Use Vi default for Vim */ -#define P_VIM 0x800 /* Vim option, reset when 'cp' set */ - - /* when option changed, what to display: */ -#define P_RSTAT 0x1000 /* redraw status lines */ -#define P_RWIN 0x2000 /* redraw current window */ -#define P_RBUF 0x4000 /* redraw current buffer */ -#define P_RALL 0x6000 /* redraw all windows */ -#define P_RCLR 0x7000 /* clear and redraw all */ - -#define P_COMMA 0x8000 /* comma separated list */ -#define P_ONECOMMA 0x18000L /* P_COMMA and cannot have two consecutive - * commas */ -#define P_NODUP 0x20000L /* don't allow duplicate strings */ -#define P_FLAGLIST 0x40000L /* list of single-char flags */ - -#define P_SECURE 0x80000L /* cannot change in modeline or secure mode */ -#define P_GETTEXT 0x100000L /* expand default value with _() */ -#define P_NOGLOB 0x200000L /* do not use local value for global vimrc */ -#define P_NFNAME 0x400000L /* only normal file name chars allowed */ -#define P_INSECURE 0x800000L /* option was set from a modeline */ -#define P_PRI_MKRC 0x1000000L /* priority for :mkvimrc (setting option has - side effects) */ -#define P_NO_ML 0x2000000L /* not allowed in modeline */ -#define P_CURSWANT 0x4000000L /* update curswant required; not needed when - * there is a redraw flag */ - #define ISK_LATIN1 (char_u *)"@,48-57,_,192-255" /* 'isprint' for latin1 is also used for MS-Windows cp1252, where 0x80 is used @@ -12244,3 +12200,19 @@ get_bkc_value(buf_T *buf) { return buf->b_bkc_flags ? buf->b_bkc_flags : bkc_flags; } + +/* + * Get the flags of an option. + * Returns -1 when the option is unknown. + */ + int +get_option_flags(char_u *name) +{ + int opt_idx; + + opt_idx = findoption(name); + if (opt_idx == -1) + return -1; + else + return options[opt_idx].flags; +} diff --git a/src/option.h b/src/option.h index cf7ba04..518f20b 100644 --- a/src/option.h +++ b/src/option.h @@ -11,6 +11,50 @@ */ /* + * Flags + */ +#define P_BOOL 0x01 /* the option is boolean */ +#define P_NUM 0x02 /* the option is numeric */ +#define P_STRING 0x04 /* the option is a string */ +#define P_ALLOCED 0x08 /* the string option is in allocated memory, + must use free_string_option() when + assigning new value. Not set if default is + the same. */ +#define P_EXPAND 0x10 /* environment expansion. NOTE: P_EXPAND can + never be used for local or hidden options! */ +#define P_NODEFAULT 0x40 /* don't set to default value */ +#define P_DEF_ALLOCED 0x80 /* default value is in allocated memory, must + use vim_free() when assigning new value */ +#define P_WAS_SET 0x100 /* option has been set/reset */ +#define P_NO_MKRC 0x200 /* don't include in :mkvimrc output */ +#define P_VI_DEF 0x400 /* Use Vi default for Vim */ +#define P_VIM 0x800 /* Vim option, reset when 'cp' set */ + + /* when option changed, what to display: */ +#define P_RSTAT 0x1000 /* redraw status lines */ +#define P_RWIN 0x2000 /* redraw current window */ +#define P_RBUF 0x4000 /* redraw current buffer */ +#define P_RALL 0x6000 /* redraw all windows */ +#define P_RCLR 0x7000 /* clear and redraw all */ + +#define P_COMMA 0x8000 /* comma separated list */ +#define P_ONECOMMA 0x18000L /* P_COMMA and cannot have two consecutive + * commas */ +#define P_NODUP 0x20000L /* don't allow duplicate strings */ +#define P_FLAGLIST 0x40000L /* list of single-char flags */ + +#define P_SECURE 0x80000L /* cannot change in modeline or secure mode */ +#define P_GETTEXT 0x100000L /* expand default value with _() */ +#define P_NOGLOB 0x200000L /* do not use local value for global vimrc */ +#define P_NFNAME 0x400000L /* only normal file name chars allowed */ +#define P_INSECURE 0x800000L /* option was set from a modeline */ +#define P_PRI_MKRC 0x1000000L /* priority for :mkvimrc (setting option has + side effects) */ +#define P_NO_ML 0x2000000L /* not allowed in modeline */ +#define P_CURSWANT 0x4000000L /* update curswant required; not needed when + * there is a redraw flag */ + +/* * Default values for 'errorformat'. * The "%f|%l| %m" one is used for when the contents of the quickfix window is * written to a file. diff --git a/src/proto/option.pro b/src/proto/option.pro index d0ba4ec..f7044da 100644 --- a/src/proto/option.pro +++ b/src/proto/option.pro @@ -63,4 +63,5 @@ long get_sw_value(buf_T *buf); long get_sts_value(void); void find_mps_values(int *initc, int *findc, int *backwards, int switchit); unsigned int get_bkc_value(buf_T *buf); +int get_option_flags(char_u *name); /* vim: set ft=c : */ diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 98cf985..bce23b8 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -175,6 +175,7 @@ NEW_TESTS = test_arglist.res \ test_increment.res \ test_json.res \ test_langmap.res \ + test_optionproperties.res \ test_packadd.res \ test_perl.res \ test_quickfix.res \ diff --git a/src/testdir/test_optionproperties.vim b/src/testdir/test_optionproperties.vim new file mode 100644 index 0000000..3f68f2f --- /dev/null +++ b/src/testdir/test_optionproperties.vim @@ -0,0 +1,20 @@ +" Test for the optionproperties function. +function Test_optionproperties() + call assert_equal({'type': 0, 'comma': 0, 'flaglist': 0}, + \ optionproperties('antialias')) + call assert_equal({'type': 1, 'comma': 0, 'flaglist': 0}, + \ optionproperties('cmdheight')) + call assert_equal({'type': 2, 'comma': 1, 'flaglist': 0}, + \ optionproperties('backspace')) + call assert_equal({'type': 2, 'comma': 1, 'flaglist': 0}, + \ optionproperties('belloff')) + call assert_equal({'type': 2, 'comma': 0, 'flaglist': 1}, + \ optionproperties('breakat')) + call assert_equal({'type': 2, 'comma': 0, 'flaglist': 0}, + \ optionproperties('ambiwidth')) + try + call optionproperties('unknown') + catch + call assert_exception('E518:') + endtry +endfunction