Emacs在Windows上使用的若干问题的解决

Emacs真是一款用得越久越觉得好用的软件,不过对应windows来说,它还是有点儿水土不服。以下是本人在使用中总结出的经验,希望能帮助新手。

1.使用哪个编译版本最适合”中日韩Windows”?
  NTEmacs,打过IME补丁的最新版:http://cha.la.coocan.jp/doc/NTEmacs.html
  原因是该版本解决了多语言输入的输入法问题。

2.如何配置最省心?
  参考这篇文章:使用purcell的配置快速上手Emacs

3.如何使用Server模式快速启动?
  error: The directory `~/.emacs.d/server’ is unsafe ?
  为什么一启动就这样呢?主要是Windows的权限管理和Unix系不太一样,重新配置一下server文件夹的NTFS权限即可。即,在NTFS权限里把”.emacs.d/server/“的权限收归个人用户,而不是群组Administrators
  server文件夹右键->安全->高级->所有者->编辑->确定->确定->确定

4.如何使用Emacsclientw快速连接?
5.如何让Emacs识别Unicode文件名?
  这两个问题一起解决,解决方式有点儿绕路,因为我的Lisp水平有限,所以用Python写了个Loader。
  unicode->utf8的转换是无损的,但unicode->local encoding的转换是有损的。NTFS里存放的文件名本身是Unicode的,但Windows转给命令行以后自动处理为local encoding,如此就造成了原文件名无法读取,所以需要让Emacs跨过Windows命令行直接识别unicode文件名。
  (本解决方案建立在所有encoding使用utf8的基础之上,如果你想使用gbk当作enviroment,那么转换损失无可避免,具体方案请参考评论1,好在中文操作系统下损失不明显,主要是因为中文字库字多。)

  先看注册表

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\*\shell\Emacs\command]
@="python.exe \"D:\\jhpx\\emacs\\PyEmacsclientwLoader.py\" \"%1\""

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Gnu\Emacs]
"HOME"="D:\\jhpx\\"
"EMACS_SERVER_FILE"="D:\\jhpx\\.emacs.d\\server\\server"
"ALTERNATE_EDITOR"="D:\\jhpx\\emacs\\bin\\runemacs.exe"

下面三条是指定一些环境变量,上面一条是真正的文件关联。即,不直接让注册表把%1交给Emacsclientw,转而使用一个Python脚本做为Loader,需要pywin32库的支持。

#!/usr/bin/env python
# -*- coding: utf8 -*-
# PyEmacsclientwLoader.py
# Author: Jiangmf
import sys
import subprocess
import win32com.client

def check_exsit(process_name):
    WMI = win32com.client.GetObject('winmgmts:')
    processCodeCov = WMI.ExecQuery(
        'select * from Win32_Process where Name="%s"' % process_name)
    return len(processCodeCov) > 0


def win32_unicode_argv():
    """Uses shell32.GetCommandLineArgvW to get sys.argv as a list of Unicode
    strings.
    """

    from ctypes import POINTER, byref, cdll, c_int, windll
    from ctypes.wintypes import LPCWSTR, LPWSTR

    GetCommandLineW = cdll.kernel32.GetCommandLineW
    GetCommandLineW.argtypes = []
    GetCommandLineW.restype = LPCWSTR

    CommandLineToArgvW = windll.shell32.CommandLineToArgvW
    CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(c_int)]
    CommandLineToArgvW.restype = POINTER(LPWSTR)

    cmd = GetCommandLineW()
    argc = c_int(0)
    argv = CommandLineToArgvW(cmd, byref(argc))
    if argc.value > 0:
        # Remove Python executable and commands if present
        start = argc.value - len(sys.argv)
        return [argv[i] for i in
                xrange(start, argc.value)]

if __name__ == "__main__":
    command = r'd:\jhpx\emacs\bin\emacsclientw.exe "'
    argv_utf8 = map(lambda x: x.encode('utf8'), win32_unicode_argv())
    # purge 1st argv since it's '...\PyEmacsclientwLoader.py'
    if check_exsit('emacs.exe'):
        # connect to the exsited server
        argv_output = argv_utf8[1:]
    else:
        # run a new server and connect to it
        argv_output = sys.argv[1:]
    command += ' '.join(argv_output)
    command += '"'
    subprocess.Popen(command)

6.为什么不以gbk作为filename-coding转而用python loader如此麻烦的形式?
  我经常在日文OS与中文OS下交叉工作,想一劳永益。