Re: Operator pending mode

2007-11-04 Fir de Conversatie Ben Schmidt
[CCing vim_dev; apologies for my continued disorganised postings!]

OK, folks,

After reading feedback, etc., here is a revised patch. It's just the 
documentation
that is different from the previous patch.

In the end, given that a number of things can be done without v:operator, as 
Andy
demonstrated, and that Yankring is a pretty specific example, I thought perhaps
the best thing would be to put a brief example analogous to the v:prevcount
example which is right nextdoor in the docs.

If you still think a lengthier example is better, though, Bram, I'm happy to
revise the patch again. I thought this, or a scaled-down count-ignorant version
might be a more useful lengthy example (compared to the function name thing I
suggested before):

: Defines a motion/text-object C which allows you to operate on
: the {count}th column of a tab-delimited table, or the column
: the cursor is currently in if no count is given.
:onoremap C Esc:call OperateColumn()CR
:function! OperateColumn()
:  let c = v:prevcount
:  if c == 0
:call search('^\|\t\zs','bc',line(.))
:  else
:call cursor(line(.),1)
:while search('\v(\zs[^\t]*(\t|$)){'.c.'}','c',line(.)) == 0
:  call setline(line(.),getline(line(.)).\t)
:endwhile
:  endif
:  call feedkeys(''.v:register.v:operator)
:  if strpart(getline(line('.')),col('.')-1,1) == \t
:call feedkeys(:\CR)
:  else
:call feedkeys(search('\t','n',line(.)) == 0 ? $ : t\t)
:  endif
:endfun

Ben.







--~--~-~--~~~---~--~~
You received this message from the vim_dev maillist.
For more information, visit http://www.vim.org/maillist.php
-~--~~~~--~~--~--~---

Index: runtime/doc/eval.txt
===
--- runtime/doc/eval.txt(revision 621)
+++ runtime/doc/eval.txt(working copy)
@@ -1401,10 +1401,20 @@
This is the screen column number, like with |virtcol()|.  The
value is zero when there was no mouse button click.
 
+   *v:operator* *operator-variable*
+v:operator The last operator given in Normal mode. This is a single
+   character except for commands starting with g or z,
+   in which case it is two characters. Best used alongside
+   |v:prevcount| and |v:register|. Useful if you want to cancel
+   Operator-pending mode and then use the operator. 
+   :omap O Esc:call MyMotion(v:operator)CR
+  Read-only.
+
*v:prevcount* *prevcount-variable*
 v:prevcountThe count given for the last but one Normal mode command.
This is the v:count value of the previous command.  Useful if
-   you want to cancel Visual mode and then use the count. 
+   you want to cancel Visual or Operator-pending mode and then
+   use the count. 
:vmap % Esc:call MyFilter(v:prevcount)CR
   Read-only.
 
Index: src/vim.h
===
--- src/vim.h   (revision 607)
+++ src/vim.h   (working copy)
@@ -1688,7 +1688,8 @@
 #define VV_MOUSE_WIN   49
 #define VV_MOUSE_LNUM   50
 #define VV_MOUSE_COL   51
-#define VV_LEN 52  /* number of v: vars */
+#define VV_OP  52
+#define VV_LEN 53  /* number of v: vars */
 
 #ifdef FEAT_CLIPBOARD
 
Index: src/eval.c
===
--- src/eval.c  (revision 607)
+++ src/eval.c  (working copy)
@@ -345,6 +345,7 @@
 {VV_NAME(mouse_win,   VAR_NUMBER), 0},
 {VV_NAME(mouse_lnum,  VAR_NUMBER), 0},
 {VV_NAME(mouse_col,   VAR_NUMBER), 0},
+{VV_NAME(operator,VAR_STRING), VV_RO},
 };
 
 /* shorthand */
@@ -17260,6 +17261,35 @@
 }
 
 /*
+ * Set v:operator if needed.
+ */
+void
+set_op_var(optype)
+intoptype;
+{
+/* This will either be two operator characters, or one and a NUL. */
+char_u opchars[2];
+
+if (optype == OP_NOP)
+{
+   set_vim_var_string(VV_OP, NULL, 0);
+   return;
+}
+
+opchars[0] = get_op_char(optype);
+if (opchars[0] == 'g' || opchars[0] == 'z')
+   opchars[1] = get_extra_op_char(optype);
+else
+   opchars[1] = 0;
+
+/* Avoid free/alloc when the value is already right. */
+if (vimvars[VV_OP].vv_str == NULL ||
+   vimvars[VV_OP].vv_str[0] != opchars[0] ||
+   vimvars[VV_OP].vv_str[1] != opchars[1])
+   set_vim_var_string(VV_OP, opchars, opchars[1]==0?1:2);
+}
+
+/*
  * Get or set v:exception.  If oldval == NULL, return the current value.
  * Otherwise, restore the value to oldval and return NULL.
  * Must always be called 

Re: Operator pending mode

2007-10-31 Fir de Conversatie Bram Moolenaar


Ben Schmidt wrote:

  Well, I can see that you get the information, but this is not really a
  useful real-world example.  Think of a user that wants to get something
  done for which v:operator is needed.  And for which there is no other
  solution.
 
 Here's a somewhat naively implemented example where a custom
 text-object is defined that allows you to operate on a function name
 whether the cursor is on the name itself or on its arguments. You can
 yank with yF, change with cF, uppercase with gUF, etc. I can't think
 of any other way to do this, or more complicated language-based custom
 text-object definition--e.g. yank/change a whole conjunction or
 disjunction in a logic language, yank or change the condition of an
 'if' or 'while' loop from anywhere within its body. Some of these
 would be more useful than others, of course, but there are a lot of
 real world possibilities, I think.
 
 Ben.
 
 
 :onoremap F Esc:call OperateFunctionName()CR
 function! OperateFunctionName()
   let last_count = v:count
   let last_op = v:operator
   let last_reg = v:register
   exe normal \Esc
   while search('\(\%#\i\|\i\s*\%#\)\i*\s*(','ce',line('.')+1) == 0
   normal [(
   endwhile
   exe normal \BS\_yiw
   echo 'normal '.(last_count0?(last_count):'').''.last_reg.last_op.'e'
 endfun

I see.  In general the reason we need v:operator would then be that you
need it for situations where you need to get out of operator pending
mode, move around and restart the operator.

Did you copy the v:variable values because they change when executing
the other commands?  A remark about that will be useful in the docs.

OK, I'll include the patch after sufficient testing.

-- 
hundred-and-one symptoms of being an internet addict:
70. ISDN lines are added to your house on a hourly basis

 /// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net   \\\
///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\download, build and distribute -- http://www.A-A-P.org///
 \\\help me help AIDS victims -- http://ICCF-Holland.org///

--~--~-~--~~~---~--~~
You received this message from the vim_dev maillist.
For more information, visit http://www.vim.org/maillist.php
-~--~~~~--~~--~--~---



Re: Operator pending mode

2007-10-31 Fir de Conversatie Bram Moolenaar


David Fishburn wrote:

   This is very useful for me, but I suspect other plugin developers will
   also benefit since they can make smarter functions by looking at what
   the user has keyed in.
 
  Well, I can see that you get the information, but this is not really a
  useful real-world example.  Think of a user that wants to get something
  done for which v:operator is needed.  And for which there is no other
  solution.
 
 
 This is as real as it gets, using omaps there is no other solution
 that I or this list could find.
 
 The echo was just an FYI to the user, but my function is replaying the
 command the user typed so that I can later act on the effects of the
 command:
 exec normal! .
\ ((v:count  0)?(v:count):'').
\ (v:register==''?'':''.v:register).
\ v:operator.
\ cmd
 
 Without v:operator, anyone who is writing an omap is hamstrung.  omap
 lets me define (or redefine) a motion.  But without the context of the
 command (in this case I don't know whether the user is yanking,
 deleting or changing).  Vim provides all the other information except
 this one piece of critical data (basically the same thing showcmd
 displays in the statusline).  omaps can be much more useful than they
 currently are.
 
 In my real world plugin I will be creating an omap for every motion
 Vim supports.  That way I have the opporunity to record changes made
 by Vim and the user.  The YankRing is missing a lot of functionality
 at the moment since I cannot support change commands (and quite a few
 others) but omaps can provide the missing link, but they are
 essentially useless without providing the intent of the user.
 c,d,y provides that context.

Well, if you show us the omap for one command that would be the
example I was asking for.  Leaving out some of the YankRing stuff
perhaps to keep it small.

-- 
hundred-and-one symptoms of being an internet addict:
69. Yahoo welcomes you with your own start page

 /// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net   \\\
///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\download, build and distribute -- http://www.A-A-P.org///
 \\\help me help AIDS victims -- http://ICCF-Holland.org///

--~--~-~--~~~---~--~~
You received this message from the vim_dev maillist.
For more information, visit http://www.vim.org/maillist.php
-~--~~~~--~~--~--~---



Re: Operator pending mode

2007-10-30 Fir de Conversatie [EMAIL PROTECTED]

On Oct 30, 1:38 pm, Bram Moolenaar [EMAIL PROTECTED] wrote:
 Ben Schmidt wrote:
   3.  Don't know about v:operator (works for me), the showcmd option
   means it could also be v:command or v:operatorcommand (since there is
...
 I'm not quite convinced adding v:operator is useful.  What would help is
 giving a couple of examples how it's used.  Also, in the docs for
 v:operator it would be good to have a few examples of the values.  I
 suppose it can be one char, like d, but also something longer.  How
 about the count, e.g., when I do 4d?

Here is a simple example:

function! MyOp(op)
   let cmd = a:op
   echo 'v:count:' v:count 'v:register:' v:register 'v:operator'
v:operator 'you pressed:' cmd
   exec normal! .
   \ ((v:count  0)?(v:count):'').
   \ (v:register==''?'':''.v:register).
   \ v:operator.
   \ cmd
endfunction

omap w :call MyOp('w')CR
omap e :call MyOp('e')CR
omap $ :call MyOp('$')CR

If you type the following commands:
c$
2yw
a3de

You will get the following output:
v:count: 0 v:register:  v:operator c you pressed: $
v:count: 2 v:register:  v:operator y you pressed: w
v:count: 3 v:register: a v:operator d you pressed: e

What this provides is all the information to capture what the user
pressed which Vim does not currently support.

In the YankRing case, I will be able to replay what the user typed and
still manage to capture the registers.

This is very useful for me, but I suspect other plugin developers will
also benefit since they can make smarter functions by looking at what
the user has keyed in.

Dave


--~--~-~--~~~---~--~~
You received this message from the vim_dev maillist.
For more information, visit http://www.vim.org/maillist.php
-~--~~~~--~~--~--~---



Re: Operator pending mode

2007-10-30 Fir de Conversatie David Fishburn

On 10/30/07, Bram Moolenaar [EMAIL PROTECTED] wrote:

 David Fishburn wrote:

  On Oct 30, 1:38 pm, Bram Moolenaar [EMAIL PROTECTED] wrote:
   Ben Schmidt wrote:
 3.  Don't know about v:operator (works for me), the showcmd option
 means it could also be v:command or v:operatorcommand (since there is
  ...
   I'm not quite convinced adding v:operator is useful.  What would help is
   giving a couple of examples how it's used.  Also, in the docs for
   v:operator it would be good to have a few examples of the values.  I
   suppose it can be one char, like d, but also something longer.  How
   about the count, e.g., when I do 4d?
 
  Here is a simple example:
 
  function! MyOp(op)
 let cmd = a:op
 echo 'v:count:' v:count 'v:register:' v:register 'v:operator'
  v:operator 'you pressed:' cmd
 exec normal! .
 \ ((v:count  0)?(v:count):'').
 \ (v:register==''?'':''.v:register).
 \ v:operator.
 \ cmd
  endfunction
 
  omap w :call MyOp('w')CR
  omap e :call MyOp('e')CR
  omap $ :call MyOp('$')CR
 
  If you type the following commands:
  c$
  2yw
  a3de
 
  You will get the following output:
  v:count: 0 v:register:  v:operator c you pressed: $
  v:count: 2 v:register:  v:operator y you pressed: w
  v:count: 3 v:register: a v:operator d you pressed: e
 
  What this provides is all the information to capture what the user
  pressed which Vim does not currently support.
 
  In the YankRing case, I will be able to replay what the user typed and
  still manage to capture the registers.
 
  This is very useful for me, but I suspect other plugin developers will
  also benefit since they can make smarter functions by looking at what
  the user has keyed in.

 Well, I can see that you get the information, but this is not really a
 useful real-world example.  Think of a user that wants to get something
 done for which v:operator is needed.  And for which there is no other
 solution.


This is as real as it gets, using omaps there is no other solution
that I or this list could find.

The echo was just an FYI to the user, but my function is replaying the
command the user typed so that I can later act on the effects of the
command:
exec normal! .
   \ ((v:count  0)?(v:count):'').
   \ (v:register==''?'':''.v:register).
   \ v:operator.
   \ cmd

Without v:operator, anyone who is writing an omap is hamstrung.  omap
lets me define (or redefine) a motion.  But without the context of the
command (in this case I don't know whether the user is yanking,
deleting or changing).  Vim provides all the other information except
this one piece of critical data (basically the same thing showcmd
displays in the statusline).  omaps can be much more useful than they
currently are.

In my real world plugin I will be creating an omap for every motion
Vim supports.  That way I have the opporunity to record changes made
by Vim and the user.  The YankRing is missing a lot of functionality
at the moment since I cannot support change commands (and quite a few
others) but omaps can provide the missing link, but they are
essentially useless without providing the intent of the user.
c,d,y provides that context.

Dave

--~--~-~--~~~---~--~~
You received this message from the vim_dev maillist.
For more information, visit http://www.vim.org/maillist.php
-~--~~~~--~~--~--~---



Re: Operator pending mode

2007-10-30 Fir de Conversatie Ben Schmidt

 Well, I can see that you get the information, but this is not really a
 useful real-world example.  Think of a user that wants to get something
 done for which v:operator is needed.  And for which there is no other
 solution.

Here's a somewhat naively implemented example where a custom text-object is 
defined that allows you to operate on a function name whether the cursor is on 
the 
name itself or on its arguments. You can yank with yF, change with cF, 
uppercase 
with gUF, etc. I can't think of any other way to do this, or more complicated 
language-based custom text-object definition--e.g. yank/change a whole 
conjunction 
or disjunction in a logic language, yank or change the condition of an 'if' or 
'while' loop from anywhere within its body. Some of these would be more useful 
than others, of course, but there are a lot of real world possibilities, I 
think.

Ben.



:onoremap F Esc:call OperateFunctionName()CR
function! OperateFunctionName()
let last_count = v:count
let last_op = v:operator
let last_reg = v:register
exe normal \Esc
while search('\(\%#\i\|\i\s*\%#\)\i*\s*(','ce',line('.')+1) == 0
normal [(
endwhile
exe normal \BS\_yiw
echo 'normal '.(last_count0?(last_count):'').''.last_reg.last_op.'e'
endfun





Send instant messages to your online friends http://au.messenger.yahoo.com 


--~--~-~--~~~---~--~~
You received this message from the vim_dev maillist.
For more information, visit http://www.vim.org/maillist.php
-~--~~~~--~~--~--~---