Chinaunix首页 | 论坛 | 博客
  • 博客访问: 46670
  • 博文数量: 3
  • 博客积分: 105
  • 博客等级: 民兵
  • 技术积分: 122
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-12 20:12
文章分类

全部博文(3)

文章存档

2012年(3)

我的朋友

分类: WINDOWS

2012-10-20 12:06:37

1.事件起因:
      继前一博文所述,本人开始了VIM的学习历程,前两天在使用c.vim插件时,注释对齐快捷键(\cj adjust end-of-line)老是有问题,会无故增加其它字符。故又开始了一次新的调试,也有这一篇博文记录。
2.事件分析:
      按照经验来说,像这种使用了这么长时间的插件,肯定不应该有这么明显的问题。那是什么造成了笔者使用过程中的问题呢?
      a) 插件源码没有改动
      b) 笔者只是配置了_vimrc
      这样看来,故障源很明显,就是与_vimrc中的配置有关。
      以上分析其实是事后诸葛亮,呵呵,由于笔者的_vimrc来源于网络上号称最强大的配置文件修改而来,当然有些配置涉及到的细节根本就不是很清楚,也就造成了这个使用问题,也与c.vim的源码有关。
3.源码分析:
      其实这个函数还是比较简单,虽然笔者也不清楚vim插件是什么代码编写,但有c语言基础以及vim中强大的帮助文档,还是可以分析一下的。下面我们来看一下插件源码。
      第一步:确定源文件位置搜索
      笔者插件源码位置 d:\tools\Vim\vimfiles\plugin\c.vim,请根据自己的安装目录进行相应查找。
      第二步:确定源码位置
      在该文件中搜索cj但可找到如下图位置,可以看到这个快捷键调用的函数是C_AdjustLineEndComm
      
      第三步:找到调用函数进行分析,函数源码如下所示,这个函数主要分为三个部分。
     a) 保存当前位置信息
     b) 根据判断条件,决定是插入空格还是删除空格
     c) 恢复位置信息
     我们的问题主要出在插入空格时,所以重点关注插入空格的代码,即英文注释处的try to ajust comment中insert some spaces这部分。

点击(此处)折叠或打开

  1. " C_AdjustLineEndComm: adjust line-end comments {{{1
  2. "------------------------------------------------------------------------------
  3. "
  4. " C comment or C++ comment:
  5. let s:c_cppcomment= '\(\/\*.\{-}\*\/\|\/\/.*$\)'
  6. C_AdjustLineEndComm ( ) range
  7. "
  8. if !exists("b:C_LineEndCommentColumn")
  9. let b:C_LineEndCommentColumn = s:C_LineEndCommColDefault
  10. endif
  11. let save_cursor = getpos(".")
  12. let save_expandtab = &expandtab
  13. exe ":set expandtab"
  14. let linenumber = a:firstline
  15. exe ":".a:firstline
  16. while linenumber <= a:lastline
  17. let line= getline(".")
  18. " line is not a pure comment but contains one
  19. "
  20. if match( line, '^\s*'.s:c_cppcomment ) < 0 && match( line, s:c_cppcomment ) > 0
  21. "
  22. " disregard comments starting in a string
  23. "
  24. let idx1 = -1
  25. let idx2 = -1
  26. let commentstart= -2
  27. let commentend = 0
  28. while commentstart < idx2 && idx2 < commentend
  29. let start = commentend
  30. let idx2 = match( line, s:c_cppcomment, start )
  31. let commentstart= match ( line, '"[^"]\+"', start )
  32. let commentend = matchend( line, '"[^"]\+"', start )
  33. endwhile
  34. "
  35. " try to adjust the comment
  36. "
  37. let idx1 = 1 + match( line, '\s*'.s:c_cppcomment, start )
  38. let idx2 = 1 + idx2
  39. call setpos(".", [ 0, linenumber, idx1, 0 ] )
  40. let vpos1 = virtcol(".")
  41. call setpos(".", [ 0, linenumber, idx2, 0 ] )
  42. let vpos2 = virtcol(".")
  43. if ! ( vpos2 == b:C_LineEndCommentColumn
  44. \ || vpos1 > b:C_LineEndCommentColumn
  45. \ || idx2 == 0 )
  46. exe ":.,.retab"
  47. " insert some spaces
  48. if vpos2 < b:C_LineEndCommentColumn
  49. let diff = b:C_LineEndCommentColumn-vpos2
  50. call setpos(".", [ 0, linenumber, vpos2, 0 ] )
  51. let @" = ''
  52. exe "normal ".diff."P"
  53. endif
  54. " remove some spaces
  55. if vpos1 < b:C_LineEndCommentColumn && vpos2 > b:C_LineEndCommentColumn
  56. let diff = vpos2 - b:C_LineEndCommentColumn
  57. call setpos(".", [ 0, linenumber, b:C_LineEndCommentColumn, 0 ] )
  58. exe "normal ".diff."x"
  59. endif
  60. endif
  61. endif
  62. let linenumber=linenumber+1
  63. normal j
  64. endwhile
  65. "
  66. " restore tab expansion settings and cursor position
  67. let &expandtab = save_expandtab
  68. call setpos('.', save_cursor)
  69. endfunction " ---------- end of function C_AdjustLineEndComm ----------
    最终插入空格使用的是什么命令呢?是如下两句。第一句是设置vim中无名寄存器的值为空格,第二名是调用P命令进行空格粘贴,diff是需要粘贴的次数。
  1. let @" = ''
  2. exe "normal ".diff."P"

      OK,找到插入空格的代码了,看上去有没有问题?说实话,笔者当时明白代码编写者的意图,就是要添加diff个空格到一个指定行,它设置寄存器""是为了想给P(粘贴命令)用的,但笔者不明白为什么要用这个寄存器呢? 不明白的地方怎么办?查help.

:help P

                                                                       *P*
["x]P   Put the text [from register x] before the cursor
   [count] times.  {Vi: no count}

      a) 首先查看P的帮助,它就是从寄存器x粘贴内容。看源码这一块应该是想用寄存器",那么这个寄存器有什么用呢?再查help.

:help registers

     1. Unnamed register ""    *quote_quote* *quotequote*
Vim fills this register with text deleted with the "d", "c", "s", "x" commands
or copied with the yank "y" command, regardless of whether or not a specific
register was used (e.g.  "xdd).  This is like the unnamed register is pointing
to the last used register.  Thus when appending using an uppercase register
name, the unnamed register contains the same text as the named register.
An exception is the '_' register: "_dd does not store the deleted text in any
register.
Vim uses the contents of the unnamed register for any put command (p or P)
which does not specify a register.  Additionally you can access it with the
name '"'.  This means you have to type two double quotes.  Writing to the ""
register writes to register "0.
{Vi: register contents are lost when changing files, no '"'}

      b) 可以看到这个无名寄存器是用于存储(d,c,x,x)操作过程中的内容,可用于P或p进行内容粘贴。

4.错误定位:
      到了这一步,看上去源码没有问题,P或p默认是用""这个寄存器的内容,那现在是这个情况吗?笔者配置的_vimrc会修改这种属性吗?查看_vimrc与粘贴相的配置项只有一个。是的,这个配置为了保证vim与windows系统间可以相互拷贝将p或P的默认寄存器有成了"*,
       " clipboard with windows
       set clipboard+=unnamed
5.测试验证
      好了,我们可以验证一下P或p在上述配置下,是取的那个寄存器的值呢?
      :let @* = 'c'
      然后在Normal模式下输入P或p,是不是在当前光标位置粘贴了一个字母c呢?
6.问题修改:
      笔者修改方案是修改了c.vim源码
      将
           let @"=' '
      替换为
           let @*=' '
7.网络资源:
      关于paste
 
     
 

 
     
阅读(2329) | 评论(0) | 转发(0) |
0

上一篇:snipMate.vim在gvim(windows)中不起作用分析

下一篇:没有了

给主人留下些什么吧!~~