Citre: 先进的 Ctags 前端

谢谢。我只是个普通的家庭 pc 用户,工作上也没有这个需要,所以一直没有用过 tramp。

我先试试用自己的两台本本能不能搞起来,不行的话就麻烦你啦

感谢楼主! :rofl:

不一定需要远程主机,可以对本地文件通过 ssh 访问,如:/sshx:localhost:~/foo/bar

另外想问一下 haskell 的使用体验好如何?原来 ghc 内建了生成 ctags。 我看了一眼 utags 代码里支持语言的实现,感觉除了 c家族,java 等几个外看起来都有点简陋

谢谢!这就去试

我个人不用 haskell,所以不太清楚。想知道支持得怎么样,一个办法是看 Units/parser-语言.r/ 下面的测试用例。

我个人感觉 python 和 julia 的支持还是不错的,看上去 Ruby 和 JavaScript 应该也不错。

这个问题应该已经修复了:

(citre-core-filter-input (buffer-file-name) (citre-tags-file-path))
=> (or
     (and $input
          (eq\? $input "D:/home/chromium-master/citre-test.c"))
     (and $input
          (eq\? $input "citre-test.c")))

现在统一用「相对路径或绝对路径」来过滤文件名。我在 Windows 上也用 Citre 读了下代码,没有碰到问题。

可以试一下 develop 分支吗?已经实现了 TRAMP 支持,但是在 localhost 上测试的,没有在真正的远程机器上测试。

哇感谢楼主这么晚了还在忙citre!develop分支现在工作的非常完美!谢谢楼主!!!

对了楼主可以在gh开一下打赏链接吗(

Great!

谢谢你 :wink: 我计划把最近收到比较迫切的需求实现之后发 0.1 版本,多少算是一个「我会根据社区意见来改进 Citre」的证明。到时会放一个收款码。

其实最近一直在考虑怎么收老外的钱。我倒是有 paypal,但是通过 paypal 收钱很难不暴露全名,从网上的情报来看提现也很困难。

1 个赞

stackexchange回答

建议楼主可以像这样放几个5刀的链接给老外用

个人感觉提现可以直接提到银行卡里面?

:rofl: paypal.me 就是隐藏不了名字的。然后提现的时候,据说国内银行可能会不给你入账。这个我之后慢慢操心吧 :rofl:

23333祝楼主好运!

谢谢,确实修复了

楼主,在使用tramp的时候,似乎发现了一个小错误?不是很清楚这个是怎么出现的

错误是

citre-core--get-lines: readtags exits 1
COMPILE ERROR: unbound-variable: helm-ff-file
MEMORY EXHAUSTED or SYNTAX ERROR
Failed to compile the expression of filter: (not (or (and $extras ((string->regexp "(^|,) ?(anonymous|inputFile)(,|$)" :case-fold false) $extras)) (and $kind ((string->regexp "^(file|F)$" :case-fold false) $kind)) (and (not (or (and $input (eq\? $input #("/scp:<blurred>/arm_gicv3_cpuif.c" 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)))) (and $input (eq\? $input "hw/intc/arm_gicv3_cpuif.c")))) (or $file (and $extras ((string->regexp "(^|,) ?(fileScope)(,|$)" :case-fold false) $extras))))))

backtrace是

Debugger entered--Lisp error: (error "readtags exits 1\nCOMPILE ERROR: unbound-variable: ...")
  signal(error ("readtags exits 1\nCOMPILE ERROR: unbound-variable: ..."))
  error("readtags exits 1\nCOMPILE ERROR: unbound-variable: ...")
  citre-core--get-lines(#("/scp:<blurred>/ta..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) #("extract64" 0 9 (citre-tags-file #("/scp:<blurred>/ta..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) citre-file-path #("/scp:<blurred>/hw..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) citre-syntax function citre-bounds (1372 . 1381))) exact nil (not (or (and $extras ((string->regexp "(^|,) ?(anonymous|inputFile)(,|$)" :case-fold false) $extras)) (and $kind ((string->regexp "^(file|F)$" :case-fold false) $kind)) (and (not (or (and $input (eq\? $input ...)) (and $input (eq\? $input "hw/intc/arm_gicv3_cpuif.c")))) (or $file (and $extras ((string->regexp "(^|,) ?(fileScope)(,|$)" :case-fold false) $extras)))))) (<or> (<or> (<> (if (and $extras ((string->regexp "(^|,) ?(reference)(,|$)" :case-fold false) $extras)) 1 -1) (if (and &extras ((string->regexp "(^|,) ?(reference)(,|$)" :case-fold false) &extras)) 1 -1))) (<or> (<> (if (or (and $kind (... $kind)) (and $kind (... $kind))) -1 1) (if (or (and &kind (... &kind)) (and &kind (... &kind))) -1 1))) (<or> (if (and $input &input) (<> $input &input) 0) (if (and $name &name) (<> (length $name) (length &name)) 0) (if (and $name &name) (<> $name &name) 0))) nil)
  citre-core--get-tags(#("/scp:<blurred>/ta..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) #("extract64" 0 9 (citre-tags-file #("/scp:<blurred>/ta..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) citre-file-path #("/scp:<blurred>/hw..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) citre-syntax function citre-bounds (1372 . 1381))) exact nil :filter (not (or (and $extras ((string->regexp "(^|,) ?(anonymous|inputFile)(,|$)" :case-fold false) $extras)) (and $kind ((string->regexp "^(file|F)$" :case-fold false) $kind)) (and (not (or (and $input (eq\? $input ...)) (and $input (eq\? $input "hw/intc/arm_gicv3_cpuif.c")))) (or $file (and $extras ((string->regexp "(^|,) ?(fileScope)(,|$)" :case-fold false) $extras)))))) :sorter (<or> (<or> (<> (if (and $extras ((string->regexp "(^|,) ?(reference)(,|$)" :case-fold false) $extras)) 1 -1) (if (and &extras ((string->regexp "(^|,) ?(reference)(,|$)" :case-fold false) &extras)) 1 -1))) (<or> (<> (if (or (and $kind (... $kind)) (and $kind (... $kind))) -1 1) (if (or (and &kind (... &kind)) (and &kind (... &kind))) -1 1))) (<or> (if (and $input &input) (<> $input &input) 0) (if (and $name &name) (<> (length $name) (length &name)) 0) (if (and $name &name) (<> $name &name) 0))) :require (name ext-abspath pattern) :optional (ext-kind-full line typeref extras) :exclude nil :parse-all-fields nil)
  citre-core-get-tags(#("/scp:<blurred>/ta..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) #("extract64" 0 9 (citre-tags-file #("/scp:<blurred>/ta..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) citre-file-path #("/scp:<blurred>/hw..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) citre-syntax function citre-bounds (1372 . 1381))) exact nil :filter (not (or (and $extras ((string->regexp "(^|,) ?(anonymous|inputFile)(,|$)" :case-fold false) $extras)) (and $kind ((string->regexp "^(file|F)$" :case-fold false) $kind)) (and (not (or (and $input (eq\? $input ...)) (and $input (eq\? $input "hw/intc/arm_gicv3_cpuif.c")))) (or $file (and $extras ((string->regexp "(^|,) ?(fileScope)(,|$)" :case-fold false) $extras)))))) :sorter (<or> (<or> (<> (if (and $extras ((string->regexp "(^|,) ?(reference)(,|$)" :case-fold false) $extras)) 1 -1) (if (and &extras ((string->regexp "(^|,) ?(reference)(,|$)" :case-fold false) &extras)) 1 -1))) (<or> (<> (if (or (and $kind (... $kind)) (and $kind (... $kind))) -1 1) (if (or (and &kind (... &kind)) (and &kind (... &kind))) -1 1))) (<or> (if (and $input &input) (<> $input &input) 0) (if (and $name &name) (<> (length $name) (length &name)) 0) (if (and $name &name) (<> $name &name) 0))) :require (name ext-abspath pattern) :optional (ext-kind-full line typeref extras) :exclude nil :parse-all-fields nil)
  citre-get-tags(#("/scp:blurred/ta..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) #("extract64" 0 9 (citre-tags-file #("/scp<blurred>/ta..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) citre-file-path #("/scp:<blurred>/hw..." 1 4 (helm-ff-file t) 5 14 (helm-ff-file t)) citre-syntax function citre-bounds (1372 . 1381))) exact :filter (not (or (and $extras ((string->regexp "(^|,) ?(anonymous|inputFile)(,|$)" :case-fold false) $extras)) (and $kind ((string->regexp "^(file|F)$" :case-fold false) $kind)) (and (not (or (and $input (eq\? $input ...)) (and $input (eq\? $input "hw/intc/arm_gicv3_cpuif.c")))) (or $file (and $extras ((string->regexp "(^|,) ?(fileScope)(,|$)" :case-fold false) $extras)))))) :sorter (<or> (<or> (<> (if (and $extras ((string->regexp "(^|,) ?(reference)(,|$)" :case-fold false) $extras)) 1 -1) (if (and &extras ((string->regexp "(^|,) ?(reference)(,|$)" :case-fold false) &extras)) 1 -1))) (<or> (<> (if (or (and $kind (... $kind)) (and $kind (... $kind))) -1 1) (if (or (and &kind (... &kind)) (and &kind (... &kind))) -1 1))) (<or> (if (and $input &input) (<> $input &input) 0) (if (and $name &name) (<> (length $name) (length &name)) 0) (if (and $name &name) (<> $name &name) 0))) :require (name ext-abspath pattern) :optional (ext-kind-full line typeref extras))
  citre-get-definitions()
  citre-peek--get-def-list()
  citre-peek--make-session(#<buffer arm_gicv3_cpuif.c> 1375)
  citre-peek()
  funcall-interactively(citre-peek)
  call-interactively(citre-peek nil nil)
  command-execute(citre-peek)

ctags 可以扫描 python 自带的或者第三方的包吗,比如 numpy, pytorch 之类的,这样就可以对这些包也进行补全了。我看了下文档没有找到如何生成,还望赐教。

谢谢报告。这个是因为 Emacs 的字符串可以带 properties,被格式化成 readtags DSL 表达式的时候,没有先把 properties 清除掉,导致转换出来的不是:

"一个字符串"

而是

#("一个字符串",其中从哪到哪具有什么 property)

等晚上我修一下。其实我一直担心有这个问题,只是目前还没有见到。

可以的。你可以在命令行最后添加那些路径:

$ ctags ... -R . /path/to/numpy /path/to/scipy

或者等我把生成 tags 文件的向导做出来,应该就是这两天的事。

1 个赞

嗯嗯,试用了下,可以的,不过就是需要手动来添加,有一些麻烦,还要慢慢摸索一下 ctags :slight_smile:

Update: 是不是可以把 python 的这些 package 手动一次性生成一个 tags 文件,然后在每个项目中去引入这个文件,这样就不用为每个项目来生成这些外部包的 tags 了

目前 Citre 只能从一个 tags 文件中获取信息,这个有很多理由。。。你说的这个其实我一直有考虑,但问题也不少,比方说目前排序的工作都是 readtags 做的,如果用多个 tags 文件的话,就不得不在 elisp 里面再排一次序了。而且要多起几个进程,Windows 用户更加受不了了。

目前折中的办法是先 tag 外部库。要 tag 工程的时候,把外部库的 tags 文件复制过来,再用 -a 选项把新扫到的 tags 加进去。这样不用每次更新都重新 tag 外部库。这个事我也考虑一下怎么把它弄得易用一些。

Edit: 其实用多个 tags 文件也好,合并多个也好,增量更新也好,共同的最大问题就是怎么保证它们用的是同一套命令行参数(不然里面格式都不一致),以及 tag 的根目录不一样的时候怎么办。

嗯嗯,感谢楼主

在 develop 分支已经修复,你测试一下?