佳音的博客

2007/12/27

VIM的几个操作实例

Filed under: Uncategorized — 佳音 @ 2:10 下午

1:在VIM当中要对所编辑的文件进行简单加密
在VIM当中对所编辑的文件进行简单加密,可以在命令行模式下键入“:X”,然后在提示“Enter the encrypt key”时输入口令字串就可以加密了。但是不要忘了保存!保存的时候会发现在屏幕底部有“[crypted]”这样的字样。下次打开该加密文件会要求您输入口令字串。

2:重复输入同一字符
有时,我们可能想多次输入同一字符,VIM的插入功能可以很好的完成这项工作
命令 80i=^ESC 一次可以输入80个字符= ,当然,80a=^ESC 也可以完成上述功能。
请注意:此处的^ESC表示键盘左上方上的ESC键。

3:在文件中置入行号

工作中,我们有时希望把行号置入文件中,而VIM提供的功能 :set nu 只能显示行号,不能编辑或将其置入文件当中,下面的宏命令脚本row_num.vim可以完成此项功能。

:%s/^/^I/ 每一行的行首添加一个TAB字符
:$ 到文件的末行
:let end=line(“.”) 末行的行号 ==〉变量 END,函数line的功能是取得指定行的行号,此处参数”.”表示当前行
:1 到文件的首行
“——————————————
:let num=1 1 ==〉计数器
:while num<=end
:let line=getline(“.”) 取当前行的内容 ==〉变量 LINE
:let line=substitute(line,$,num,”") 在变量 LINE 的前面置入行号
:call setline(“.”,line) 将变量 LINE 的内容写回当前行
:+ 下移一行
:let num=num+1 计数器加一
:endwhile 循环执行,直到文件结束
“——————————————

4:将文件名插入文件中
在编辑状态下,使用Ctrl+R %来输入你正在编辑的文件名。

5: 用VIM编写C/C++程序
Vi是Unix下最常用的文本编辑器。VIM(Vi IMproved)则是它的增强版。有人常常拿VIM和emacs比较,VIM尽管不象emacs那样有那么多的功能,但是比emacs更方便、好用。用过emacs的人肯定会为emacs的一些快捷键感到烦恼,有时候用真希望自己有八只手。VIM的学习曲线也不象emacs那么长,只要看看VIM自带的vitutor,大约只要20分钟就能掌握VIM的用法。对于Unix下的C/C++的程序员,我推荐你们使用VIM+Ctags的组合来写程序。其中原因听我慢慢道来。(下面对VIM的介绍主要是针对5.6以后的版本)

VIM支持语法制导和自动缩进
VIM会根据文件的后缀名,如:*.c、*.cpp、*.cc,等,自动设置语法制导(Syntax Highlighting)。C/C++中的一些保留字,如:if、for、include,等等,就会有不同的颜色,这样就会减少程序员犯错的可能,阅读程序的时候相对来说也轻松很多。用下面这些命令在VIM中查看有关语法制导的帮助:“:h syntax”、“:h syn-qstart”、“:h syntax-printing”。

VIM也支持根据GNU的风格自动缩进,这样程序员编写出来的代码就更易阅读,而且也有利于培养好的编程风格。用下面这些命令在VIM中查看有关自动缩进的帮助:“:h cindent”、“:h cinoptions”、“:h cinoptions-values”、“:h cinkeys”、“:h cinwords”。

使用Ctags
VIM中已经带了Ctags这个程序。尽管ctags也可以支持其它编辑器,但是它正式支持的只有VIM。Ctags可以帮助程序员很容易地浏览源代码。用下面的命令可以在源代码的根目录下创建“tags”文件:

[/home/brimmer/src]$ ctags -R

“-R”表示递归创建,也就包括源代码根目录下的所有子目录下的源程序。“tags”文件中包括这些对象的列表:

l 用#define定义的宏

l 枚举型变量的值

l 函数的定义、原型和声明

l 名字空间(namespace)

l 类型定义(typedefs)

l 变量(包括定义和声明)

l 类(class)、结构(struct)、枚举类型(enum)和联合(union)

l 类、结构和联合中成员变量或函数

VIM用这个“tags”文件来定位上面这些做了标记的对象,下面介绍一下定位这些对象的方法:

1) 用命令行。在运行vim的时候加上“-t”参数,例如:

[/home/brimmer/src]$ vim -t foo_bar

这个命令将打开定义“foo_bar”(变量或函数或其它)的文件,并把光标定位到这一行。

2) 在vim编辑器内用“:ta”命令,例如:

:ta foo_bar

3) 最方便的方法是把光标移到变量名或函数名上,然后按下“Ctrl-]”。用“Ctrl-o”退回原来的地方。

注意:运行vim的时候,必须在“tags”文件所在的目录下运行。否则,运行vim的时候还要用“:set tags=”命令设定“tags”文件的路径,这样vim才能找到“tags”文件。

快速改正错误
在VIM编辑器的环境下用“:make”就可以编译程序,当然其前提是在当前目录下有Makefile文件。运行完“:make”之后,如果程序中有错误,就会显示出来。这时候,光标会自动指向第一个出现错误的地方,而且你还可以看到错误的提示。然后,你就可以改正错误,而不用手工找到出错的那一行。记住下面几个有用的命令:

l “:cl”列出错误

l “:cn”让光标指向下一个错误

l “:cp”让光标指向上一个错误

l “:cnew”从头开始

你甚至可以让VIM识别出其它编译器而不是gcc的错误提示。这对一些开发嵌入式系统的程序员这很有用,因为他们很可能用的不是gcc而是其它编译器。通过设置“errorformat”的值,可以让VIM识别出编译器的出错提示。因为不同的编译器的出错提示是不同的,所以如果用的不是gcc就要重新设置。

“errorformat”的值是一个字符串,它的格式和C语言的scanf的字符串格式相识。

gcc的“errorformat”的值为:%f:%l:\%m。其中“%f”表示文件名,“%l”表示行号,“%m”表示出错信息。

用“:h errorformat”查看详细的帮助信息。

用“:h quickfix”、“:h make”、“:h makeprg”、“:h errorfile”查看其它的信息。

有用的快捷键
下面的这些快捷键对程序员很有帮助:

在函数中移动光标
[[ 转到上一个位于第一列的“{”

]] 转到下一个位于第一列的“{”

{ 转到上一个空行

} 转到下一个空行

gd 转到当前光标所指的局部变量的定义

* 转到当前光标所指的单词下一次出现的地方

# 转到当前光标所指的单词上一次出现的地方

括号的匹配
% 用来进行小括号、中括号和大括号的匹配。这要看当前光标指向的是什么符号了。

其它
VIM的配置文件是“.vimrc”,用这个文件可以配置VIM。VIM的图形界面的版本叫gvim。VIM也有用于Windows平台的版本。

版权说明
这个技巧的版权属于作者brimmer(brimmer@linuxaid.com.cn)和www.linuxaid.com.cn

6:自动补齐
这个技巧在你写程序是十分的有用,在编辑状态下使用Ctrl+N就可以了,当然你要先输入前面的一小部分,如果不是你可以重复使用
Ctrl+N来选择正确的匹配,当你的程序变量十分长时,该命令就显得很有用出了。

7:对一段文字进行排序
例如,有下面一段文字
version.o
pch.o
getopt.o
util.o
getopt1.o
inp.o
patch.o
backupfile.o
你想要对他们进行排序,按照字母顺序
通过以下几部可以做到:
a:移动光标到想要排序的那一行
b:使用ma标志改行为a
c:移动光标到想要排序的最后一行
d:使用指令”!’asort”,来完成排序(注意这些步骤都是在非输入模式下进行的。)下面解释一下各个的用途。”!”表示将要执行指令,”‘a”表示从当前行道标志为a的行,’sort’是执行的指令。

]]>

Vim的折叠功能

Filed under: Uncategorized — 佳音 @ 2:00 下午

作者:haijd

折行的用处:

  • 创建折行进行大纲预览
  • 移动到某处进行编辑
  • 使用jzij打开文本进行编辑
  • 编辑完毕后再用jzij打开折行进行移动

打开vim的折叠功能,请在 “~/.vimrc” 中加入 “:set foldmethod=marker”,使用vim默认的折叠标签进行处理。使用方法如下:

1、加折叠标签

在normal模式下,从键盘输入zf并回车,您就会看到折叠在一起的两行标签如下:

/*{{{*/
.....这里输入您 的程序代码
/*}}}*/

2、输入程序代码后,将代码折叠起来使用如下命令(normal模式):

zc 回车

3、打开折叠的程序有以下几种方法

  1. 在折叠的行上移动光标
  2. 在normal模式下输入zo并回车

4、给一段文字加折行(normal 模式)

zfap

5、zr命令可以打开折叠几层的内容 zm使用内容折叠的更多一些(多层折叠操作时可反复使用)。

6、嵌套了多层的折行, 也可以用zR命令一次打开所有折行

7、关闭所有的嵌套折行使用zM

8、可以用jznj命令来禁用一个折行. 然后用jzNj还可以恢复它. jzij命令则可以在两者之间切换.

其它的请参考vim的使用手

]]>

Comments (0)

2007/12/21

python 去utf-8 bom

Filed under: Uncategorized — 佳音 @ 11:41 上午

#!/usr/bin/python
#-*- coding: utf-8 -*-
import os
import codecs
import time

from sys import *

__trim_ext_array__ = (“php”, “js”)

def trimBom(filename):

Comments (0)

2007/12/19

python多线程[http://www.faydu.cn/blog/post/27.html]

Filed under: Uncategorized — 佳音 @ 11:56 上午

从三个方面来考虑 1实现 2 同步 3 通讯

1实现 :主要是从thread或threading两种方式,

def run(num):

Comments (0)

2007/12/17

本月某人发表文章的日期

Filed under: Uncategorized — 佳音 @ 11:52 上午

SELECT DISTINCT date( created_at ) AS ‘est_date’
FROM `clip`
WHERE `created_at` > DATE_SUB( NOW( ) , INTERVAL DAYOFMONTH( NOW( ) )
DAY )
AND `channel_id` = ‘xxxx’
LIMIT 0 , 30

这个是在 基数 为 250643 channel_id 建索引的情况下查询的结果

查询花费 0.0006 秒(时间比较经济)

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE clip ref channel_id channel_id 4 const 24 Using where; Using temporary

]]>

Comments (0)

2007/12/12

javascript 内存管理 避免内存泄漏 [ajax in action]

Filed under: Uncategorized — 佳音 @ 1:44 下午

任何程序都有可能发生内存“泄漏”(即申请了系统内存并且在工作完成后没有释放),并且对于使用非托管语言(unmanaged languages)(如C语言)的开发者来说,内存的分配和释放是一个主要的关注点。JavaScript是一种内存托管(memory-managed)的语言,垃圾回收过程能够帮助程序员自动地处理内存的分配和释放。该机制解决了大部分困扰的非托管代码的问题,但是,认为内存托管语言不会产生内存泄漏却是错误的。

垃圾回收进程尝试推断何时可以安全地回收不再使用的变量,通常是通过判定程序是否能够通过变量之间形成的引用网络到达该变量。当确信变量是不可达的,就在它上面标上可以回收的记号,并且在回收器的下一次清理中(可能在未来的任意时刻)释放相关的内存。在托管语言中产生内存泄漏非常简单:只需使用完变量而忘记解除引用。

我们来考虑一个简单的例子,其中定义了一个描述家庭宠物及其主人的对象模型。首先看看主人,以Person对象描述:

function Person(name){

this.name=name;

this.pets=new Array();

}

一个主人可以养一只或者多只宠物。当主人得到了一只宠物,他告诉宠物现在自己是它的主人:

Person.prototype.addPet=function(pet){

this.pets[pet.name]=pet;

if (pet.assignOwner){

Comments (0)

惰性函数定义模式 【realazy】

Filed under: Uncategorized — 佳音 @ 12:43 下午

这篇文章阐述的是一种函数式编程(functional-programming)设计模式,我称之为惰性函数定义(Lazy Function Definition)。我不止一次发现这种模式在JavaScript中大有用处,尤其是编写跨浏览器的、高效运行的库之时。

热身问题

编写一个函数foo,它返回的是Date对象,这个对象保存的是foo首次调用的时间。

方法一:上古时代的技术

这个最简陋的解决方案使用了全局变量t来保存Date对象。foo首次调用时会把时间保存到t中。接下来的再次调用,foo只会返回保存在t中的值。

var t;
function foo() {
    if (t) {
        return t;
    }
    t = new Date();
    return t;
}

但是这样的代码有两个问题。第一,变量t是一个多余的全局变量,并且在 foo调用的间隔期间有可能被更改。第二,在调用时这些代码的效率并没有得到优化因为每次调用 foo都必须去求值条件。虽然在这个例子中,求值条件并不显得低效,但在现实世界的实践例子中常常会有极为昂贵的条件求值,比如在if-else-else-…的结构中。

方法二:模块模式

我们可以通过被认为归功于CornfordCrockford模块模式来弥补第一种方法的缺陷。使用闭包可以隐藏全局变量t,只有在 foo内的代码才可以访问它。

var foo = (function() {
    var t;
    return function() {
        if (t) {
            return t;
        }
        t = new Date();
        return t;
    }
})();

但这仍然没有优化调用时的效率,因为每次调用foo依然需要求值条件。

虽然模块模式是一个强大的工具,但我坚信在这种情形下它用错了地方。

方法三:函数作为对象

由于JavaScript的函数也是对象,所以它可以带有属性,我们可以据此实现一种跟模块模式质量差不多的解决方案。

function foo() {
    if (foo.t) {
        return foo.t;
    }
    foo.t = new Date();
    return foo.t;
}

在一些情形中,带有属性的函数对象可以产生比较清晰的解决方案。我认为,这个方法在理念上要比模式模块方法更为简单。

这个解决方案避免了第一种方法中的全局变量t,但仍然解决不了foo每次调用所带来的条件求值。

方法四:惰性函数定义

现在,这是你阅读这篇文章的理由:

var foo = function() {
    var t = new Date();
    foo = function() {
        return t;
    };
    return foo();
};

foo首次调用,我们实例化一个新的Date对象并重置 foo到一个新的函数上,它在其闭包内包含Date对象。在首次调用结束之前,foo的新函数值也已调用并提供返回值。

接下来的foo调用都只会简单地返回t保留在其闭包内的值。这是非常快的查找,尤其是,如果之前那些例子的条件非常多和复杂的话,就会显得很高效。

弄清这种模式的另一种途径是,外围(outer)函数对foo的首次调用是一个保证(promise)。它保证了首次调用会重定义foo为一个非常有用的函数。笼统地说,术语“保证” 来自于Scheme的惰性求值机制(lazy evaluation mechanism)。每一位JavaScript程序员真的都应该学习Scheme,因为它有很多函数式编程相关的东西,而这些东西会出现在JavaScript中。

确定页面滚动距离

编写跨浏览器的JavaScript, 经常会把不同的浏览器特定的算法包裹在一个独立的JavaScript函数中。这就可以通过隐藏浏览器差异来标准化浏览器API,并让构建和维护复杂的页面特性的JavaScript更容易。当包裹函数被调用,就会执行恰当的浏览器特定的算法。

在拖放库中,经常需要使用由鼠标事件提供的光标位置信息。鼠标事件给予的光标坐标相对于浏览器窗口而不是页面。加上页面滚动距离鼠标的窗口坐标的距离即可得到鼠标相对于页面的坐标。所以我们需要一个反馈页面滚动的函数。演示起见,这个例子定义了一个函数getScrollY。因为拖放库在拖拽期间会持续运行,我们的getScrollY必须尽可能高效。

不过却有四种不同的浏览器特定的页面滚动反馈算法。Richard Cornford在他的feature detection article文章中提到这些算法。最大的陷阱在于这四种页面滚动反馈算法其中之一使用了 document.body. JavaScript库通常会在HTML文档的加载,与此同时docment.body并不存在。所以在库载入的时候,我们并不能使用特性检查(feature detection)来确定使用哪种算法。

考虑到这些问题,大部分JavaScript库会选择以下两种方法中的一种。第一个选择是使用浏览器嗅探navigator.userAgent,为该浏览器创建高效、简洁的getScrollY. 第二个更好些的选择是getScrollY在每一次调用时都使用特性检查来决定合适的算法。但是第二个选择并不高效。

好消息是拖放库中的getScrollY只会在用户与页面的元素交互时才会用到。如果元素业已出现在页面中,那么document.body也会同时存在。getScrollY的首次调用,我们可以使用惰性函数定义模式结合特性检查来创建高效的getScrollY.

var getScrollY = function() {

    if (typeof window.pageYOffset == 'number') {
        getScrollY = function() {
            return window.pageYOffset;
        };

    } else if ((typeof document.compatMode == 'string') &&
               (document.compatMode.indexOf('CSS') >= 0) &&
               (document.documentElement) &&
               (typeof document.documentElement.scrollTop == 'number')) {
        getScrollY = function() {
            return document.documentElement.scrollTop;
        };

    } else if ((document.body) &&
               (typeof document.body.scrollTop == 'number')) {
      getScrollY = function() {
          return document.body.scrollTop;
      }

    } else {
      getScrollY = function() {
          return NaN;
      };

    }

    return getScrollY();
}

总结

惰性函数定义模式让我可以编写一些紧凑、健壮、高效的代码。用到这个模式的每一次,我都会抽空赞叹JavaScript的函数式编程能力。

JavaScript同时支持函数式和面向对象便程。市面上有很多重点着墨于面向对象设计模式的书都可以应用到JavaScript编程中。不过却没有多少书涉及函数式设计模式的例子。对于JavaScript社区来说,还需要很长时间来积累良好的函数式模式。

原文:Lazy Function Definition Pattern. 转载没有我的信息没有关系,但你一定得写上原文信息,谢谢。

更新

这个模式虽然有趣,但由于大量使用闭包,可能会由于内存管理的不善而导致性能问题。来自FCKeditor的FredCK改进了getScrollY,既使用了这种模式,也避免了闭包:

var getScrollY = function() {

    if (typeof window.pageYOffset == 'number')
        return (getScrollY = getScrollY.case1)();

    var compatMode = document.compatMode;
    var documentElement = document.documentElement;

    if ((typeof compatMode == 'string') &&
               (compatMode.indexOf('CSS') >= 0) &&
               (documentElement) &&
               (typeof documentElement.scrollTop == 'number'))
        return (getScrollY = getScrollY.case2)();

    var body = document.body ;
    if ((body) &&
               (typeof body.scrollTop == 'number'))
        return (getScrollY = getScrollY.case3)();

    return (getScrollY = getScrollY.case4)();
};

getScrollY.case1 = function() {
    return window.pageYOffset;
};

getScrollY.case2 = function() {
    return documentElement.scrollTop;
};

getScrollY.case3 = function() {
    return body.scrollTop;
};

getScrollY.case4 = function() {
        return NaN;
};

]]>

Comments (0)

.bind()之美 [来自 realazy]

Filed under: Uncategorized — 佳音 @ 12:41 下午

我并不是 Prototype JavaScript framework的忠实粉丝,但我对它的总体代码质量印象深刻。具体而言,它为Function对象增加一个简洁的补充,对我管理函数呼叫执行后的上下文产生了极大的正面影响:bindcall一样执行相同的常见任务,改变函数执行的上下文。不同之处在于bind返回的是函数引用可以备用,而不是call的立即执行而产生的最终结果。

如果需要简化一下bind函数以抓住概念的重点,我们可以先把它插进前面讨论的乘积例子中去,看它究竟是如何工作的。这是一个相当优雅的解决方案:

首先,我们定义了first_object, second_objectmultiply函数,一如既往。细心处理这些后,我们继续为Function对象的prototype定义一个bind方法,这样的话,我们程序里的函数都有一个bind方法可用。当执行multiply.bind(first_object)时,JavaScript为bind方法创建一个运行上下文,把this置为multiply函数的引用,并把第一个参数obj置为first_object的引用。目前为止,一切皆顺。

这个解决方案的真正天才之处在于method的创建,置为this的引用所指(即multiply函数自身)。当下一行的匿名函数被创建,method通过它的作用域链访问,obj亦然(不要在此使用this, 因为新创建的函数执行后,this会被新的、局部的上下文覆盖)。这个this的别名让apply执行multiply函数成为可能,而传递obj则确保上下文的正确。用计算机科学的话说,temp是一个闭包(closure),它可以保证,需要在first_object的上下文中执行multiplybind呼叫的最终返回可以用在任何的上下文中。

这才是前面说到的事件处理函数和setTimeout情形所真正需要的。以下代码完全解决了这些问题,绑定deep_thought.ask_question方法到deep_thought的上下文中,因此能在任何事件触发时都能正确运行:

function addhandler() {
 var deep_thought = new BigComputer(42),
  the_button = document.getElementById('thebutton');

 the_button.onclick = deep_thought.ask_question.bind(deep_thought);
}

漂亮。

]]>

Comments (0)

2007/12/11

js 数据结构简析

Filed under: Uncategorized — 佳音 @ 10:37 下午

这里简单介绍几个函数
Array.prototype.shift();
Array.prototype.push();
Array.prototype.pop();
Array.prototype.length;
这几个函数或属性 足可以模拟数据结构中的栈和队列
hoho
不知道js里面有没有匿名的内存空间

]]>

Comments (0)

2007/12/10

apache mod_proxy 安装

Filed under: Uncategorized — 佳音 @ 12:34 下午

在Linux系统下,需要给已经运行的Apache增加mod_proxy模块,编译的时候应该这样:

apxs -c -i mod_proxy.c proxy_util.c

否则你可能会收到这样的错误信息

如果还需要其他proxy模块如mod_proxy_http、mod_proxy_ftp,则单独

apxs -c -i proxy_http.c
apxs -c -i proxy_ftp.c

]]>

Comments (0)
Older Posts »

Powered by 00RZ