girzel / ebdb

An EIEIO port of BBDB, Emacs' contact-management package
67 stars 11 forks source link

Can not search chinese with pinyin by "//" #23

Closed tumashu closed 7 years ago

tumashu commented 7 years ago

General search can not search chinese with pinyin, does it neet addition settings?

girzel commented 7 years ago

If you have ebdb-chn loaded, then contacts with Chinese names should be searchable using pinyin. Other fields (notes or what have you) won't be searchable with pinyin, only names.

tumashu commented 7 years ago

ebdb-chn have been loaded, but can not search

tumashu commented 7 years ago

Can't find how to deal with it , I need a configure simple to test.

girzel commented 7 years ago

You'll need to have ebdb-chn loaded before you load your EBDB contacts. The pinyin indexing happens at initialization time. Alternately, to test, you can run (ebdb-initialize) manually.

That's it, there's no other configuration...

tumashu commented 7 years ago

我英文不好,这一段话只能用中文了:

对于ebdb中文搜索,我根据以前 bbdb 折腾的经验,有三种方式:

1.为每一个中文 record 生成 pinyin 对应,然后用普通英文搜索,这是 bbdb-china 的工作模式,似乎也是当前 ebdb 拼音搜索的方式,但我现在认为这种模式有点傻.... 2.ebdb 通过搜索来筛选合适的记录, 这种模式,大多数都有一个类似 string-match-p 的函数,用来判断一个字符串是否和另一个字符串匹配,只要我们提供机制,让用户可以自定义这个函数,那搜索中文也非常容易实现, 我当时给bbdb提交了一个patch, 就是使用的这种模式,不过bbdb搜索工具用一个特别大的宏实现,我的patch没有打动维护者,所以被拒了;-(

  1. 第三种模式是:在搜索之前,对待搜索的字符串进行预处理,生成一个新的搜索字符串或者正则表达式,然后再搜索,这个模式只有两三个包在使用,pyim通过这种模式,添加了中文拼音搜索功能,可以用拼音搜索任意buffer种的中文

我的建议是: 让 ebdb 支持后两种方式,让用户可以自定义.实现起来难度也很低,如果你使用pyim, 可以试试下面的函数.

(pyim-isearch-build-search-regexp "nihao")
tumashu commented 7 years ago

突然想到,第二种模式和第三种模式,其实是一种模式: 自定义筛选工具

我们可以添加一个类似 obdb-filter-functions 的自定义变量:

(setq obdb-filter-functions '(func1 func2 func3 func4))

(defun obdb-string-match-p (str1 str2)
  (cl-some
   #'(lambda (func)
       (funcall func str1 str2))
   obdb-filter-functions))

只要任意一个 func1 func2 func3 func4 中任意一个返回 t ,就可以搜索出来, 用户可以简单的添加函数来设置适合自己的搜索方式。

girzel commented 7 years ago

我之前确实没有多想这个问题,我毕竟不是中国人,除了记录的名字、地址可能是中文之外,我自己很少会添加别的汉字内容。

其实,第二种可能性估计现在就可以实现。基本上所有搜索过程使用 `ebdb-search-read' 这个generic函数来组织搜索方法(是不是所有地方都用我得确认一下)。Generic functions 挺有弹性,我想下面这个编码就可以达到你想要的效果:

(cl-defmethod ebdb-search-read :around (field)
  (let ((criteria (cl-call-next-method)))
    (if (stringp criteria)
        criteria
      (pyim-isearch-build-search-regexp criteria)))

还没有测试,要不你试试看?如果遇到bugs,我很愿意及时修,这种customization EBDB应该尽可能支持。如果这样好用的话,我可以在ebdb-chn加一个选项让人关掉拼音的自动生成。

第三种模式我希望可以支持,但感觉这种功能不应该限于像EBDB这样的package,因为它对Emacs的更深层功能进行修改,应该在EBDB之外实现。不过,我正在看manual的"Keymaps for Translating Sequences of Events"这部分,可能会有一些新的想法。

girzel commented 7 years ago

呃,回答的时候没有发现你上面这条,其实我们说的是一个意思,只不过是我采取了 generic function 的方法来实现。

tumashu commented 7 years ago

好的,找个时间我测试一下,突然感觉clos值得学习一下了,等有时间,我也试着重构一下pyim。

tumashu commented 7 years ago

我想了一下,其实我们应该再添加一个类似 string-match-p 的广义函数,再这个地方可以同时处理第二种和第三种方案,而在ebdb-search-read处,只能用第三种方案,第二种方案,是功能最强大的方案,它可以实现n*h匹配 你好 和 你不好,这重匹配用第三种方案就很难实现了

girzel commented 7 years ago

但是,提供代替string-match-p的某个函数,跟在ebdb-search-read让用户自己做处理,我没有觉得有太大的区别。

EBDB现在有两个对应的函数:ebdb-search-read产生字符串,然后ebdb-field-search决定字符串是不是匹配某个field的内容(大部分用string-match-p)。两个都是generic functions,两个都可以让用户override或添加功能。我是说,第二和第三种方法之间好像没有那么大的区别,用这两个generic functions好像可以实现任何效果。

tumashu commented 7 years ago
但是,提供代替string-match-p的某个函数,跟在ebdb-search-read让用户自己做处理,我没有觉得有太大的区别。

两个都可以override那最好了, 我感觉两个区别还是比较大的, 总体来说,自定义 ebdb-field-search 更有看头。

tumashu commented 7 years ago

Can you gave me a example of overriding ebdb-field-search with pyim-hanzi2pinyin-simple?

tumashu commented 7 years ago

我用这个测试了一下,很好使,不过这个依赖最新的 pyim-hanzi2pinyin

(cl-defmethod ebdb-field-search :around (field criterion)
              (or (cl-call-next-method)
                  (let ((str (ebdb-string field)))
                    (when (stringp str)
                      (cl-some
                       #'(lambda (pinyin)
                           (string-match-p criterion pinyin))
                       `(,@(pyim-hanzi2pinyin str nil "" t)
                         ,@(pyim-hanzi2pinyin str t "" t)))))))
tumashu commented 7 years ago

不过,我发现无法搜索 notes,是不是ebdb当前没法搜索自定义field?

girzel commented 7 years ago

嗯,写notes式搜索时没有用ebdb-field-search,是个遗漏,一会儿修。

这种 :around 的 generic function 很方便,可以实现各种功能。我可能最终要按你的建议来做:给一个 custom option 让用户加自己的函数,这样只需要一个这样的:around,有太多:around不太好。

要不你先用那个:around函数用一段时间,没有发现别的问题我就加一个定制函数选项。

tumashu commented 7 years ago

ok

tumashu commented 7 years ago

对了, "alt name" 是一个内置的field吗?我的设置似乎不能搜索这个field,不知道什么原因

girzel commented 7 years ago

哦,对了。为了加快搜索,一个记录的所有名字都要放在cache里,然后搜索对象是这个cache,不是name fields本身。我原来的处理方法也会把所有name fields变成拼音,所以能用。

我可以让名字搜索直接搜name fields,只是怕会慢一些。

girzel commented 7 years ago

对了,建议你用这个:around method:

(cl-defmethod ebdb-field-search :around (field criterion)
  (or (cl-call-next-method)
      (when (stringp criterion)
    (let ((str (ebdb-string field)))
      (cl-some
       (lambda (pinyin)
         (string-match-p criterion pinyin))
       (append (pyim-hanzi2pinyin str nil "" t)
           (pyim-hanzi2pinyin str t "" t)))))))

其实要确认的是criterion是字符串,因为有的地方它不是。还有,lambda 不需要 quote。

tumashu commented 7 years ago

我大概有200条记录,搜索速度还是可以接受的,很好用

girzel commented 7 years ago

我有两千多记录!有时还是会感觉慢。不过无所谓,最重要是好不好使,以后想办法让它快一点。

tumashu commented 7 years ago

这两天我测试补齐,发现搜索速度确实需要优化, 200条记录补齐时有卡顿的感觉

girzel commented 7 years ago

Is that with using ebdb-handy/complete? Or what kind of completion?

tumashu commented 7 years ago

用handy弹出bbdb窗口的时候,稍微有些卡顿,对联系人循环的时候,也感觉有些卡,不过优化是缓慢的过程,不着急

girzel commented 7 years ago

I'm going to close this for now. This thread has touched on many issues, and most of them have mostly been addressed. Please open more issues for more specific problems!

tumashu commented 7 years ago

OK,虽然我不太了解,你为什么设置 ebdb-search-read 而不是 ebdb-field-search, 字符串转换有时候简单,但如果遇到正则表达式之类的,转换起来其实更麻烦一点,我唯一能想到的好处就是,性能可能好一点。

girzel commented 7 years ago

My thinking is that it would actually be easier this way! No matter what, you are constructing a regular expression to match the field value. You'll have to do that the same, whether in ebdb-search-read or ebdb-field-search. The big win is, you only do it once in ebdb-search-read, but you'll have to do it once per record field searched in ebdb-field-search. That could be a huge slowdown.

Anyway, there's no reason you can't keep using the :around method above, if you prefer that!

(I just got a new laptop and haven't figured out how to get fcitx working on it, so only English today, sorry!)