九天雁翎的博客
如果你想在软件业获得成功,就使用你知道的最强大的语言,用它解决你知道的最难的问题,并且等待竞争对手的经理做出自甘平庸的选择。 -- Paul Graham

Qt/PyQt的系统托盘图标(SystemTrayIcon)实现

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

估计这种小的知识会有几篇文章,除了全局快捷键部分外,其他的都比较简单,都是我实现“onekeycodehighlighter"

中碰到的一些小问题,这里顺便整理一下。事实上,稍微懂一点的人,去看看one key code highlighter的源代码都能明白了。这里相当于将其详细的剖析一下。。。。。。。另外,实现上用Python+PyQt,事实上,主要的部分是对Qt的一些类的使用,所以其实看懂了C++的Qt中使用上是一样的。啥?你看不懂Python?好的,这就是我为什么靠C++吃饭,却学习JAVA,JavaScript,Lua,Python,Bash的一个原因,不然你看不懂别人在写啥-_-!(当然,我基本上也就学到能看懂)
对于pyQt完全不懂的,这里也不用看了,《pyqt
的学习(1) 入门


》,《pyqt
(2) 对话框...


》可以看看,但是写的有点乱,因为那时候我懂得也少(不代表现在就懂的多了)

SystemTrayIcon在官方的Demo中有一个示例,(那些示例有些可真酷啊!)位置在Desktop->System Tray中。该示例展示了大部分需要用到的内容。包括实现TrayIcon,显示气泡信息,TrayIcon的菜单等等。

创建系统系统托盘图标(TrayIcon)

主要用到的类是QtGui.QSystemTrayIcon。
图标用QtGui.QIcon类来表示,可以以文件名字符串为构造函数的参数。如:

icon = QtGui.QIcon('jt.png
')

然后用QtGui.QSystemTrayIcon的


setIcon(icon) 去完成系统TrayIcon的创建。OK,已经完成80%了,图标已经出来了。

气泡信息

再然后呢?希望有特定的气泡信息?

QtGui.QSystemTrayIcon的showMessage
可以完成。

菜单

再然后呢?希望有菜单?这个稍微复杂点,在Qt中,菜单是一个一个的Action,如下建立Action:


        self.quitAction = QtGui.QAction("&Quit
", self,
                                        triggered=QtGui.qApp.quit)
        
        self.aboutAction = QtGui.QAction("&About
", self,
                                        triggered=self.about)
注意上述Action的triggerd参数,实际上是一个Callable的回调函数,意思是点击此菜单时进行的操作。
然后将Action添加进某个Menu



self.trayIconMenu = QtGui.QMenu(self)

self.trayIconMenu.addAction(self.aboutAction)
self.trayIconMenu.addAction(self.quitAction)
然后将Menu

关联上TrayIcon
self.trayIcon.setContextMenu(self.trayIconMenu)

完成了。

 

CheckBox菜单

 

我的需求更加复杂一点,希望有可以Check的菜单,当然,这个需求已经超出SystemTrayIcon相关的需求了,与Qt中的菜单有关。

将需要实现成Check菜单的所有命令添加到一个Action组中,在Qt中称为QActionGroup。



        self.synGroup = QtGui.QActionGroup(self)
        
        for

 syn in

 config.syntaxSupport:
            action = QtGui.QAction(syn, self, checkable=True,
                triggered=self.setSyn)
            self.synGroup.addAction(action)

 

需要注意的是,每个Action的checkable参数设为True,表示是CheckBox类型的菜单。
通过某个Action的setChecked来选中,比如:

        actions = self.synGroup.actions()


        if

 len(actions) != 0:
            actions[0].setChecked(True)

主要注意的是,在Qt中QActionGroup返回的是一个QList的列表,但是在PyQt已经将其转换为Python中原生的list了,这样更加符合Python的使用习惯,当然,调用方法的时候也需要注意一下了,接口可是不同的,感谢RiverBank(PyQt的创造维护公司)伟大的工作,对于可怜的RiverBank我其实还有话要说,以后再详述吧。
具体哪个菜单选项被Check了,通过


checkedAction = self.synGroup.checkedAction()
来查询,返回的是被Check的Action,此时假如你是通过Action的字符串来查询的话,(比如我)那么调用Action的text

函数获取。

一切都结束了。。。。。。。需要注意几个特别的地方:
1。官方的教程中,有
QtGui.QApplication.setQuitOnLastWindowClosed(False)
这样一句,大概的意思是在应用程序所有窗口都关闭的时候不关闭应用程序,事实上,就我试验,无论是设为True,还是False,都不管关。。。。。。原因不明。
2。在应用程序利用QtGui.qApp.quit关闭后,TrayIcon其实还不会自动消失,直到你的鼠标移动到上面去后,才会消失,这是个问题,(如同你terminate一些带TrayIcon的应用程序时出现的状况),这种问题的解决我是通过在程序退出前将其setVisible(False)来完成的。

 

 

 

 

完整源代码获取说明

由于篇幅限制,本文一般仅贴出代码的主要关心的部分,代码带工程(或者makefile)完整版(如果有的话)都能用Mercurial在Google Code中下载。文章以博文发表的日期分目录存放,请直接使用Mercurial克隆下库:

https://onekeycodehighlighter.googlecode.com/hg/

Mercurial使用方法见《分布式的,新一代版本控制系统Mercurial的介绍及简要入门

要是仅仅想浏览全部代码也可以直接到google code上去看,在下面的地址:

http://code.google.com/p/onekeycodehighlighter/source/browse/

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

阅读全文....

Qt/PyQt中操作系统剪贴板(clipboard)

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

估计这种小的知识会有几篇文章,除了全局快捷键部分外,其他的都比较简单,都是我实现onekeycodehighlighter"中碰到的一些小问题,这里顺便整理一下。事实上,稍微懂一点的人,去看看one key code highlighter的源代码都能明白了。这里相当于将其详细的剖析一下。。。。。。。另外,实现上用Python+PyQt,事实上,主要的部分是对Qt的一些类的使用,所以其实看懂了C++的Qt中使用上是一样的。啥?你看不懂Python?好的,这就是我为什么靠C++吃饭,却学习JAVA,JavaScript,Lua,Python,Bash的一个原因,不然你看不懂别人在写啥-_-!(当然,我基本上也就学到能看懂)
对于pyQt完全不懂的,这里也不用看了,《pyqt的学习(1) 入门》,《pyqt(2) 对话框...》可以看看,但是写的有点乱,因为那时候我懂得也少(不代表现在就懂的多了)

概述

系统剪贴板的操作在Qt中有原生的支持,这点很强大,操作起来比Windows本身附带的要简单的多,更重要的是,这是跨平台的。
Windows中的剪贴板其实很简单,只有一种,就是你选择然后CTRL-C的那一个。在Vim中用寄存器"+"存储,(不懂就算了)。Linux中剪贴板有两种,一种是鼠标选中后立刻就生效的,在Vim中用寄存器"+"存储,称作select剪贴板,另外一种就是类似Windows下的那种剪贴板,vim中用寄存器"*"存储。
剪贴板作为应用程序中较为通用的一种共享数据的方式,应用较为广泛,就我所知,这好像是唯一一种用户可以很方便操作的应用程序共享数据的途径,其他的如Socket等,编程的时候是很容易实现,用户要操作就难了。

操作

简单的剪贴板操作,很简单,Qt中用QClipboard类来表示
在Qt中用
 clipboard = QtGui.QApplication.clipboard()
获取到剪贴版的对象,然后用text表示获取到文本数据,(类似CTRL-P),用setText来设置文本数据。(类似CTRL-C)

更深入的操作

对于普通的文本操作,这两个函数就足够了。以前我也是这样做的。但是,我发现一个现象,那就是复制网页上的数据后,在Google Document上paste的时候,是直接可以复原原来的网页内容的(虽然常常有些偏差),但是我转换后的HTML源码是用setText设置到剪贴板中的话,paste出来的就是源码,说明肯定里面还有蹊跷,要是我的转换工具,直接粘贴就可以在Google Document中出现语法高亮过的文字多好啊,于是我查看了一下QClipboard类,及MSDN。果然,在剪贴板中保存的不仅仅是文字,还可以是一些有格式的内容,在windows中可以保存OLE的东西。。。。Qt中将其统一划分为MimeData。
看看QMimedata这个类就会很惊喜,包括了HTML,Image等很多的东西,当然我要的就是HTML。
于是乎,我通过
mimeData = QtCore.QMimeData()
mimeData.setHtml(clipboard.text())
clipboard.setMimeData(mimeData)

来设置一个转换过的HTML源码,此时就能直接在Google Document上通过粘贴来得到高亮过的代码了:)
但是,在语法文本源代码的地方此时的粘贴就无效了,因为已经没有文本了,经过试验,Qt中不同的数据时相互不影响的,于是再改了一下:


def setClipboardMimeToHTML():
    clipboard = QtGui.QApplication.clipboard()
    mimeData = QtCore.QMimeData()
    mimeData.setText(clipboard.text())
    mimeData.setHtml(clipboard.text())
    clipboard.setMimeData(mimeData)

哈哈,能够粘贴HTML的地方,显示的就是HTML,只能显示文本的地方,粘贴的即是HTML的源码。好不强大,这也就是最后,你们在onekeycodehighlighter" 中实际使用的效果。
总之,我是对自己做的这个工具很满意了:)

完整源代码获取说明

由于篇幅限制,本文一般仅贴出代码的主要关心的部分,代码带工程(或者makefile)完整版(如果有的话)都能用Mercurial在Google Code中下载。文章以博文发表的日期分目录存放,请直接使用Mercurial克隆下库:

https://onekeycodehighlighter.googlecode.com/hg/

Mercurial使用方法见《分布式的,新一代版本控制系统Mercurial的介绍及简要入门

要是仅仅想浏览全部代码也可以直接到google code上去看,在下面的地址:

http://code.google.com/p/onekeycodehighlighter/source/browse/

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

Python与C之间的相互调用(Python C API及Python ctypes库)

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

我实现onekeycodehighlighter
"


中碰到的一些小问题,需要实现全局快捷键,但是是事实上Qt并没有对全局快捷键提供支持,那么用Qt的话就只能通过Win32Api来完成了,而我,用的是PyQt,还需要用Python来调用win32 API,事实上,都没有什么难的。

因为Python如此的流行,导致,开源社区按照自己的爱好,对于Python与C之间互相调用上,各自开发了自己想要的调用方式,其中包括用Python C API来完成,包括ctypes这个Python标准库,还有那一大堆的各式各样的绑定方案如SIP,Boost::Python等,要知道,Python流行到什么程序,Boost库号称C++准标准库,唯一对C++以外的一种语言提供了支持,那就是Python,Python还是Symbian除C++,JAVA外支持的第3种语言,当年在原来的公司,我还一直以为Python是个新鲜的小玩意儿,要我鼓捣Python C API的时候很新鲜,(事实上原公司的确没有用Python的人)到了新公司一看,啊~~~公司只允许使用3中语言,C++,JAVA,还有Python,而大家对Python那都是驾轻就熟,信手拈来,常用来开发一些工具及脚本,呵呵,世界原来与我想象的并不同。
这里将以前工作中用到的Python C API知识,及最近用到的ctypes库的知识梳理一下。

Python C API

此部分可以参考我原来的文章《python
c
api
使用心得...


》,这里只是会有一些实际的例子,原来那是一个大概流程的描述。
某年某月,在我开始学习Python古老的岁月中(我不是倚老卖老啊)。。。。ctypes还不存在,那时候我们都是老实的用C语言,调用Python C
API来完成从Python中调用C语言函数的任务,我学习Python的时候还在想,哈哈哈哈哈,我以前学过C/C++,我可以很熟练的调用
Python C API来完成Python调用Win32 API这样的任务,我多了不起啊:)这个时候的感觉就像,嘿,Python你不是了不起吗。。。。还不是没有办法逃离C语言的魔掌。。。。此时,画面中出现的是K&R嘿嘿嘿嘿的冷笑。。。。Guido van Rossum在他们脚下抱着头哭了。。。。。。。
那时候,情况大概是这样的:

准备工作:

闲话少说,看看Python C API。事实上,Python C API比起Lua的API了来说,清晰了很多,这也符合Pythonic的风格,就算这时Python C API是设计给C语言使用者使用的,还是这样的风格,比起Lua API那种汇编式的接口,(据说为了效率,可以直接操作每个数据)强了太多了。
要使用Python C API,用普通的二进制包是不行的,得下源码包。这里我用3.1.1的源码包为例:Source Distribution

Python的源码在Windows的版本中已经完全换到VS2008了,直接用VS2008打开在PCbuild目录下的工程即可,对于VS2005及以前的用户打开PC目录下的其他版本工程。我们编译debug版本的pythoncore会得到python31_d.lib,python31_d.dll两个文件,需要的头文件在Include目录下,还需要将pyconfig.h文件从PCBuild目录下拷贝到Include中,(硬要直接指定也可以)这样准备工作就已经齐了。

Python C API有两个方向的使用方式,从C中调用Python脚本及利用C扩展Python。
先讲简单的从C中调用Python,也就是常说的在C中内嵌Python。

C中内嵌Python

新建立一个工程,首先需要将工作目录设置到Python-3.1.1PCbuild中,以获取到动态库,至于静态库的包含,Include目录的指定,那自然也是少不了的。文件中需要包含Python.h文件,这也是必须的。
接口中
    Py_Initialize();
    Py_Finalize();
一对的调用是必须的,一个用于初始化Python的动态库,一个用于释放。释放时会输出[31818 refs],意义不明。

PyRun_SimpleString

可用于执行简单的Python语句。如下:



#include
"python.h"

int

 main(int

 argc, char

* argv[])
{
    Py_Initialize();

    PyRun_SimpleString("print(
"
Hello World
"
)"
);
    Py_Finalize();

    system("PAUSE"
);
    return

 0
;
}

 

此时,输出为:

Hello World
[31829 refs]
请按任意键继续. . .

 

此时可以执行一些Python语句了,并且,特别需要注意的是,在一个Py_Initialize();与Py_Finalize();之间,Python语句执行是在同一个执行环境中,不懂什么意思?看个示例就知道了。



int

 main(int

 argc, char

* argv[])
{
    Py_Initialize();

    PyRun_SimpleString("str =
"
Hello World
"
"
);
    PyRun_SimpleString("print(str)"
);

    Py_Finalize();

    system("PAUSE"
);
    return

 0
;
}

此例与上例输出是一样的,懂我的意思了吧?意思就是以前执行的语句对后面的语句是有效的,相当于在同一个交互式命令行中顺序执行语句。

获取返回值

PyRun_SimpleString有的缺点,文档中的描述是:

Returns 0
on success or
-1
if an exception was
raised.

那么你就无法在Python及C语言中传递任何信息。我们需要高级点的函数才行。

 

PyObject* PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
就是干这个的。
但是需要注意的是此函数的一些参数的获取,按照想当然的给他们置空可是不行的,如下例所示:


#include
"python.h"

int

 main(int

 argc, char

* argv[])
{
    Py_Initialize();

    PyRun_SimpleString("x = 10"
);
    PyRun_SimpleString("y = 20"
);
    PyObject* mainModule = PyImport_ImportModule("__main__"
);
    PyObject* dict = PyModule_GetDict(mainModule);
    PyObject* resultObject = PyRun_String("x + y"
, Py_eval_input, dict, dict);

    if

(resultObject)
    {
        long

 result = PyLong_AsLong(resultObject);
        printf("
%d
"
, result);
        Py_DECREF(resultObject);
    }

    Py_Finalize();

    system("PAUSE"
);
    return

 0
;
}
这里我利用了一个知识,那就是
PyRun_SimpleString实际是将所有的代码都放在
__main__

模块中运行,注意啊,没有导入正确的模块及其dict,你会运行失败,失败的很惨。至此,C语言已经于Python来了个交互了。
呵呵,突然觉得深入下去就没有尽头了。。。。。。。还是点到为止吧。
稍微深入点的可以去看《Programming Python》一书。在啄木鸟
上有此书及一些译文。Part VI: Integration 部分Chapter 23. Embedding Python,有相关的知识。

利用C扩展Python

此部分在《Programming Python》的Chapter 22. Extending Python 部分有介绍。
这里也只能开个头了,最多告诉你,其实,这些都没有什么难的。稍微复杂点的情况《python
c
api
使用心得...


》一文中有介绍。
配置上与前面讲的类似,一般来说,利用C扩展Python最后会生成一个动态库,不过这个动态库的后缀会设为.pyd,只有这样,import的时候才会自动的查询到。
另外,为Python写扩展要遵循Python的那套规则,固定的几个命名。
首先看自带的例子:


#include
"Python.h"

static

 PyObject *
ex_foo(PyObject *self, PyObject *args)
{
    printf("Hello, world
n
"
);
    Py_INCREF(Py_None);
    return

 Py_None;
}

static

 PyMethodDef example_methods[] = {
    {"foo"
, ex_foo, METH_VARARGS, "foo() doc string"
},
    {NULL
, NULL
}
};

static

 struct

 PyModuleDef examplemodule = {
    PyModuleDef_HEAD_INIT,
    "example"
,
    "example module doc string"
,
    -1
,
    example_methods,
    NULL
,
    NULL
,
    NULL
,
    NULL

};

PyMODINIT_FUNC
PyInit_example(void

)
{
    return

 PyModule_Create(&examplemodule);
}

这个例子包含了全部C语言为Python写扩展时的基本信息:
1.PyInit_example是最后的出口,其中需要注意的是example不仅仅代表example的意思,还代表了最后生成的库会用example命名,也就是你调用此库会需要使用
import example


的形式。
2.static

 struct

 PyModuleDef examplemodule的存在也是必须的,指定了整个模块的信息,比如上面

的"example module doc string", 模块的说明文字。每个参数的含义上面已经有些演示了。
全部内容可以参考文档中关于PyModuleDef的说明
3.example_methods是一个函数列表,事实上表示此模块中含有的函数。此例中仅含有
foo一个函数。
static

 PyObject *
ex_foo(PyObject *self, PyObject *args)
{
    printf("Hello, world
n
"
);
    Py_INCREF(Py_None);
    return

 Py_None;
}


就是整个函数的具体实现了,此函数表示输出"Hello, world",还是hello world。。。。。。。。这个world还真忙啊。。。。天天有人say hello。

这个Python本身附带的例子有点太简单了,我给出一个稍微复杂点的例子,还是我最喜欢的MessageBox,最后的效果自然还是Hello world。。。。。。。。。。。

#include

static

 PyObject *
MessageBox(PyObject *self, PyObject *args)
{
    LPCSTR lpText;
    LPCSTR lpCaption;
    UINT uType;

    PyArg_ParseTuple(args, "ssi"
, &lpText, &lpCaption, &uType);

    int

 result = MessageBoxA(0
, lpText, lpCaption, uType);

    PyObject* resultObject = Py_BuildValue("
%i
"
, result);

    return

 resultObject;
}

static

 PyMethodDef c_methods[] = {
    {"MessageBox"
, MessageBox, METH_VARARGS, "MessageBox() "
},
    {NULL
, NULL
}
};

static

 struct

 PyModuleDef win32module = {
    PyModuleDef_HEAD_INIT,
    "Win32API"
,
    "Win32 API MessageBox"
,
    -1
,
    c_methods,
    NULL
,
    NULL
,
    NULL
,
    NULL

};

PyMODINIT_FUNC
PyInit_Win32API(void

)
{
    return

 PyModule_Create(&win32module);
}


需要注意的还是需要注意,唯一有点区别的是这里我有从Python中传进来的参数及从C中传出去的返回值了。
PyArg_ParseTuple
用于解析参数
Py_BuildValue 用于构建一个Python的值返回
他们的构建和解析形式有点类似于sprintf等C常见的形式,可是每个字符代表的东西不一定一样,需要注意,文档中比较详细,此例中展示的是String及int的转换。

以生成动态库的方式编译此文件后,并指定为Win32API.pyd文件,然后将其拷贝到Python_d所在的目录(用Python3.1.1源代码生成的调试版本Python),此时import会首先查找*_d.pyd形式的动态库,不然只会搜索release版。
首先看看库的信息:

>>> import Win32API
[44692 refs]
>>> dir(Win32API)
['MessageBox', '__doc__', '__file__', '__name__', '__package__']
[44705 refs]
>>> help(Win32API)
Help on module Win32API:

NAME
    Win32API - Win32 API MessageBox

FILE
    d:python-3.1.1pcbuildwin32api_d.pyd

FUNCTIONS
    MessageBox(...)
        MessageBox()

[68311 refs]
注意到文档的作用了吧?还注意到dir的强大。。。。。。。。。。。。。此时MessageBox已经在Win32API中了,直接调用吧。我这里忽略了窗口的句柄,需要注意。

多么繁忙的World啊。。。。。。。。
此时你会想,太强大了,我要将整个的Win32 API到处,于是Python就能像C/C++语言一样完全操作整个操作系统了,并且,这还是动态的!!!!
没错,不过多大的工作量啊。。。。。。不过,Python这么流行,总是有人做这样的事情的,于是PyWindows出世了。去安装一个,于是你什么都有了。
>>> import win32api
>>> win32api.MessageBox(0, "Great", "Hello World", 0)
1
这样,就能达到上面全部的效果。。。。。。。。。。。

Python ctypes

如此这般,原来Python还是离不开C啊(虽然Python本身使用C写的)。。。,直到。。。。某年某月ctypes横空出世了,于是,完全不懂C语言的人,也可以直接用Python来完成这样的工作了。毫无疑问,Python越来越自成体系了,他们的目标是,没有其他语言!-_-!在Python v3.1.1的文档中如此描述,
ctypes
— A foreign
function library for Python
然后:It can be used to wrap these libraries in pure Python.
注意,他们要的是Pure Python!(我不是想要挑起语言战争。。。。。)
Guido van Rossum开始说,wrap these,in pure Python。。。。不要再用foreign语言,血统不pure的家伙了。

闲话少说,看看ctypes,因为是pure Python嘛,所以看起来很简单,事实上文档也比较详细(当然,还是遗漏了一些细节),下面都以Windows中的Python3.1.1的操作为例:
>>> import ctypes
>>> from ctypes import *
>>> dir(ctypes)
['ARRAY', 'ArgumentError', 'Array', 'BigEndianStructure', 'CDLL', 'CFUNCTYPE', '
DEFAULT_MODE', 'DllCanUnloadNow', 'DllGetClassObject', 'FormatError', 'GetLastEr
ror', 'HRESULT', 'LibraryLoader', 'LittleEndianStructure', 'OleDLL', 'POINTER',
'PYFUNCTYPE', 'PyDLL', 'RTLD_GLOBAL', 'RTLD_LOCAL', 'SetPointerType', 'Structure
', 'Union', 'WINFUNCTYPE', 'WinDLL', 'WinError', '_CFuncPtr', '_FUNCFLAG_CDECL',
 '_FUNCFLAG_PYTHONAPI', '_FUNCFLAG_STDCALL', '_FUNCFLAG_USE_ERRNO', '_FUNCFLAG_U
SE_LASTERROR', '_Pointer', '_SimpleCData', '__builtins__', '__doc__', '__file__'
, '__name__', '__package__', '__path__', '__version__', '_c_functype_cache', '_c
alcsize', '_cast', '_cast_addr', '_check_HRESULT', '_check_size', '_ctypes_versi
on', '_dlopen', '_endian', '_memmove_addr', '_memset_addr', '_os', '_pointer_typ
e_cache', '_string_at', '_string_at_addr', '_sys', '_win_functype_cache', '_wstr
ing_at', '_wstring_at_addr', 'addressof', 'alignment', 'byref', 'c_bool', 'c_buf
fer', 'c_byte', 'c_char', 'c_char_p', 'c_double', 'c_float', 'c_int', 'c_int16',
 'c_int32', 'c_int64', 'c_int8', 'c_long', 'c_longdouble', 'c_longlong', 'c_shor
t', 'c_size_t', 'c_ubyte', 'c_uint', 'c_uint16', 'c_uint32', 'c_uint64', 'c_uint
8', 'c_ulong', 'c_ulonglong', 'c_ushort', 'c_void_p', 'c_voidp', 'c_wchar', 'c_w
char_p', 'cast', 'cdll', 'create_string_buffer', 'create_unicode_buffer', 'get_e
rrno', 'get_last_error', 'memmove', 'memset', 'oledll', 'pointer', 'py_object',
'pydll', 'pythonapi', 'resize', 'set_conversion_mode', 'set_errno', 'set_last_er
ror', 'sizeof', 'string_at', 'windll', 'wstring_at']

一个这样的小玩意儿包含的东西还真不少啊,可以看到主要包括一些C语言的类型定义。
当你import ctypes的时候,一些动态库已经载入了:
>>> print(windll.kernel32)

>>> print(windll.user32)

>>> print(windll.msvcrt)

直接来使用试试吧,我们最喜欢的自然是Hello World。这里直接调用MessageBox。查查MSDN,MessageBox在User32中,我们调用它。
>>> MessageBox = windll.user32.MessageBoxW
>>> MessageBox(0,"Great","Hello World", 0)
然后,就调用了MessageBox了。。。。。。。。

怎么?晕了?比较一下ctypes库及Python C API吧。。。。于是,K&R哭了。。。。。。。。。。。。。
故事以下图开始

以下图结束:

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

一键在剪贴板中进行语法高亮的工具发布

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

我一直希望有个工具能够便捷的进行语法高亮,因为很多地方都可以用到。特别是,假如我在Google Document或者Office中编辑文件的时候,或者是在Windows Live Writer中编写博客文章的时候(WLW中有插件支持,但还是没有此工具这么方便,并且现在写博客的时候我已经改用Google Document了),我都希望能便捷的进行语法高亮,但是并不是都那么容易实现。特别是像Google Document这样不支持插件的工具,因为Google Document不支持插件,不能进行语法高亮,所以长时间以来我都不将其作为博客的编写工具,直到,你知道的,我决定写个工具来解决这个问题。于是,就有了今天这个工具。

其实本程序实际是原来的chc2c工具的一个UI版本,code-highlight-clipboard2clipboard chc2c是一个命令行工具,可能很多人会比较排斥,虽然我建一些快捷方式也能实现比较便捷的效果。当然,怎么说还是UI工具来的方便,此功能托管在Google Code上:onekeycodehighlighter 已经有下载了:ClipboardHighlighter0.1.rar

因为还是使用Gvim来完成实际工作,所以,gvim的安装还是不可少,假如有人发现绿色版简易版支持语法高亮和ToHtml的vim请推荐给我,我直接放在下载包中,这样大家就可以不用安装gvim了。对了,安装后,将gvim添加到PATH中,这样我才能找到并执行它。

可以通过config.py文件来配置,配置文件中的注释说明的很详细了,简单的修改应该没有问题,config文件本身就是一个python脚本,只要你满足我原来的变量名不变,你可以做很多事情。
默认情况下,我仅添加了c,cpp,python,java,javascript的语法高亮支持,其他的语法在config中配置吧。config中除了syntaxSupport 以外,都支持动态改变。比如保存的文件名,是否有行号,颜色主题等。

使用中软件为一个任务栏中的图标,右键点击会出现菜单:

选中的一栏表示使用的语法高亮语言。使用中将需要进行语法高亮的文字用CTRL-C复制到剪贴板中,然后按Win+Z完成转换,然后就可以直接粘贴到任何支持HTML的地方了。可以是网站的编辑器,可以是Windows live writer,office word,Google Document。。。。。。。。。。你也可以在config.py中配置你想要保存的文件名,直接保存成一个HTML文件。

实际编写的主要工具为PyQt。因为此工具有一些特殊的功能要求,比如全局快捷键,比如用ctypes来调用了Win32的API,比如我要使用System Tray Icon,比如对剪贴板的操作等等等等,我觉得可以将这些例子分为单独的文章来讲解,目前仅贴出一些此工具转换的效果给大家看看。
下面是一些示例:
配置文件(Python):


MOD_ALT = 0x0001
MOD_NONE = 0x000
MOD_CONTROL = 0x0002
MOD_SHIFT = 0x0004
MOD_WIN = 0x0008

# the syntax support you want in the trayicon menu
syntaxSupport = ["c", "cpp", "python", "java", "javascript"]

# the global hotkey define,the modifier can be used is listed above.
modifier = MOD_WIN
hotkey = 'Z'

# do you need display line number before every line?
isLineNumber = False

#------------------------------------------------------------------------------------
# you need not change these below at most time if you don't know what it is.
# the color theme you want use. (corresponding to gvim)
color = 'default'

# if you want to save the transformed in a file.
filename = ''

C++:


//激活创建OpenGL窗口
void EnableOpenGL()
{
    PIXELFORMATDESCRIPTOR pfd;
    int iFormat;

    ghDC = GetDC( ghWnd );

    ZeroMemory( &pfd;, sizeof( pfd ) );
    pfd.nSize = sizeof( pfd );  
    pfd.nVersion = 1;      //版本,一般设为1
    pfd.dwFlags =   PFD_DRAW_TO_WINDOW | //一组表明象素缓冲特性的标志位
        PFD_SUPPORT_OPENGL;
    pfd.iPixelType = PFD_TYPE_RGBA;   //明象素数据类型是RGBA还是颜色索引;
    pfd.cColorBits = 32;     //每个颜色缓冲区中颜色位平面的数目,对颜色索引方式是缓冲区大小
    pfd.cDepthBits = 16;
    pfd.iLayerType = PFD_MAIN_PLANE; //被忽略,为了一致性而包含的

    iFormat = ChoosePixelFormat( ghDC, &pfd; );//选择一个像素格式

    SetPixelFormat( ghDC, iFormat, &pfd; ); //设置到DC中

    ghRC = wglCreateContext( ghDC );    //创建绘图描述表
    wglMakeCurrent( ghDC, ghRC );     //使之成为当前绘图描述表
}

java:



//: holding/AddingGroups.java
package holding; /* Added by Eclipse.py */
// Adding groups of elements to Collection objects.
import java.util.*;

public class AddingGroups {
  public static void main(String[] args) {
    Collection collection =
      new ArrayList
(Arrays.asList(1, 2, 3, 4, 5));
    Integer[] moreInts = { 6, 7, 8, 9, 10 };
    collection.addAll(Arrays.asList(moreInts));
    // Runs significantly faster, but you can't
    // construct a Collection this way:
    Collections.addAll(collection, 11, 12, 13, 14, 15);
    Collections.addAll(collection, moreInts);
    // Produces a list "backed by" an array:
    List
list = Arrays.asList(16, 17, 18, 19, 20);
    list.set(1, 99); // OK -- modify an element
    // list.add(21); // Runtime error because the
                     // underlying array cannot be resized.
  }
} ///:~


javascript:



// This function recursively looks at Node n and its descendants,
// converting all Text node data to uppercase
function upcase(n) {
    if (n.nodeType == 3 /*Node.TEXT_NODE*/{
        // If the node is a Text node, create a new Text node that
        // holds the uppercase version of the node's text, and use the
        // replaceChild() method of the parent node to replace the
        // original node with the new uppercase node.
        n.data = n.data.toUpperCase();
    }
    else {
        // If the node is not a Text node, loop through its children
        // and recursively call this function on each child.
        var kids = n.childNodes;
        for(var i = 0; i < kids.length; i++) upcase(kids[i]);
    }
}


再来个不一样的,delek主题+行号的Python效果:
 


1
 2 MOD_ALT = 0x0001
 3 MOD_NONE = 0x000
 4 MOD_CONTROL = 0x0002
 5 MOD_SHIFT = 0x0004
 6 MOD_WIN = 0x0008
 7
 8 # the syntax support you want in the trayicon menu
 9 syntaxSupport = ["c", "cpp", "python", "java", "javascript"]
10
11 # the global hotkey define,the modifier can be used is listed above.
12 modifier = MOD_WIN
13 hotkey = 'Z'
14
15 # do you need display line number before every line?
16 isLineNumber = True
17
18 #------------------------------------------------------------------------------------
19 # you need not change these below at most time if you don't know what it is.
20 # the color theme you want use. (corresponding to gvim)
21 color = 'delek'
22
23 # if you want to save the transformed in a file.
24 filename = ''

 

呵呵,效果不错吧?唯一的问题是因为使用了vim,所以总是会弹出一个gvim的窗口,有点影响视觉效果,但是好在不影响使用,对于支持的语法我重新贴一下:

2html          a2ps
a65            aap            abap           abaqus
abc            abel           acedb          ada
aflex          ahdl           alsaconf       amiga
aml            ampl           ant            antlr
apache         apachestyle    arch           art
asm            asm68k         asmh8300       asn
aspperl        aspvbs         asterisk       asteriskvm
atlas          autohotkey     autoit         automake
ave            awk            ayacc          b
baan           basic          bc             bdf
bib            bindzone       blank          bst
btm            bzr            c              calendar
catalog        cdl            cdrdaoconf     cdrtoc
cf             cfg            ch             change
changelog      chaskell       cheetah        chill
chordpro       cl             clean          clipper
cmake          cmusrc         cobol          coco
colortest      conaryrecipe   conf           config
context        cpp            crm            crontab
cs             csc            csh            csp
css            cterm          ctrlh          cuda
cupl           cuplsim        cvs            cvsrc
cweb           cynlib         cynpp          d
dcd            dcl            debchangelog   debcontrol
debsources     def            denyhosts      desc
desktop        dictconf       dictdconf      diff
dircolors      diva           django         dns
docbk          docbksgml      docbkxml       dosbatch
dosini         dot            doxygen        dracula
dsl            dtd            dtml           dtrace
dylan          dylanintr      dylanlid       ecd
edif           eiffel         elf            elinks
elmfilt        erlang         eruby          esmtprc
esqlc          esterel        eterm          eviews
exim           expect         exports        fasm
fdcc           fetchmail      fgl            flexwiki
focexec        form           forth          fortran
foxpro         framescript    freebasic      fstab
fvwm           fvwm2m4        gdb            gdmo
gedcom         git            gitcommit      gitconfig
gitrebase      gitsendemail   gkrellmrc      gnuplot
gp             gpg            grads          gretl
groff          groovy         group          grub
gsp            gtkrc          haml           hamster
haskell        haste          hastepreproc   hb
help           hercules       hex            hitest
hog            hostconf       html           htmlcheetah
htmldjango     htmlm4         htmlos         ia64
ibasic         icemenu        icon           idl
idlang         indent         inform         initex
initng         inittab        ipfilter       ishd
iss            ist            jal            jam
jargon         java           javacc         javascript
jess           jgraph         jproperties    jsp
kconfig        kix            kscript        kwt
lace           latte          ld             ldapconf
ldif           lex            lftp           lhaskell
libao          lifelines      lilo           limits
lisp           lite           litestep       loginaccess
logindefs      logtalk        lotos          lout
lpc            lprolog        lscript        lsl
lss            lua            lynx           m4
mail           mailaliases    mailcap        make
man            manconf        manual         maple
masm           mason          master         matlab
maxima         mel            messages       mf
mgl            mgp            mib            mma
mmix           mmp            modconf        model
modsim3        modula2        modula3        monk
moo            mp             mplayerconf    mrxvtrc
msidl          msmessages     msql           mupad
mush           muttrc         mysql          named
nanorc         nasm           nastran        natural
ncf            netrc          netrw          nosyntax
nqc            nroff          nsis           objc
objcpp         ocaml          occam          omnimark
openroad       opl            ora            pamconf
papp           pascal         passwd         pcap
pccts          pdf            perl           pf
pfmain         php            phtml          pic
pike           pilrc          pine           pinfo
plaintex       plm            plp            plsql
po             pod            postscr        pov
povini         ppd            ppwiz          prescribe
privoxy        procmail       progress       prolog
promela        protocols      psf            ptcap
purifylog      pyrex          python         qf
quake          r              racc           radiance
ratpoison      rc             rcs            rcslog
readline       rebol          registry
remind         resolv         reva           rexx
rhelp          rib            rnc            rnoweb
robots         rpcgen         rpl            rst
rtf            ruby           samba          sas
sass           sather         scheme         scilab
screen         sd             sdl            sed
sendpr         sensors        services       setserial
sgml           sgmldecl       sgmllnx        sh
sicad          sieve          simula         sinda
sindacmp       sindaout       sisu           skill
sl             slang          slice          slpconf
slpreg         slpspi         slrnrc         slrnsc
sm             smarty         smcl           smil
smith          sml            snnsnet        snnspat
snnsres        snobol4        spec           specman
spice          splint         spup           spyce
sql            sqlanywhere    sqlforms       sqlinformix
sqlj           sqloracle      sqr            squid
sshconfig      sshdconfig     st             stata
stp            strace         sudoers        svn
syncolor       synload        syntax         sysctl
tads           tags           tak            takcmp
takout         tar            tasm           tcl
tcsh           terminfo       tex            texinfo
texmf          tf             tidy           tilde
tli            tpp            trasys         trustees
tsalt          tsscl          tssgm          tssop
uc             udevconf       udevperm       udevrules
uil            updatedb       valgrind       vb
vera           verilog        verilogams     vgrindefs
vhdl           vim            viminfo        virata
vmasm          voscm          vrml           vsejcl
wdiff          web            webmacro       wget
whitespace     winbatch       wml            wsh
wsml           wvdial         xbl            xdefaults
xf86conf       xhtml          xinetd         xkb
xmath          xml            xmodmap        xpm
xpm2           xquery         xs             xsd
xslt           xxd            yacc           yaml
z8a            zsh           

支持的颜色主题有:
blue  
color
darkblue  
default  
delek  
desert  
elflord  
evening  
koehler  
morning  
murphy  
pablo  
peachpuff  
ron  
shine  
slate  
torte  
zellner

支持的颜色主题,语言语法都是通过config来配置,其实操作就是选择好语言,copy,Win+Z,paste。。。。。。。。。。

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

C和Python程序员的JavaScript学习指南(译)

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

 原文来自:《JavaScript for C & Python programmers

》,经过作者Canis允许后翻译,即使转载请附带此链接。



前言:很少干翻译的事情,累,辛苦,不能发挥,典型的费力不讨好,最近无聊,想在网页上显示动画(因为CSDN贴图不是不让贴了嘛),Java
applet虽然已经搞定了,但是总感觉这不是Java的世界,所以想大概学习一下JavaScript后再做决定,(-_-!从命名上看其实像是换成了
Java的脚本-_-!)网上类似JAVA for C++
programmers的文章很多,但是js类似的文章却很少,一方面可能的确java更加流行,另一方面可能一般的C/C++程序员与js的领域差的太
远,没有此需求,本文也不是为C++程序员写的,是为c和python程序员写的。

翻译完后,就个人感觉,本文甚至不能算是一个较好的指南,大概可以看做一个C,Python程序员学习
JavaScript时的抱怨,全文有太多作者的抱怨,针对JavaScript不寻常的语法提出了很多看法,用本文来全面的了解Javascript是
不太可能的,但是了解一下作为一个C,Python程序员,学习JavaScript应该注意哪些奇特的地方,也不是没有好处。



(以下我的注释都添加**开头,没有添加的为作者原注释)


以下是译文:



C和Python程序员的JavaScript学习指南

作者:Canis


  • 第一次发表: 2006年三月


  • 更新: 2008年七月 (添加了到 JSLint的链接)


  • 最后一次更新: 2009四月 (更好的删除Array items的方式)


 


    本文是对JavaScript的简单介绍。网上有很多类似的资料,但是大部分都是针对非程序员读者的,教导一些javascript的简单代码。那样也没有什么,因为很多从来不编程的人发现他们的网页需要一些js脚本的时候会需要这些。


    这篇文章提供了一些有关JavaScript的更深层次的信息。我假设你完全不懂javascript但是也假设你已经是一个称职的程序员,是"C-like"语言的程序员更好,并且懂一点python将很有帮助(**说的不就是我吗?-_-!)


    我将谈到任何我认为javascript不好的地方。(**原文用到object model 指的的是对象模型吗?作者是想说面向对象吗?我都没有在文章中看到)



JS不是JAVA

    
首先,一个常见的误解需要澄清,javascript从来与JAVA没有任何关系。JS以前甚至不叫js(另外,java以前也不叫java,但是那就是另外一个故事了
)。(**
链接中关于JAVA历史的第一句话就是:Java programming Language evolved from a language
named
Oak)这个Java的前缀完全是出于市场的因素,可能是因为(**这句没有看懂)这对他们互相的支持有意义,就像将他们的腿绑在一起,共同在市场上进
退。警告:本文包含JS特性这样的主题,假如你发现这对你来说太难了,你最好早点走吧。

  
 JS是一个动态语言,有着C语言一族的基本语法,但是却有很先进,看起来很像Python的数据类型。(**原文用Pythonesque,表示非常符
合Python设计思想和Python好的使用习惯,更通常我们用Pythonic一词),事实上,从很多方面来讲,它的很多行为也是这样的。

    
事实上,JS是有令人惊讶的强大的,表达能力强的语言,似乎应该能非常优雅的完成很多工作。

    然而,事实并非如此。

   它带来的是一个无尽的痛苦。陷阱潜伏在黑暗之中,等待时机,像野兽一样潜伏着,他们会吃掉你。(**作者此处提供了一个我无法打开的网页链接:http://www.scarygoround.com/shop-tshirts.php#bears)

    JS是一个彻头彻尾的混账语言,但是你却无法摆脱,同样的,浏览器的API也是同样的让人困惑。

通常来说,JS似乎遵循的是最大惊讶原则。(**-_-!)



网页的嵌入


  

 JS 可以单独运行(比如
Rhino

),(**Rhino是

JavaScript for Java,一个将js编译为java字节码运行的开源项目,我常认为犀牛书《JavaScript The Definitive Guilde》封面画了个雄壮的犀牛就是这个原因)或者嵌入到特定的hosts中,(比如Mac OS X Widgets

),但是,最通常的做法是将其嵌入到网页中,通过如下的形式:

 

 

html:

<script language='javascript'> // source code goes here </script>

或者:

html:

<script language='javascript' src='/path/to/source.js' />

在<script>的tag的scope内,普通的HTML语法不再有效。--<就是<,不是tag开始符,并且&就是&,不是指示一个字符的开始。(全文需要的HTML知识仅限于此)










基础语法

    
大部分的基本语法直接来自于C,所有下面的语法行为就像在C/C++/等语言(**等等中包括java,python-_-!)一样。

注释:  /* C */ 风格 和  // C++ 风格

条件:    if /then /else

选择:    switch /case /break default

while循环:    while /do /break /continue

for循环:    for /break /continue


    函数看起来与C类似,但是又一些不同。我们马上就会讲到。for的循环有一些我们需要关心的额外语法。类在js中是与其他大部分语言完全不同的。


    在语句结尾的分号: 你可以使用它们,但是他们是普遍是可选的,根据晦涩难解的的ECMAScript标准(呵呵--”标准化“版本的JS)的规则,js会自动的插入分号。它大概意思是,在缩进是比较清楚,没有二意性时,你不需要分号。



变量和声明

但是,不像Python,你确实需要声明一个局部变量的存在,只是不声明它是什么类型。这不是显而易见的,因为如果你没有声明一个变量,JS将自动声明它。

全局声明

    是的,JS采用了Python相反的决定(Python中除非明确的声明一个变量是一个全局变量,那么就是局部变量),JS中除非你明确的声明,不然都假设变量是全局的。


这样会有一些非常令人惊讶和恼火的
影响
特别是,如果你忘了声明一个变量,你的代码可能会很好地工作,直到它彻底的与其他代码搅在一起,因为其他代码使用了同样名字的全局变量。



或者你写了一些递归代码,接着可怕的嵌入一个意外的无限循环中 -- 可能会没有反应,甚至崩溃。你的浏览器不是足够智能化去跳出无限循环,唉。。。。。。



  
 是的,JS设计的时候就是要让某些事情花掉你95%的时间(还不是全部),当你忘记这些事情的时候,它可能静静的失败,也有可能崩溃,还有可能让整个执
行环境没有反应,使得你除了反复试验外没有办法去调试。感谢你,JS语言的设计者们! 感谢你,浏览器的实现者们!




  
 无论如何,你使用var关键字声明变量,比如:var msg = "hello" --
如果你不指定值,变量默认是未定义的。我建议你总是通过var声明你的变量,不管是不是真的需要,这样会更加安全。假如任何人知道一个JS的Lint工具
(**lint是一个很著名的C语言错误分析程序),让我知道并且我会在此添加一个链接。









Update: Martin Clausen指出存在
JSLint
。你需要仔细的调整你的options,另一方面,JSLint在其首页有一个强大的警告信息系统。











函数

JS的函数与C有些不同。他有两种形式,命名的及匿名的。命名函数与C中很像,但是,当然,没有任何参数或返回值的类型声明。在C语言中放置返回值的地方,使用function关键字。
function treeWalk(branch, visitor){
    visitor(branch)
    var i // not going to let you forget! you'll thank me later! 
    for (i in branch.children) {
        treeWalk(branch.children[i], visitor)
    }
}
在这里,visitor是一个传递进来的函数,我们将在以后展示怎么样做到。branch是一个用户定义的对象,我们假设它有一个名叫children的array。
此外,我相信你已经注意到这个不寻常的for结构。这是一个迭代器版本。(**事实上是典型的for each语法规则)
迭代器语法:
for (<variable> in <variable of container type>) <statements>

迭代器遍历容器中的每一项,然而,这是另一个经典的JS令人烦恼的情况,它仅返回每个成员的索引。假如容器是一个有10个元素的array,它可能返回整数0到9(看看下面关于arrays的内容)。假如容器是一个hash-map,它将返回每个key。

这就需要一个额外的,多余的哈希查找过程,因为似乎没有(就我目前所找到的)对应Python的for(key,value) in container: statements循环的语法。




匿名函数是非常明显的,你仅仅忽略名字。

function(param1, param2 ...) {
statements 
}

就其本身而言,这是毫无价值的,上面的就是表达一下语法。你可以将整个定义放在任何地方,包括变量赋值(**其实意味着JS中函数是第一类值(first class)),下面的例子是相同的定义一个名为mul的函数。

var mul = function(a,b) { return a*b }


一个不同的例子,用了前面定义的的treeWalk函数:(**即将匿名函数直接作为函数参数传递)




treeWalk(rootNode, function(item) { logDebug(item) } )




类型,转换,比较

显然,你有数字类型(double float -- JS事实上没有整数) ,字符串类型,并且他们就像你预期的那样使用。然而,JS有一个偶然(或者说令人惊讶的)的在各种类型中间转换的倾向。例如,

rhino 
示例:

js> 2 + 2

4

js> "2" + 2

22

js> "2" * 2

4

"+" 被用于数学的加法和字符串连接。

当至少有一个字符串参数时,它将其他类型全部转换为字符串然后连接,但是其他数学操作却是转换字符串到数字。哈哈!结合操作符的优先级将带来更多的额外奖励的乐趣和混乱。

rhino 示例

:




js> "2" + 2 + 2
222
js> 2 + "2" + 2
222
js> 2 + 2 + "2"
42
js> "2" + 2 * 2
24
js> "2" * 2 + 2
6
js> ("2" + 2) * 2

44

 

深深的,慢慢的呼吸...
 这一切总会过去的。。。。。。。(**真不愧是最大惊讶。。。。)


Oh yeah,并且JS的比较操作符也是诡异的,==转换类型,===不会


rhino 示例
:
js> 2 == 2
true
js> 2 == "2"
true
js> 2 === 2
true
js> 2 === "2"
false
并且,注意字符串比较中给你的意外,然而,这还不算太坏,假如每个操作数都是数字,转换将会向着数字的方向。
rhino 示例
:
js> 4 > 2
true
js> 4 > 22
false
js> 4 > "22"
false
js> "4" > "22"
true

噢!并且JS将会很高兴的无声无息的将无效的数字转换为NaN,并且会将这种行为贯穿在整个代码中。。。。

rhino 示例
:
js> "2" * 2
4
js> "two" * 2
NaN
js> x = "two" * 2
NaN
js> 4 * x
NaN
记住,深深的,慢慢的呼吸......






Arrays 和 Hashmaps

JS内建Arrays and hashmaps 。假如你仅仅需要声明一个含有一些初始化数据的array和hashmap,JS有一个可以直接从Python中拷贝数据过来的语法 -- 中括号用于list,大括号用于hashmap。

rhino 示例:
js> myArray = [1, 2, 3, 17, 23, 42, 69]
1,2,3,17,23,42,69
js> myHash = {"key": "value", "key2": "value2"}
[object Object]
两者都是用方括号索引:
rhino 示例:(接上面)

js> myArray[3]
17
js> myHash["key2"]
value2
你可以混合和配对使用任何集合数据类型,比如每个值都是一个array或者hashmap。对于key来说,似乎转换所有的数据类型到字符串形
式并且这样使用--所以JS中的语句myHash[fred] = value似乎像python中的myDict[repr(fred)] =
value一样。
你可以用同一种语法删除两种类型的元素,delete语句:
rhino 示例:(接上面)
js> myHash["key2"]
value2
js> delete myArray[3]
true
js> delete myHash["key2"]
true
(delete似乎总是返回true,是的,甚至你的索引超出范围,是的,甚至这里没有一个对应的key。我不知道为什么)


(**rhino 示例:(接上面)

js> myHash["key2"]
js> delete myHash["key2"]
true
)
然而,你应该注意,如果你从一个array中移出了一个元素,它会留下一个空白(undefined),并且所有的其他元素仍然有同样的索引。
rhino 示例:
js> myArray
1,2,3,,23,42,69
js> print(myArray)
1,2,3,,23,42,69
js> print(myArray[3])
undefined
js> print(myArray[4])
23
(那个两个连续的逗号不是一个印刷错误,undefined的值转换到字符串类型时没有任何输出,但是这里仍然有一个在array为其保留的‘槽’)
现在,当您在一个数组迭代, 它会自动跳过这样的空插槽:
rhino 示例:
js> for (i in myArray) print(i)
 1
 2
 3
 23
 42
 69



(**在我这里的  rhino 运行效果与原作者的有所区别,就像作者前面说的那样,返回的是key

js> for( i in  myArray) print(i)
0
1
2
4
5
6
js> for( i in  myArray) print(myArray[i])
1
2
3
23
42
69
真正神奇的是此时跳过undefined值的方式是直接忽略了,连个空行都没有

虽然如此,对于许多人物来说,有一个undefined的值在array中可能是非常痛苦的事情,所以你会发现,写一个函数用于“压缩”一个array,或者返回一个指定索引忽略的副本是有用的,给你一个删除+压缩的函数。(代价是一次不必要的复制操作)

JS:

function deleteArrayItem(source, index){
    var result = new Array()
    for (i in source) 
        if (i != index) 
            result.push(source[i])
    return result
}

Update:Reddit 用户 davidsickmiller
提到一个我忽略的array方法,当我在2006年写下这个的时候。Array::splice(**切片函数)从数组中移出一个范围,返回移出的元素,并且,将原来的array打包。(**此处原作者用packing,其实就是去除undefined的元素)



rhino 示例:

js> myArray = [1, 2, 3, 17, 23, 42, 69]
1,2,3,17,23,42,69
js> myArray.splice(3,1)
17
js> myArray
1,2,3,23,42,69
(**这样的形式可以看到,事实上不想要undefined的数据时根本就不应该使用delete操作,事实上,对于已经有了undefined数据时,splice也是很有用的,可以直接移出undefined的数据)
Arrays会自动的扩展,当你插入一个超出索引范围的值的时候。并且,假如这个范围不是连续的,那么所有中间的“槽”都是undefined的。
Array有一个length成员变量,比如myArray.length,但是它不告诉你到底有多少元素存在,它告诉你有多少的"槽",用另外的话说,它总是返回你插入元素的最高的索引+1,假如你想要知道实际的元素数量,好的,你就不得不遍历array并且自己计数。
好了,我要走了,留下你自生自灭。。。。。。。。。。
















 


原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com



阅读全文....

CMake中的字符串及文件操作

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

 以前写过一篇关于CMake的基本用法的文章(现代软件构建系统的使用 cmake简介...),在最近的使用中,发现一些更复杂情况的使用还有待学习,并且相关的资料也比较少,真正可以依赖的也就(CMake 实践)一文.所以,最近准备将一些非常重要,但是网上资料较少的用法--字符串,文件操作,好好整理一下.目标是,实现一个目录下的多个工程的一次性工程文件生成,而不是为每个工程都建立一个CMake文件,这个需求在我下载一些图书的配套源码时经常碰到,可能大部分的图书作者都习惯于仅仅提供原始源代码文件而不提供工程文件.

    特别声明的是,本文并不是一个完备3的CMake教程(以前写的简介也不是),需要相关入门教程的应该去寻找(CMake 实践),那才是你想要的.本文仅仅是作为一些缺失资料的收集,也包括我自己对CMake字符串,文件处理的探索.(真是纯个人探索,网上即使是英文的相关资料也不多,可能毕竟CMake还是不怎么流行吧),仅适合需要的人搜索到这里查看相关信息.

本文内容:

    实际上,本文研究的仅仅包括CMake的以下两部分,已经一些if,else中对字符串的判断.在本文中,由于目的不同,主要将会把CMake作为一种普通的编程语言来对待,(其实它本来就是)甚至很多地方根本不建工程,请注意.

string: String operations.
string(REGEX MATCH (regular_expression)
(output variable) (input) [(input)...])
string(REGEX MATCHALL (regular_expression)
(output variable) (input) [(input)...])
string(REGEX REPLACE (regular_expression)
(replace_expression) (output variable)
(input) [(input)...])
string(REPLACE (match_string)
(replace_string) (output variable)
(input) [(input)...])
string(COMPARE EQUAL (string1) (string2) (output variable))
string(COMPARE NOTEQUAL (string1) (string2) (output variable))
string(COMPARE LESS (string1) (string2) (output variable))
string(COMPARE GREATER (string1) (string2) (output variable))
string(ASCII (number) [(number) ...] (output variable))
string(CONFIGURE (string1) (output variable)
[@ONLY] [ESCAPE_QUOTES])
string(TOUPPER (string1) (output variable))
string(TOLOWER (string1) (output variable))
string(LENGTH (string) (output variable))
string(SUBSTRING (string) (begin) (length) (output variable))
string(STRIP (string) (output variable))
string(RANDOM [LENGTH (length)] [ALPHABET (alphabet)]
(output variable))


 

file: File manipulation command.
file(WRITE filename "message to write"... )
file(APPEND filename "message to write"... )
file(READ filename variable [LIMIT numBytes] [OFFSET offset] [HEX])
file(STRINGS filename variable [LIMIT_COUNT num]
[LIMIT_INPUT numBytes] [LIMIT_OUTPUT numBytes]
[LENGTH_MINIMUM numBytes] [LENGTH_MAXIMUM numBytes]
[NEWLINE_CONSUME] [REGEX regex]
[NO_HEX_CONVERSION])
file(GLOB variable [RELATIVE path] [globbing expressions]...)
file(GLOB_RECURSE variable [RELATIVE path]
[FOLLOW_SYMLINKS] [globbing expressions]...)
file(REMOVE [file1 ...])
file(REMOVE_RECURSE [file1 ...])
file(MAKE_DIRECTORY [directory1 directory2 ...])
file(RELATIVE_PATH variable directory file)
file(TO_CMAKE_PATH path result)
file(TO_NATIVE_PATH path result)
file(DOWNLOAD url file [TIMEOUT timeout] [STATUS status] [LOG log])

 

以上列表来自于CMake最新的文档:http://www.cmake.org/cmake/help/cmake2.6docs.html

实验方式:

    完全依靠CMake的GUI工具,通过configure的输出来获取实验结果.最终的结果就是为我的博客所有源代码重建工程,以后在博客源代码中仅保留CMake的配置文件,不再保留工程, 保留工程很有局限性,比如Linux下没有makefile是很有问题的,个人建工程的时候用的是VS2008,这样VS2005的使用者也会很郁闷(虽然改个版本号就可以用),再加上以前刚开始学习OpenGL的时候非常短视,为了方便自己,将GLUT等库都装在系统目录下,这样的确是方便了自己,但是任何人clone的源代码都无法顺利运行,必须首先装一套配套的库才行,这可不是太好的工程管理方法,这次顺便解决.原来的源代码目录完全按照日期分目录,每天又分很多示例,很有典型意义.

    比如说( DirectX 9.0 3D游戏开发编程基础)--(d3d龙书)(英文名:(Introduction to 3D Game Programming with DirectX 9.0))的附带源码仅有源代码文件,分散在N个目录(每章一个目录+每章每个示例一个目录),也与我的博客中源代码的分配很类似,事实上,很多书籍配套的源代码都有这样的问题,通过这样的方法可以一次解决.没有CMake的时候,想OpenGL红宝书,D3d龙书,3D游戏编程大师这样的书的源代码你得分别建几十个工程才能很好的在Windows下使用,这是非常让人郁闷的事情,你郁闷吗?我想,我可以通过这中方法搞定这些源代码,弄一个配套的project放在google code上,方便大家;),辛苦我一人,方便千万家的工作,那是责无旁贷的完成啊:)
    本文顺便用于介绍CMake的强大及其推广,按照开源的理念,即使我没有真的参与某个开源产品的研发,我实际的使用了它,这是第一层次的支持,使用后感觉不错,向大家推广,这是第二层次的支持,我决定将我对CMake的支持上升一个层次(以前写简介的时候就上升过了)


实验过程

我的HelloWord:
获取某个源代码目录下的所有源代码,而不需要单个的列举,这是个很大的进步,在(现代软件构建系统的使用 cmake简介...)中介绍过,这是从
set(SRC_LIST test.cpp)

aux_source_directory(./ SRC_LIST)

的进步.通过aux_source_directory来实现.

现在的问题是,单个工程这个函数很好用了,对于多个工程多级目录的情况呢?答案是file()一族的函数.

cmake_minimum_required(VERSION 2.8)
FILE(GLOB_RECURSE SRC_LIST "*.cpp")
FOREACH(src ${SRC_LIST})
MESSAGE( ${src} )
ENDFOREACH()
上面的代码,放在我的博客的根目录下,会找到所有的.cpp文件并输出
关键在于两个地方FILE(GLOB_RECURSE .......
及FOREACH的使用
FILE(GLOB_RECURSE .......用于循环递归遍历目录并且使用GLOB匹配,GLOB是我们熟悉的文件匹配语法,(类似正则的简化版)
*用于表示任意长度的任意文字,?用于匹配任意的一个字符.这里*.cpp用于匹配所有的.cpp后缀的文件.
同时还有FILE(GLOB....用于非递归式的寻找,(即只寻找当前目录)
FOREACH就是我在使用C++时一直梦寐以求的循环语法,这里很明白,就是遍历${SRC_LIST}的值,然后用MESSAGE输出,所以有了以下的输出.
在CMake的GUI中,确认正确的CMakeLists.txt的位置及工程准备在的位置,Configure后,
输出一下信息:
Check for working C compiler: cl

Check for working C compiler: cl -- works

Detecting C compiler ABI info

Detecting C compiler ABI info - done

Check for working CXX compiler: cl

Check for working CXX compiler: cl -- works

Detecting CXX compiler ABI info

Detecting CXX compiler ABI info - done

F:/MySrc/blog/2009-10-12/SimpleRectangle/SimpleRectangle.cpp

F:/MySrc/blog/2009-10-14/GLDrawCircle/GLDrawCircle.cpp

F:/MySrc/blog/2009-10-14/GLDrawFourCircle/GLDrawFourCircle.cpp

F:/MySrc/blog/2009-10-14/GLFourCircleAnimation/GLFourCircleAnimation.cpp

F:/MySrc/blog/2009-10-14/GLShadeAnimation/GLShadeAnimation.cpp

F:/MySrc/blog/2009-10-14/WinDrawCircle/WinDrawCircle.cpp

F:/MySrc/blog/2009-10-18/glInterleavedArrays/glInterleavedArrays.cpp

F:/MySrc/blog/2009-10-18/glRectWithArrayDraw/glRectWithArrayDraw.cpp

F:/MySrc/blog/2009-10-18/glRectWithDrawElements/glRectWithDrawElements.cpp

F:/MySrc/blog/2009-10-18/glRectWithMultiDrawElements/glRectWithMultiDrawElements.cpp

F:/MySrc/blog/2009-10-18/glVertexArray/glVertexArray.cpp

F:/MySrc/blog/2009-10-18/glVertexArrayWithColor/glVertexArrayWithColor.cpp

F:/MySrc/blog/2009-10-20/OpenGL/debug/moc_opengl.cpp

F:/MySrc/blog/2009-10-20/OpenGL/main.cpp

F:/MySrc/blog/2009-10-20/OpenGL/opengl.cpp

F:/MySrc/blog/2009-10-21/gl3DCoordinate/gl3DCoordinate.cpp

F:/MySrc/blog/2009-10-21/glSmoothColorPyramid/glSmoothColorPyramid.cpp

F:/MySrc/blog/2009-10-21/glWirePyramid/glWirePyramid.cpp

F:/MySrc/blog/2009-10-25/glCullFace/glCullFace.cpp

F:/MySrc/blog/2009-10-25/glPolygonFace/glPolygonFace.cpp

F:/MySrc/blog/2009-10-25/glViewingTrans/glViewingTrans.cpp

F:/MySrc/blog/2009-10-26/glComposModelTrans/glComposModelTrans.cpp

F:/MySrc/blog/2009-10-26/glComposModelTrans2/glComposModelTrans2.cpp

F:/MySrc/blog/2009-10-26/glScaleSample/glScaleSample.cpp

F:/MySrc/blog/2009-10-28/glOrthoSample/glOrthoSample.cpp

F:/MySrc/blog/2009-10-28/glPerspective/glPerspective.cpp

F:/MySrc/blog/2009-10-29/JTFourTangram/JTTangram.cpp

F:/MySrc/blog/2009-11-11/glHalfTrans/glHalfTrans.cpp

F:/MySrc/blog/2009-11-12/glDepthTest/glDepthTest.cpp

F:/MySrc/blog/2009-11-12/glFogSample/glFogSample.cpp

F:/MySrc/blog/2009-11-9/glSimpleColorPyramid/glSimpleColorPyramid.cpp

F:/MySrc/blog/2009-11-9/LightSimple/LightSimple.cpp

F:/MySrc/blog/2009-9-27/Win32OpenGLTemplate/Win32OpenGLTemplate.cpp

F:/MySrc/blog/2009-9-28/RotateRect/RotateRect.cpp

F:/MySrc/blog/2009-9-29/TestOpenGL/mvarray.cpp

F:/MySrc/blog/JTTangram/JTTangram.cpp

Configuring done


获取了SRC_LIST后,就可以开始处理了

FOREACH(src ${SRC_LIST})
    IF(NOT (src MATCHES ".*2009-10-20.*")) 
        MESSAGE( ${src} Finded)
        STRING( REGEX REPLACE ".*/(.*)/.cpp$" "/1" prjName ${src} )
        MESSAGE( ${prjName} Added)
        ADD_EXECUTABLE( ${prjName} ${src} )
        IF (NOT (prjName STREQUAL mvarray) )
            SET_TARGET_PROPERTIES(${prjName} PROPERTIES WIN32_EXECUTABLE "true")
        ENDIF(NOT (prjName STREQUAL mvarray) )
    ENDIF(NOT (src MATCHES ".*2009-10-20.*"))
ENDFOREACH(src)
一下是关键点的解释:

通过STRING( REGEX REPLACE命令来获取到所有的.cpp后缀的文件,因为我的工程中所有的工程都仅包含一个cpp,所以可以这样做

string(REGEX REPLACE (regular_expression)
(replace_expression) (output variable)

的语法不算太好用,学会以后,就主要靠你的正则表达式理解能力了,几乎无所不能.CMake的语法中用()来表示正则表达式的匹配捕获,

用"1"的方式在替换中表示捕获到的字符串(会正则的理解起来应该不难).但是,特别需要注意的是,CMake中需要用/1的形式来传递参数,就像你在C++中需要做的那样.


ADD_EXECUTABLE( ${prjName} ${src} )

以每个cpp的文件名来作为工程名,每个源文件作为此工程需要的文件.


SET_TARGET_PROPERTIES(${prjName} PROPERTIES WIN32_EXECUTABLE "true")

用于指定我的这些工程都是Win32的工程(调用WinMain),默认时时命令行的工程.


上面这么几句就完成了为我10多个工程的一次工程文件生成


此代码中有几个特别点:

2009-10-20那个工程是一个Linux的工程,不要生成VS下Win32的工程,我通过

IF(NOT (src MATCHES ".*2009-10-20.*")) 的形式过滤掉了


IF (NOT (prjName STREQUAL mvarray) )语句用于过滤mvarray所在的工程,因为它是一个命令行的工程(使用Glut管理窗口)


以下是完整的文件(CMake的高亮很漂亮吧:)见我以前fachc2c),完成文件也可在我博客的示例代码中获取.

PROJECT( JTianLingBLog )
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
INCLUDE_DIRECTORIES(./dependes/windows/include/)
LINK_DIRECTORIES(../dependes/windows/lib/)
FILE(GLOB_RECURSE SRC_LIST "*.cpp")
FOREACH(src ${SRC_LIST})
    IF(NOT (src MATCHES ".*2009-10-20.*"))
        MESSAGE( ${src} Finded)
        STRING( REGEX REPLACE ".*/(.*)/.cpp$" "/1" prjName ${src} )
        MESSAGE( ${prjName} Added)
        ADD_EXECUTABLE( ${prjName} ${src} )

        IF (NOT (prjName STREQUAL mvarray) )
            SET_TARGET_PROPERTIES(${prjName} PROPERTIES WIN32_EXECUTABLE "true")
        ENDIF(NOT (prjName STREQUAL mvarray) )

    ENDIF(NOT (src MATCHES ".*2009-10-20.*"))
ENDFOREACH(src)


进一步的应用

有了以上的经验后,我再为(d3d龙书)的源代码生成工程,以方便大家.
原来源代码的目录结构前面已经讲过了,直接先看全部CMake文件的代码:

PROJECT( IntroToD3D9 )
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

FILE(GLOB_RECURSE srcList "*.cpp")

# fliter duplicates projects
FOREACH(src ${srcList})
        MESSAGE("finded: " ${src})
        STRING( REGEX REPLACE "(.*/.*)/.*/.cpp$" "/1" dirName ${src} )
        LIST(APPEND dirNameList ${dirName})
        MESSAGE("directory Finded: " ${dirName} )
ENDFOREACH(src ${srcList})

MESSAGE("..................................................................")

LIST(REMOVE_DUPLICATES dirNameList)

FOREACH(dir ${dirNameList})
        MESSAGE( ${dir} " Process begin.....")
        STRING( REGEX REPLACE ".*/(.*)" "/1" prjName ${dir} )
        FILE(GLOB prjSrcList "${dir}/*.cpp" "${dir}/*.h")

        FOREACH(prjSrc ${prjSrcList})
                MESSAGE("src glob: " ${prjSrc})
        ENDFOREACH(prjSrc)

        MESSAGE("before replace Project: " ${prjName} )
        STRING( REPLACE " " "" prj ${prjName})
        ADD_EXECUTABLE( ${prj} ${prjSrcList} )

        MESSAGE("Added Project: " ${prj} )
        SET_TARGET_PROPERTIES(${prj} PROPERTIES WIN32_EXECUTABLE "true")
        TARGET_LINK_LIBRARIES(${prj} d3d9 d3dx9 winmm)

ENDFOREACH(dir ${dirName})


已经比较复杂了,基本上,看到这里,你会认可其实CMake就是一个专门用于管理工程的脚本语言-_-!

这里讲一下代码中的几个要点,就不多说了:

FILE(GLOB_RECURSE srcList "*.cpp" 遍历所有.cpp文件(带完整路径)

用STRING( REGEX REPLACE "(.*/.*)/.*/.cpp$" "/1" dirName ${src} )获取到目录名

LIST(APPEND dirNameList ${dirName})

保存所有的目录名,此时因为可能每个目录中有多个源代码导致重复,然后通过
LIST(REMOVE_DUPLICATES dirNameList)
将重复去掉
再通过
STRING( REGEX REPLACE ".*/(.*)" "/1" prjName ${dir} )
获取目录最后的名字作为每个工程的名字
FILE(GLOB prjSrcList "${dir}/*.cpp" "${dir}/*.h")
再反过来,获取每个目录下的源代码(此时已经获得了每个工程及其对应的源代码了
剩下的就简单了
STRING( REPLACE " " "" prj ${prjName})
是唯一有意思的,去掉所有的空格后再建立工程(原来的目录中有空格,所以获取的工程名也有空格,并且导致建立的目录及一些文件会出现问题)
TARGET_LINK_LIBRARIES(${prj} d3d9 d3dx9 winmm)
链接上需要的库,OK,一下子生成几十个工程,还带ALL_BUILD选项,爽
为了方便大家,我将所有的( DirectX 9.0 3D游戏开发编程基础)(英文名:(Introduction to 3D Game Programming with DirectX 9.0)源代码托管在Google Code上了,并且建立好了VS2008的工程(不需要的用CMake换吧),大家各取所需吧.
浏览地址:
http://code.google.com/p/jtianling/source/browse/?repo=introd3d9
CheckOut地址:
hg clone https://introd3d9.jtianling.googlecode.com/hg/ jtianling-introd3d9
下载地址:
呵呵独家出品带工程的源代码:)
最后其实还有个问题,原来的源代码资源全部在各自的目录中,运行时的默认工作路径与工程一直,这样会全部找不到资源.但是我没有找到CMake怎么改变工作路径.
在网上找到一个CMake 的 FAQ()是这样解释的:

 Can CMake set the Debugging/Working Directory property in Visual Studio projects?

No. The value of this property is not stored in the project files.
It is stored in extra files created by the IDE when a solution is
loaded (VS .NET 2003 uses a hidden .suo file next to the .sln solution
file). The format of these files is not known to CMake and cannot be
generated. In some versions of VS the files are binary and not human
readable. 

事实上,我一直以为VS中将工作路径放在suo文件中而不是工程文件是MS干过的最愚蠢的事情之一,导致工作中的使用从来没有达到过从

源代码库中获取源代码及工程后,直接正常编译运行的情况,工作路径必须的额外设置,并且,要知道,是每个工程的工作路径!也因为这个原因,还因为suo是一个只有MS才懂的二进制文件,CMake无法自动改变此值,也就是说,虽然我已经通过CMake为你生成了几十个工程,但是凡事需要用到资源的地方,你都得手动改变工作路径,真无聊啊!!!!还好资源文件都不一样,我将其全部移到projects目录下,这样,只要你在projects目录下生成工程,默认的运行工作路径就是当前工作路径,省去了这样的操作,但是带来的资源及projects混合的情况,那就没有办法了.你们去骂MS吧,我已经尽力了.

事实上,虽然用CMake完成上述工作后,一次就建立了所有需要的工程,几十个几十个的生成,会感觉很爽,其实,花去的时间(主要用于学习CMake诡异特别的语法)要远超过自己一个一个手动生成工程.但是,实在无法忍受手动生成几十个工程的枯燥,习惯重复的工作只能使人越来越懒,没有任何收获...................

enjoy them all!

    

博客本身完整源代码获取说明

由于篇幅限制,本文一般仅贴出代码的主要关心的部分,代码带工程(或者makefile)完整版(如果有的话)都能用Mercurial在Google Code中下载。文章以博文发表的日期分目录存放,请直接使用Mercurial克隆下库:

https://blog-sample-code.jtianling.googlecode.com/hg/

Mercurial使用方法见《分布式的,新一代版本控制系统Mercurial的介绍及简要入门

要是仅仅想浏览全部代码也可以直接到google code上去看,在下面的地址:

http://code.google.com/p/jtianling/source/browse?repo=blog-sample-code

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

可商业使用的免费软件推荐列表(revision 2 )

write by 九天雁翎(JTianLing) -- www.jtianling.com


讨论新闻组及文件

 

缘起

 

     可以参看《谷歌金山词霸是完全免费的吗?谷歌自己的软件呢?
》中的原因,新的公司对软件的使用控制很严,(当然,从中国的情况出发显的很严,其实严是正常的)我需要能够可商业使用(其实仅表示可以在企业使用)的免费使用的软件,并且,事实上,为了维持工作环境的尽量统一,我将尽量保持公司家里一套软件环境而不是公司一套家里一套,这样会很麻烦,比如会碰到公司的openoffice文档在家里没有办法用office来编辑和查看的问题。

    于是,软件寻找之旅开始了。。。。。。。。。。中间有很多陷阱,这里会告诉大家。。。。。另外,每个软件后以(Linux Enable)标志Linux下也可用。

 

列表:

 

文本编辑工具:

OpenOffice:作为MS Office的替代,相对来说,有一些不太好用的地方,但是使用后发现数学公式的编写利用了类Tex的方式,强大的很,HTML,PDF的输出也是非常漂亮。(Linux Enable)

GVim:常用,特别是一般简单代码的编写,比如Python,Lua等。(Linux Enable)

notepad++:插件丰富,事实上,也用其16进制编辑插件用于替代Winhex,事实上由于我更习惯GVim,所以其实用的很少.

Google Doc:非常强大,支持博客的发布,并且自带版本控制,这点使得其更加强大,平时管理文档时使用hg的管理的麻烦方式完全省略了.(Linux Enable)

 

IDE:

作为程序员最常使用的东西之一,自然需要一个好用的,还好我们有很多选择:

C++: Visual studio express,MS出品的免费产品,事实上,因为不能使用Visual assist X和ViEmu,原来的VS还是还是太简单了,这几点有些郁闷,ViEmu就是无可替代的。。。。。。。在某些情况下,我们也仅能使用Autohotkey
+Ditto来稍微的替代一下Visual assist的snippet功能.

JAVA: Eclipse,强大无须多言,很多好用的插件都是免费的,唯一可惜的就是一个vi的模拟插件是要钱的(其实也相当不好用)。(Linux Enable)

 

 

版本控制:

TortoiseHg:我喜欢在本地使用TortoiseHg来管理自己的源代码。(Linux Enable)

TortoiseSVN: 仍然是世界上最优秀的源代码管理软件之一

 

文档生成工具:

doxygen: 通吃C++,C#,JAVA世界,开源世界最流行(不开源应该也流行)的文档生成工具,生成的文档漂亮并且索引做的很好,boost等众多开源产品使用的家伙。虽然JAVA自带JAVADOC功能,但是为了统一,感觉都是用doxygen也没有什么不可以。(Linux Enable)

资源管理器:

freecommand:以前还以为是彻底告别TotalCommand了,结果原来还有免费的可以用啊。。。。虽然没有TotalCommand好用,典型的就是插入U盘不刷新,常用目录功能设计不合理。但是,免费的嘛。

 

即时通信:

MSN:企业专用-_-!没得选择。

QQ: 偶尔用用,大众选择.

 

比较工具:

WinMerge:最好的目录,文件比较工具肯定是Beyond compare,可惜是收费的。。。。于是,WinMerge稍微替代一下吧,而在源代码合并时使用的比较工具,WinMerge是最优秀的。

 

浏览器:

这个世界浏览器这么重要的东西竟然几乎全是免费的。。。。。。。。。而那么多小工具却都是收费的,有人能够给我解释一下吗?我解释一下,因为世界上所占份额最高的产品是MS垄断的Internel Explorer,所以其他软件公司没有办法收费。。。。。。。按照这样的逻辑,假如有一天Windows是免费的,那么,估计很难再有其他收费的操作系统.不是吗?

IE:为了兼容性的考虑,很多时候不得不使用,比如迅雷看看,比如网银,其他时候一般不使用。

FireFox:最常使用的浏览器,因为众多插件的存在,无疑是世界上最优秀的浏览器,事实上,对我来说Firefox已经不仅仅是个浏览器了。我使用Gmail Manager来关注Gmail,使用FlashGot+DownthemAll!来作为下载工具,使用Adblock Plus来控制广告,使用FireShot(仅Windows下可用)来对网页进行截图,使用FoxTab来管理众多的Tab,使用Weave+XMarks来管理书签。。。。。当然,还有tor套装。(Linux Enable)

Chrome:使用此浏览器主要用于测试一些javascript,毕竟其效率比较高.

 

笔记软件:

Evernote:以前使用的是Google Note,的确比较好用,但是因为Google Note已经停止开发了,所以将所有数据导入了Evernote中使用,每月有40M的使用空间限制,但是基本够用了,对于文本以外的东西支持的也非常好(比如图片)。网页版在Linux下可用,并且可以使用Firefox的evernote插件.

 

截图软件:

picpick:网页的截图使用FireFox的FireShot插件,普通的截图使用Evernote带的功能,已经基本够用,再复杂点的情况,截图,然后绘制一些指导性的文字和箭头时,picpick这样非常小巧好用的软件就非常适合了.

 

看图软件:

Picasa:因为很多优秀的看图软件都是个人使用免费却非商业的,IrfanView,XnView等软件我在家里用用还可以,但是他们是不允许商业使用的(non-commercial)的,(特别注意啊。。。)Picasa以前使用过,可能因为用惯了IrfanView,觉得太花,认为它是管理照片才用的,所以开始没有使用,事实上使用后觉得看看图也不错。

 

思维导图:

XMind:虽然freemind也是不错的软件,但是感觉XMind生成的图片更好看,所以嘛。。。呵呵,割舍freemind了。(Linux Enable)

 

输入法:

搜狗输入法:虽然常常做出匪夷所思的广告行为,但是总体而言,输入法还是搜狗的用的比较舒服。

 

图像编辑:

GIMP
:不说太好用,但是基本还行,也找不到更好的免费软件了。同时还做为不常见图片格式的查看工具(比如tga)(Linux Enable)

 

邮件客户端:

Thunderbird
:以前工作的时候连网都不能上,使用Gmail的时候也靠Firefox的Gmail Manager插件使用,不用专业的邮件客户端(当年的foxmail可是很出名,也用过,可是当时真的没有这个工作需求),使用Thunderbird的感觉还是不错的。(Linux Enable)

 

文件搜索:

Everything: 搜索速度的确是如善用佳软中所说的快到令人发指。。。。。。不用不知道,一用吓一跳,真的比Windows自身的快太多了,Google桌面虽然搜索功能还还行,可是太花,太拖累系统了,所以割爱放弃。

 

脚本工具:

AutoHotkey
:GUI的bash工具,强大无比。以前我有过专门的文章介绍。见《懒惰是程序员的美德! 懒惰程序员的最爱AutoHotkey 尝鲜

 

视频播放:

k-mplayer:韩国的一个播放软件,无广告,支持的视频总类多,可选信息丰富,支持高清加速,个人使用后没有再考虑过别的软件。(据说其使用GNU不开源。。。。。)

Realplayer: 作为k-mplayer的补充。(Linux Enable)

 

压缩软件:

7-Zip:虽然使用方便程度上与Winrar还有一定差距,但是哪叫它是免费开源的呢。。。。(Linux Enable)

 

虚拟桌面软件:

VirtualWin:非常方便,支持自定义快捷键,切换速度也比很多同类软件快的多。(Linux下自然就不需要了)

 

FTP工具

FileZilla:不仅仅又方便的FTP客户端,甚至还有服务器版本。。。。强大的无以复加。

 

电子词典:

stardict:特别注意金山词霸。。。。。。。个人免费(non-commercial),别被谷歌和到处免费的字眼混淆了,stardict虽然在屏幕捕获上有些问题,(用复制来代替就好了)其他方面还是很好的。(Linux Enable)

 

日程管理:

Google Calendar+Gmail+Task:基本上已经很好用了,事实上我以前试用过Chandler这个梦幻般的软件,可惜速度上实在无法接受。。。。Python啊Python…….也许在用JAVA编写的大型软件都会有人抱怨速度慢的今天(比如Eclipse),用Python编写。。。。速度上要让人接受并不容易啊。。。。(Linux Enable)

 

剪贴板增强工具:

Ditto:剪贴板的历史记录保存算是小功能,但是在没有办法使用Visual Assist的功能时,与autohotkey互补使用Ditto的命名剪贴功能,作为补充。

 

UML绘制

StarUML:刚开始离开了Rational Rose会有不习惯的感觉。。。。。但是发现了StarUML后,发现原来开源免费的软件不一定就比庞大著名的商业软件差,Rational Rose的逆向工程(从代码到UML)我就没有搞明白怎么用过,但是一拿到StarUML就会用,非常好用!不过工程大了的时候,UML图会有点卡。

更多我会安装的东西,一般人可能不需要了。

 

数学计算及可视化

scilab:法国出的很强大的软件,以前因为其与matlab的语法不兼容而选择了与matlab语法兼容的GNU Octave和freemat等,但是到了更高级的计算时,这两个软件根本无法胜任,这个两个软件仅仅只能作为简单数学的可视化工具而已,相关的toolbox太少,因此,无奈的选择了与matlab不兼容的道路...............(Linux Enable)

 

Unix环境:

Cygwin:让Windows有类似Unix的环境,贡献无论怎么评价都不过分,特别是bash及其shell的全套引入,习惯了Unix脚本管理的人使用起来方便没有极限,哪怕是简单的grep工具的使用,Windows下我也不知道有啥可以替代的。。。。

MingW:Windows下的gcc套件,虽然我自己不用,但是很多软件用到,比如Qt

目前有些软件在公司还没没有碰到需求,所以暂时没有列出来,此列表考虑长期更新吧,不仅给大家一个参考,自己假如碰到重新安装电脑的时候,也能一一的安装。

 

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com


阅读全文....

从剪贴板到剪贴板的通用语法高亮软件发布(支持N多语言)

 

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

 需求来源

    不太喜欢太限制于Windows下的Windows live
writer(以下简称WLW),虽然很多人认为它是博客写作工具的number
one,甚至看到有外国的朋友曾经高呼,Linux下唯一缺少替代品的软件就是WLW了,经过长久的使用,本身功能并不算太强大,但是开放的插件系统,让
其强大到无以复加,我在以前《windows
live
writer
试用及众多插件试用评测...



文中有很详细的描述,过程中也解决过很多WLW本身的问题,比如没有模板的问题,(通过autohotkey解决),比如说本地保存目录不能改变的问题,
(通过junction来改变)比如在公司及家中文档不能同步的问题,(通过dropbox),但是越依赖WLW,我就感觉越不舒服,因为我在Linux
下越来越感觉没有好用的博客写作工具了,而且WLW专有的格式,使得我无法太好的使用已有的文档,这些都是无法忽视的大问题,于是,最终,我决定彻底的迁
移到Google Document上来,无论是普通的文档,还是Blog的写作。

    首先有个先天性的问题,Google
Document是没有开发插件系统的,这样,碰到问题我们都没有办法通过扩展来解决,特别突出的问题就是代码高亮问题,对于程序员的博客。。。。。。贴
代码实在是太经常的事情了,不能解决此问题也是我以前甚至愿意用Word2007来写博客都不用Google
Document。既然今天决定了使用Google
Document,那么找个办法来解决此问题吧,方法目前想到一个,HTML的直接插入,(还好Google
Document支持),那么我只需要将代码在剪贴板中保存为高亮的HTML,然后直接嵌入Google Document就行了,So
Easy................解决此问题吧,于是就有了我的新工程“code-highlight-clipboard2clipboard
”,因为自己写语法分析及高亮的代码实在太麻烦了,只好选择站在巨人的肩膀上:)我利用GVim来解决此问题。(目前使用时需要自己先安装Gvim,并且将其目录加进PATH中,即在任何目录下都能通过gvim命令调用到gvim)

 

先看看效果

 

此文在Google Document下完成,以下是主体源代码的实际转换效果。还算是比较漂亮吧:)

 


 1
from
 optparse import
 OptionParser
 2
from
 distutils.file_util import
 *
 3
import
 os
 4
import
 tempfile
 5

 6
def

 main
():
 7
    
 8
    usage = 'usage: %prog [options]
'
 9
    version = '''%prog 0.1 Created By JTianLing

10
Any Question could be sent to JTianLing{at}Gmail.com,

11
and any advice or any bug report is appreciated too.
'''
12
    
13
    parser = OptionParser(usage, version = version)
14
    parser.add_option('-f
', '--filename
', metavar = 'FILE
', dest = 'filename
',
15
                      help = 'Write output to FILE and save it.
')
16
    parser.add_option('-t
', '--syntax
', action = 'store
',
17
                      type = 'string
', dest = 'syntax
',
18
                      default = '',
19
                      help = 'Set the code syntax type
')
20
    parser.add_option('-c
', '--color
', action = 'store
',
21
                      type = 'string
', dest = 'color
',
22
                      default = 'default
',
23
                      help = 'Set the code highlight color template
')
24
    parser.add_option('-n
', action= 'store_true
', dest = 'isNumber
',
25
                      default = False,
26
                      help = 'Is output with line number.
')
27
    (options, args) = parser.parse_args()
28
    
29
    filename = tempfile.mktemp() + '.tmp
'
30
        
31
    cboutStr = 'cbout >
' + filename
32
    os.system(cboutStr)
33
    
34
    syn = options.syntax
35
    color = options.color
36
    
37
    # ugly but useful vim's format code

38
    vimCmd = 'gvim -c ":syntax on|:color
' + color + '|:set syn=
' + syn/

39
     + '|:set nu
' + ('' if

 options.isNumber else

 '!
') + '|TOhtml" -c ":w|:qa"
' + filename
40
    os.system(vimCmd)
41
    #print(vimCmd)

42
    
43
    newFilename = filename + '.html
'
44
    cbinStr = 'more
' + newFilename + ' | cbin
'
45
    os.system(cbinStr)          
46

47
    # Del the temp file when that's needed

48
    if

 options.filename:
49
        move_file(newFilename, './
' + options.filename)
50
    else

:
51
        os.remove(newFilename)
52
        
53
    os.remove(filename)
54
    
55
if

 __name__ == '__main__
':
56
    main()

 

 

使用

 

除了以上的源代码,我还实现了两个类似于stdin及stdout的与剪贴板相关的cbin,cbout命令(clipboard in or out)。实际使用方法类似stdin及stdout,分别是写入剪贴版中及从剪贴板中读出数据,(只支持文本格式)

其实下一版预计还可以抽出整个转换的过程,那样使用起来可能更加灵活。目前此代码仅在Windows下测试,但是为了兼容,我使用了PyQt的库(所以狂大,其实才几行代码),将来会在Linux下测试及发布Linux的

二进制版本。

 

使用方法是在Google Document中通过(Edit->Edit Html->粘贴->Update),你也可以保存为任何你想要的文件/粘贴到你想要去的任何位置。

命令的使用方法如下:

 

>chc2c --help
Usage: chc2c [options]

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -f FILE, --filename=FILE
                        Write output to FILE and save it.
  -t SYNTAX, --syntax=SYNTAX
                        Set the code syntax type
  -c COLOR, --color=COLOR
                        Set the code highlight color template
  -n                    Is output with line number.

 

支持的语言

 

支持的语言种类/语法格式几乎囊括了常见的所有语言,(仅限制于Vim支持的种类,站在巨人的肩膀上就是好),以下是一个列表:

 


2html          a2ps
a65            aap            abap           abaqus
abc            abel           acedb          ada
aflex          ahdl           alsaconf       amiga
aml            ampl           ant            antlr
apache         apachestyle    arch           art
asm            asm68k         asmh8300       asn
aspperl        aspvbs         asterisk       asteriskvm
atlas          autohotkey     autoit         automake
ave            awk            ayacc          b
baan           basic          bc             bdf
bib            bindzone       blank          bst
btm            bzr            c              calendar
catalog        cdl            cdrdaoconf     cdrtoc
cf             cfg            ch             change
changelog      chaskell       cheetah        chill
chordpro       cl             clean          clipper
cmake          cmusrc         cobol          coco
colortest      conaryrecipe   conf           config
context        cpp            crm            crontab
cs             csc            csh            csp
css            cterm          ctrlh          cuda
cupl           cuplsim        cvs            cvsrc
cweb           cynlib         cynpp          d
dcd            dcl            debchangelog   debcontrol
debsources     def            denyhosts      desc
desktop        dictconf       dictdconf      diff
dircolors      diva           django         dns
docbk          docbksgml      docbkxml       dosbatch
dosini         dot            doxygen        dracula
dsl            dtd            dtml           dtrace
dylan          dylanintr      dylanlid       ecd
edif           eiffel         elf            elinks
elmfilt        erlang         eruby          esmtprc
esqlc          esterel        eterm          eviews
exim           expect         exports        fasm
fdcc           fetchmail      fgl            flexwiki
focexec        form           forth          fortran
foxpro         framescript    freebasic      fstab
fvwm           fvwm2m4        gdb            gdmo
gedcom         git            gitcommit      gitconfig
gitrebase      gitsendemail   gkrellmrc      gnuplot
gp             gpg            grads          gretl
groff          groovy         group          grub
gsp            gtkrc          haml           hamster
haskell        haste          hastepreproc   hb
help           hercules       hex            hitest
hog            hostconf       html           htmlcheetah
htmldjango     htmlm4         htmlos         ia64
ibasic         icemenu        icon           idl
idlang         indent         inform         initex
initng         inittab        ipfilter       ishd
iss            ist            jal            jam
jargon         java           javacc         javascript
jess           jgraph         jproperties    jsp
kconfig        kix            kscript        kwt
lace           latte          ld             ldapconf
ldif           lex            lftp           lhaskell
libao          lifelines      lilo           limits
lisp           lite           litestep       loginaccess
logindefs      logtalk        lotos          lout
lpc            lprolog        lscript        lsl
lss            lua            lynx           m4
mail           mailaliases    mailcap        make
man            manconf        manual         maple
masm           mason          master         matlab
maxima         mel            messages       mf
mgl            mgp            mib            mma
mmix           mmp            modconf        model
modsim3        modula2        modula3        monk
moo            mp             mplayerconf    mrxvtrc
msidl          msmessages     msql           mupad
mush           muttrc         mysql          named
nanorc         nasm           nastran        natural
ncf            netrc          netrw          nosyntax
nqc            nroff          nsis           objc
objcpp         ocaml          occam          omnimark
openroad       opl            ora            pamconf
papp           pascal         passwd         pcap
pccts          pdf            perl           pf
pfmain         php            phtml          pic
pike           pilrc          pine           pinfo
plaintex       plm            plp            plsql
po             pod            postscr        pov
povini         ppd            ppwiz          prescribe
privoxy        procmail       progress       prolog
promela        protocols      psf            ptcap
purifylog      pyrex          python         qf
quake          r              racc           radiance
ratpoison      rc             rcs            rcslog
readline       README.txt         rebol          registry
remind         resolv         reva           rexx
rhelp          rib            rnc            rnoweb
robots         rpcgen         rpl            rst
rtf            ruby           samba          sas
sass           sather         scheme         scilab
screen         sd             sdl            sed
sendpr         sensors        services       setserial
sgml           sgmldecl       sgmllnx        sh
sicad          sieve          simula         sinda
sindacmp       sindaout       sisu           skill
sl             slang          slice          slpconf
slpreg         slpspi         slrnrc         slrnsc
sm             smarty         smcl           smil
smith          sml            snnsnet        snnspat
snnsres        snobol4        spec           specman
spice          splint         spup           spyce
sql            sqlanywhere    sqlforms       sqlinformix
sqlj           sqloracle      sqr            squid
sshconfig      sshdconfig     st             stata
stp            strace         sudoers        svn
syncolor       synload        syntax         sysctl
tads           tags           tak            takcmp
takout         tar            tasm           tcl
tcsh           terminfo       tex            texinfo
texmf          tf             tidy           tilde
tli            tpp            trasys         trustees
tsalt          tsscl          tssgm          tssop
uc             udevconf       udevperm       udevrules
uil            updatedb       valgrind       vb
vera           verilog        verilogams     vgrindefs
vhdl           vim            viminfo        virata
vmasm          voscm          vrml           vsejcl
wdiff          web            webmacro       wget
whitespace     winbatch       wml            wsh
wsml           wvdial         xbl            xdefaults
xf86conf       xhtml          xinetd         xkb
xmath          xml            xmodmap        xpm
xpm2           xquery         xs             xsd
xslt           xxd            yacc           yaml
z8a            zsh            

 

 

是不是比目前存在的所有语法高亮工具支持的语言种类还要多?你要是说你懂的上面没有的语言,我一定认为你是神仙。。。。。。。。。。。。

 

好了,别的不多说了,自己下载试用吧,目前还是0.1版,以后会慢慢增加一些功能的,最主要的是找到一个精简版的vim(目前需要首先自己安装Vim才能使用,并将Vim的目录加入PATH中才能使用)

 

 

完整源代码获取说明

工程保管在Google上:http://code.google.com/p/code-highlight-clipboard2clipboard/

也可以直接使用Mercurial克隆下库:

https://code-highlight-clipboard2clipboard.googlecode.com/hg/

Mercurial使用方法见《分布式的,新一代版本控制系统Mercurial的介绍及简要入门

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

阅读全文....

迅雷官方手把手教你,一个下载软件中到底可以强行植入多少广告

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

参看来源:http://vip.xunlei.com/freedom/freedom_skinad.html

的确是官方权威资料。。。。。。。。不弄虚作假哦

image

其实,即使成为会员,迅雷下方的“资讯”还是无法屏蔽,这也是上面官方未提及的广告。。。。。。。。。

唉。。。互联网时代,要用一个好的下载软件就得忍受这么多东西。。。。。。说实话,我几乎天天使用迅雷,还有迅雷看看,但是却怎么都对迅雷提不起好感,(好像这样的软件及公司就迅雷一家了)不知道是不是我自己有问题。。。。。。。。起码,迅雷对于我,还算是免费提供服务。为啥我对Google的感觉好的多呢?唉。。。。都是广告公司,看看广告的水平就知道了。

何况,迅雷软件的很多流氓做法实在让人忍无可忍。。。。。。。迅雷老总不是说么?有的软件的流氓行为看起来很诱人,但是我们坚决不会做。。。。。注意,“有的”两字,其他自己体会。

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

十五种途径告诉你什么不是云计算

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

云计算最近炒的很火,这点不用我说了,但是我们知道什么是云计算吗?

可以参考一下《技术百科:什么是云计算(图文)》

但是,广大的云计算应用还是容易让人迷惑,今天看到国外的一篇文章,教你怎么去识别伪云计算及真正的云计算,有的很实在,有的很搞,算是异类,翻译过来,给大家一个参考,大家也可以以此对比一下,到底广大厂商各自炒作的产品是真是伪,也可纯粹作为娱乐。

原文来自《15 Ways to Tell Its Not Cloud Computing》:(实际十六条)

假如它提到“网格计算”和“开放式网格计算服务”。。。。。它不是一个真的云

假如你需要发送40页需求文档给服务器提供商才能获取服务。。。。。它不是一个真的云

假如你不能用自己的信用卡购买。。。。。它不是一个真的云

假如他们尝试卖你硬件。。。。。它不是一个真的云

假如没有一个API可供调用。。。。。它不是一个真的云

假如你需要为了它重新设计你的系统。。。。。。它不是一个真的云

假如它需要超过10分钟才能提供服务。。。。。。它不是一个真的云

假如你不能在10分钟之内终止服务。。。。。它不是一个真的云

假如你知道机器在哪。。。。。。它不是一个真的云

假如房子里还有个顾问。。。。它不是一个真的云

假如你需要预先支付你需要的机器数量。。。。。它不是一个真的云

假如它只能在一个操作系统中运行。。。。。。它不是一个真的云

假如你不能从你自己的机器上连接上它。。。。。它不是一个真的云

假如你需要为使用它而安装软件。。。。。它不是一个真的云

假如你拥有所有的硬件。。。。。。。。。。。它不是一个真的云

假如它需要花费20页幻灯片来解释。。。。。。它不是一个真的云

 

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- www.jtianling.com 

阅读全文....