IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Emacs自虐

    Yukang (moorekang@gmail.com)发表于 2010-08-21 00:00:00
    love 0
    无意中用了一下C#,发现VS下面有一个功能还是非常好的,就是每次按下回车键盘的时候,都可以把刚刚输入的那行代码自动排版一下, 看起来要清晰一些。比如
    int a=0;                       ==>  int a = 0;
    struct Node* p=&node;          ==> struct Node* p = &node;
    a+=b;                          ==>  a += b;
    int *p=&a;                     ==>  int *p = &a;
    int a=b+c+d+f;                 ==>  int a = b + c + d + f;
    for(a=0,b=0;a<10;a++)          ==>  for(a = 0, b=0; a< 10; a++)
    if(a==b)                       ==>  if(a == b)
    if(pbuf!=0)                    ==>  if(a != b)
    fwrite(buf,1,size,fp);         ==>  fwrite(buf, 1, size, fp);
    printf("%d %s\n",len,buf);     ==>  printf("%d %s\n", len, buf); //引号内的不变,引号外的","后面加空格
    if(p>=allocbuf&&p; if(p >= allocbuf && p < buf + size)
    return (b!=0)?gcd_ver2(b,a%b):a;  ==> return (b != 0) ? gcd_ver2(b, a % b) : a;
    
    同时要注意的情况,还有些情况下我不想让符号两边加空格:
    #include        //< > 两边不加
    
    printf("%d%d%d\n",n,m,k);//这个%两边不加 检测是否在引号内部
    a++;                     //不加空格
    int *p;                  //不加空格
    return manip(*this);     //这个*两边不加 找到*前面或者后面是否为(
    strcpy(mode,"w+");       //引号里面的不变 检测是否在引号内部
    
    我以前写代码习惯都不加空格,感觉不加要写得快一些,可是这不是个很好的习惯。linux下有indent这样的工具,不过是针对于最后完成的源程序来排版。在写程序的过程中像赋值操作符两边加上空格会显得比较清晰,Emacs里面好像还没这么个插件,那我来折腾一下自己写了一个。原来还是比较复杂的。应该好好学学正则表达式,这就是一个正则匹配和替换的过程。呜,括号看得头都晕呼呼的,不过还好,最终有这么一个东西用起来比较顺手了。 首先定一个关键字和替换列表:
    (setq beautifly-line-list
          '(
            ("+" . " + ")
            ("-" . " - ")
            ("=" . " = ")
            ("*" . " * ")
            ("/" . " / ")
            ("%" . " % ")
            ("<" . " < ")
            (">" . " > ")
            ("," . ", ")
            ("+=" . " += ")
            ("*=" . " *= ")
            ("/=" . " /= ")
            ("%=" . " %= ")
            ("==" . " == ")))
    
    一个用来测试dest是否为上面关键字的函数,后面用char-after来获取一个point的字符,对应的是asci码。
    (defun test-valid(dest)
      (interactive)
      (if(or (equal dest 43)
             (equal dest 45)
             (equal dest 42)
             (equal dest 47)
             (equal dest 37)
             (equal dest 62)
             (equal dest 60)) ;;<
          t
        nil))
    
    ;;打印出当前位置的字符 调试用
    (defun print-pos-char ()
      (interactive)
      (setq value (char-after (point)))
      (print value))
    
    ;;从point-pos位置开始 到这一行的尾部,检测是否有",即检测是否在" "内部
    (defun test-in-quote (point-pos)
      (interactive)
      (move-end-of-line 1)
      (setq end-pos (point))
      (goto-char point-pos)
      (setq ret-value nil)
      (if (search-forward "\"" end-pos t)
          (setq ret-value t)
        )
      (goto-char point-pos)
      ret-value)
    
    ;;这个函数先调用我的排版函数,然后调用原来的new-line-and-indent
    (defun my-new-line-and-beautyfly ()
      (interactive)
      (beautifly-line)
      (newline-and-indent))
    
    ;;在my-c-mode-common-hook下面加上这么一句,表示把回车键绑定在上面那个函数上。
      (define-key c-mode-base-map [(return)] 'my-new-line-and-beautyfly)
    
    下面就剩下这两个函数了,写的太过复杂,可惜不会用高级一点的正则表达式,所以显得不好看。其想法比较简单,按照上面那个列表,一次查找,我要找一个两员操作符,其两边都是空格,在其两边加上空格,注意排除掉++,—操作。然后识别+=,-=,*=等符号,再两边加上空格。用起来还可以。逐渐写了些elisp,感觉特别适合自底向上的方式进行,通过一些小函数,逐步累积成一个功能,再最后只用一个上层函数来调用这个功能。每个小函数除了返回结果不改变函数外的其他变量(无副作用)。同时写一个小的函数可以马上写一个测试函数,保证其正确无误。 最后bueatifly_line的代码有点点长,不贴咯。


沪ICP备19023445号-2号
友情链接