使用 emacs 的时间不算很长 了解点 elisp 的皮毛
写了几行 elisp 的代码 代码的作用就是从一个文本文件中提取用于补全的代码
下面附有代码(抱歉 没有测试 没有版本号 没有依赖 没有配置 是 compamy 而不是 auto-complete 在别人的机器上应该运行不了)
;;; company-chong.el --- company-mode completion back-end for aid_files
;; Author: Zhou Chong
;; This file is Not part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(eval-when-compile (require 'cl))
(require 'company)
(defgroup company-chong nil
"Completion back-end for chong."
:group 'company)
(defcustom company-chong-ignore-case nil
"Non-nil to ignore case in completion candidates."
:type 'boolean)
(defun company-chong-read-data ()
"从文件中提取一段代码 并将其分割成多个补全方式"
(save-excursion
(let ((start (line-end-position))
end parts)
(if (search-forward-regexp "\n<\\([^>]+\\)>" nil t)
(setq end (line-beginning-position))
(setq end (point-max)))
(setq parts (buffer-substring start end))
(setq parts (split-string parts "\n\s*<<" t))
parts)))
;;(company-chong-read "/Users/mac/Downloads/emacs-24.1/lisp/company-mode-0.7.3/chong/sqlite.txt")
(defun company-chong-read (file)
"用于从文件中得到数据"
(let (title data
(file-hash (make-hash-table :test 'equal)))
(unless (file-exists-p file)
(error "`company-chong-read' file not exist :%s" file))
(with-temp-buffer
(insert-file-contents file)
(goto-char 1)
(while (search-forward-regexp "\n<\\([^>]+\\)>" nil t)
(setq title (match-string 1))
(message "%s" title)
;; 接下来就是从中提取数据了 数据要能够得到一段的描述
(setq data (company-chong-read-data))
(puthash title data file-hash)))
file-hash))
(defun company-chong-add-hash (file title data)
"用于将数据加入到与文件对应的hash中" ;; data中的数据是包含多个 sub title>> 的
)
(defvar company-chong-hash (make-hash-table :test 'equal)
"用于存储从文件中得到的数据")
(make-local-variable 'company-chong-hash)
(defvar company-chong-hash-all-mode (make-hash-table :test 'equal)
"所有mode中的hash都在这里")
(defun company-chong-add-file (file cur-mode)
"添加新的文件到数据库中 文件的路径一定要是绝对的路径
并且会覆盖原来系统文件的数据"
(chong-debug nil
(message "`company-chong-add-file' file:%s mode:%s" file cur-mode))
(let ((cur-mode-hash (gethash cur-mode company-chong-hash-all-mode))
(old-data )
(new-data (company-chong-read file)))
(unless cur-mode-hash
(setq cur-mode-hash (make-hash-table :test 'equal))
(puthash cur-mode cur-mode-hash company-chong-hash-all-mode))
(setq company-chong-hash cur-mode-hash)
(setq old-data (gethash file company-chong-hash))
(when old-data (message "old-data be overwrited :%s" file))
(puthash file new-data company-chong-hash)
;;(print company-chong-hash)
;;(print cur-mode-hash)
(message "new-data OK :%s" file)))
;;(print (company-chong--candidates "lis"))
(defun company-chong--candidates (prefix)
"用于得到文件中的补全
补全不仅要得到一行 还要能得到一段"
(let (ret candi-item)
(chong-debug
(message "`company-chong--candidates' the buffer is %s"
(buffer-name (current-buffer))))
(maphash
(lambda (file file-hash)
(maphash
(lambda (title data)
(when (string-match prefix title)
(setq candi-item
(propertize title 'data data 'file file))
(setq ret (cons candi-item ret))
))
file-hash))
company-chong-hash)
;;(print ret)
ret))
(defun company-chong--annotation (candidate) ; 我可以让他得到更多的meta 进而得到更多的补全
"其实就是得到原来存储的meta" ; 或是用另外的一种方法
(let ((meta (company-chong--meta candidate))
(metas))
(message "Meta->>>>")
(print meta)
(message "company-chong--annotation")
(print (cond
((null meta)
(message "Error meta is nil")
nil)
(t
(setq metas (company-chong-subtitles meta))
(message "Metas >>>>>")(print metas)
(company-abort)
(setq meta (popup-menu* metas))
)))))
(defun company-chong-subtitles (subtitles)
"参数是一个list 得到list中的第一个含有>>的行"
(let (sub-title title data ret)
(mapc
(lambda (subtiltle)
(setq sub-title (split-string subtiltle "\n"))
(while (and sub-title (not (string-match ">>" (car sub-title))))
(setq sub-title (cdr sub-title)))
(setq title (car sub-title))
(setq sub-title (cdr sub-title))
(setq data (mapconcat (lambda (it) it) sub-title "\n"))
(when title (setq ret (cons (propertize title 'data data) ret)))
)
subtitles)
ret))
(defun company-chong--meta (candidate)
(let (my-candi
(cands company-candidates))
(mapc
(lambda (cand)
(when (equal cand candidate)
(setq my-candi cand)))
cands)
(setq ret (get-text-property 0 'data my-candi))
(unless ret (error "`company-chong--meta' error ,no data"))
;;(print "company-chong--meta") (print ret)
ret))
(defun company-chong--annotation-1 (candidate) ; 我可以让他得到更多的meta 进而得到更多的补全
"其实就是得到原来存储的meta" ; 或是用另外的一种方法
(let ((meta (company-chong--meta candidate)))
(cond
((null meta) nil)
((stringp meta)
(substring meta 0 100))
((listp meta)
(let (sub-title)
(concat
" "
(mapconcat
(lambda (subtiltle)
(setq sub-title (split-string subtiltle "\n"))
(while (and sub-title (not (string-match ">>" (car sub-title))))
(setq sub-title (cdr sub-title)))
(car sub-title))
meta " ")))))))
(defun company-chong-init ()
"初始化每个buffer"
(interactive)
(company-chong-load-file))
;;;###autoload
(defun company-chong (command &optional arg &rest ignored)
"`company-mode' completion back-end for chong aid files."
(interactive (list 'interactive))
(case command
(interactive (company-begin-backend 'company-chong))
(init (company-chong-load-file)
(message "company-chong load files OK")
t)
(prefix (and
(not (company-in-string-or-comment))
;;(or (> (hash-table-count company-chong-hash) 0)
;;(message "`company-chong-hash' count ==0 ,use (company-chong-add-file file) to add file"))
(or (company-grab-symbol) 'stop)))
(candidates (company-chong--candidates arg))
(meta (company-chong--annotation-1 arg))
(annotation (company-chong--annotation-1 arg))
(post-completion (let* ((ttt (print arg))
(anno (company-chong--annotation arg))
(ttx (print anno))
data)
(print anno)
(when anno ;;(insert anno)
(message "anno %s" anno)
(setq data (get-text-property 0 'data anno))
(message "应该注释掉当前的行")
(insert "\n" data)
)))
(location (let ((prefix company-prefix)
(file (get-text-property 1 'file arg)))
(let ((buffer (find-file file)))
(cons buffer
(with-current-buffer buffer
(goto-char 1)
(search-forward-regexp (concat "\n<" arg) nil t)
(point))))))))
(defvar company-chong-load-file
"根据不同的mode 装载不同的txt文件")
(setq company-chong-load-file
(list
'(ruby-mode ("/Users/mac/ruby/ruby.txt"))
'(emacs-lisp-mode ("/Users/mac/Elisp/elisp.txt"))
))
(defun company-chong-load-file ()
"会根据不同的mode 装载不同的txt文件"
(let* ((cur-mode major-mode)
(files (cadr (assq cur-mode company-chong-load-file))))
(if (not files)
(message "`company-chong-load-file' not found files for this mode")
(mapc
(lambda (file)
(company-chong-add-file file cur-mode))
files))))
(defun chong-move-next ()
"用于移动到下一个节点 会根据当前的节点移动
比如说 当前处于 <class> 则会移动到下一个 <>
当前处于 <<attribute >> 则会移动到下一个 <<>>"
(interactive)
(let ((line (current-line)))
(cond
((string-match "^<[^>]+>" line)
(end-of-line)
(search-forward-regexp "\n<" nil t))
((string-match "^\s*<<[^>]+>>" line)
(end-of-line)
(search-forward-regexp "\n\s*<<" nil t))
(t
(search-forward-regexp "\n<" nil t)
))))
(provide 'company-chong)
;;; company-chong.el ends here
;;; company-chong.el --- company-mode completion back-end for org-files
;; Copyright (C) 2015 Free Software Foundation, Inc.
;; Author: Zhou Chong
;; This file is Not part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see http://www.gnu.org/licenses/.
;;; Commentary: ;;
;;; Code:
(eval-when-compile (require 'cl)) (require 'company)
(defgroup company-chong nil "Completion back-end for chong." :group 'company)
(defcustom company-chong-ignore-case nil "Non-nil to ignore case in completion candidates." :type 'boolean)
(defun company-chong-read-data () "从文件中提取一段代码 并将其分割成多个补全方式" (save-excursion (let ((start (line-end-position)) end parts) (if (search-forward-regexp "\n\\s\([^\n]+\)" nil t) (setq end (line-beginning-position)) (setq end (point-max))) (setq parts (buffer-substring start end)) (setq parts (cdr (split-string parts "\n\s\*\*\s" t))) parts)))
;;(company-chong-read "/Users/mac/Downloads/emacs-24.1/lisp/company-mode-0.7.3/chong/sqlite.txt")
(defun company-chong-read (file) "用于从文件中得到数据" (let (title data (file-hash (make-hash-table :test 'equal))) (unless (file-exists-p file) (error "`company-chong-read' file not exist :%s" file)) (with-temp-buffer (insert-file-contents file) (goto-char 1) (while (search-forward-regexp "\n\*\s\([^\n]+\)" nil t) (setq title (match-string 1)) (message "%s" title) ;; 接下来就是从中提取数据了 数据要能够得到一段的描述 (setq data (company-chong-read-data)) (puthash title data file-hash))) file-hash))
(defun company-chong-add-hash (file title data) "用于将数据加入到与文件对应的 hash 中" ;; data 中的数据是包含多个 sub title>> 的 )
(defvar company-chong-hash (make-hash-table :test 'equal) "用于存储从文件中得到的数据") (make-local-variable 'company-chong-hash)
(defvar company-chong-hash-all-mode (make-hash-table :test 'equal) "所有 mode 中的 hash 都在这里")
(defun company-chong-add-file (file cur-mode) "添加新的文件到数据库中 文件的路径一定要是绝对的路径 并且会覆盖原来系统文件的数据" (chong-debug nil (message "`company-chong-add-file' file:%s mode:%s" file cur-mode)) (let ((cur-mode-hash (gethash cur-mode company-chong-hash-all-mode)) (old-data ) (new-data (company-chong-read file))) (unless cur-mode-hash (setq cur-mode-hash (make-hash-table :test 'equal)) (puthash cur-mode cur-mode-hash company-chong-hash-all-mode)) (setq company-chong-hash cur-mode-hash) (setq old-data (gethash file company-chong-hash)) (when old-data (message "old-data be overwrited :%s" file)) (puthash file new-data company-chong-hash) ;;(print company-chong-hash) ;;(print cur-mode-hash) (message "new-data OK :%s" file)))
;;(print (company-chong--candidates ""))
(defun company-chong--candidates (prefix) "用于得到文件中的补全 补全不仅要得到一行 还要能得到一段" (let (ret candi-item) (chong-debug (message "`company-chong--candidates' the buffer is %s" (buffer-name (current-buffer)))) (maphash (lambda (file file-hash) (maphash (lambda (title data) (when (string-match prefix title) (setq candi-item (propertize title 'data data 'file file)) (setq ret (cons candi-item ret)) )) file-hash)) company-chong-hash) ;;(print ret) ret))
(defun company-chong--annotation (candidate) ; 我可以让他得到更多的 meta 进而得到更多的补全 "其实就是得到原来存储的 meta" ; 或是用另外的一种方法 (let ((meta (company-chong--meta candidate)) (metas)) (message "Meta->>>>") (print meta) (message "company-chong--annotation") (print (cond ((null meta) (message "Error meta is nil") nil) (t (setq metas (company-chong-subtitles meta)) (message "Metas >>>>>")(print metas) (company-abort) (setq meta (popup-menu* metas)) )))))
(defun company-chong-subtitles (subtitles) "参数是一个 list 得到 list 中的第一个含有>>的行" (let (sub-title title data ret) (mapc (lambda (subtiltle) (setq sub-title (split-string subtiltle "\n")) (setq title (car sub-title)) (message "title %s" title) (setq sub-title (cdr sub-title)) (setq data (mapconcat (lambda (it) it) sub-title "\n")) (when title (setq ret (cons (propertize title 'data data) ret))) ) subtitles) ret))
(defun company-chong--meta (candidate) (let (my-candi (cands company-candidates)) (mapc (lambda (cand) (when (equal cand candidate) (setq my-candi cand))) cands) (setq ret (get-text-property 0 'data my-candi)) (unless ret (error "`company-chong--meta' error ,no data")) ;;(print "company-chong--meta") (print ret) ret))
(defun company-chong--annotation-1 (candidate) ; 我可以让他得到更多的 meta 进而得到更多的补全 "其实就是得到原来存储的 meta" ; 或是用另外的一种方法 (let ((meta (company-chong--meta candidate))) (cond ((null meta) nil) ((stringp meta) ;;(message "yyyyyyyy") (substring meta 0 100)) ((listp meta) (let (sub-title) (concat " " (mapconcat (lambda (subtiltle) (setq sub-title (split-string subtiltle "\n")) (car sub-title)) meta " ")))))))
(defun company-chong-init () "初始化每个 buffer" (interactive) (company-chong-load-file))
;;;###autoload
(defun company-chong (command &optional arg &rest ignored)
"company-mode' completion back-end for chong aid files."
(interactive (list 'interactive))
(case command
(interactive (company-begin-backend 'company-chong))
(init (company-chong-load-file)
(message "company-chong load files OK")
t)
(prefix (and
(not (company-in-string-or-comment))
;;(or (> (hash-table-count company-chong-hash) 0)
;;(message "
company-chong-hash' count ==0 ,use (company-chong-add-file file) to add file"))
(or (company-grab-symbol) 'stop)))
(candidates (company-chong--candidates arg))
(meta (company-chong--annotation-1 arg))
(annotation (company-chong--annotation-1 arg))
(post-completion (let* ((ttt (print arg))
(anno (company-chong--annotation arg))
(ttx (print anno))
data)
(print anno)
(when anno ;;(insert anno)
(message "anno %s" anno)
(setq data (get-text-property 0 'data anno))
(message "应该注释掉当前的行")
(insert "\n" data)
)))
(location (let ((prefix company-prefix)
(file (get-text-property 1 'file arg)))
(let ((buffer (find-file file)))
(cons buffer
(with-current-buffer buffer
(goto-char 1)
(search-forward-regexp (concat "\n* " arg) nil t)
(point))))))))
(defvar company-chong-load-file "根据不同的 mode 装载不同的 txt 文件") (setq company-chong-load-file (list '(ruby-mode ("/Users/mac/ruby/ruby.txt")) '(emacs-lisp-mode ("/Users/mac/Elisp/elisp.txt")) ))
(defun company-chong-load-file () "会根据不同的 mode 装载不同的 txt 文件" (let* ((cur-mode major-mode) (files (cadr (assq cur-mode company-chong-load-file)))) (if (not files) (message "`company-chong-load-file' not found files for this mode") (mapc (lambda (file) (company-chong-add-file file cur-mode)) files))))
;;; -----------------下面的函数是用来辅助编辑的
(defun ruby-run-current-region () "通过搜索两个注释行 确定要执行的代码" (interactive) (let (start end str temp-buf) (save-excursion (if (not (search-forward-regexp "\n#" nil t)) (setq end (point-max)) (line-move -1) (setq end (line-end-position)))) (save-excursion (if (not (search-backward-regexp "\n#" nil t)) (setq start 1) (line-move 2) (setq start (line-beginning-position)))) (setq str (buffer-substring-no-properties start end)) (setq temp-buf (find-buffer-visiting "~/zx.rb")) (unless temp-buf (setq temp-buf (find-file "~/zx.rb"))) (with-current-buffer temp-buf (erase-buffer) (insert str)(my-ruby-run))))
;;--- 给 ruby 添加测试功能
(defun ruby-test-region () "得到所有的 class 区间 主要是针对 class 来写的 对于 modeule 也是一样的" )
(defun ruby-test-region-str () "通过上面的 region 得到中所有的 ##T str")
(defun ruby-test-region-gene () "根据 ##T str 生成一个测试函数")
(defun ruby-test-gene2class () "根据所有的测试函数生成测试类")
;; # require "test/unit" ;; # class TestSongList < Test::Unit::TestCase ;; # def test_delete ;; # nil ;; # end ;; # end
;;--- 我追加的代码
(defvar my-ruby-output nil "记录输出的数据用的")
(defun my-ruby-filter (proc data) "只是添加数据而已" (setq my-ruby-output (concat my-ruby-output data)) )
(defun my-ruby-sent (proc data) "只是添加数据而已" ;; (message "OK") (if (null my-ruby-output) (popup-tip "请用 puts 或 print 输出") (popup-tip my-ruby-output)))
(defun run-ruby-chong () "定义我自己的方法 用于显示 ruby 的结果" (interactive) (let (proc (file (buffer-file-name (current-buffer)))) (save-buffer) (setq proc (start-process "ruby" "Ruby" "ruby" file)) (setq my-ruby-output nil) ;清空缓存 (set-process-filter proc 'my-ruby-filter) (set-process-sentinel proc 'my-ruby-sent) ))
;; 你可以修改的部分
(defvar my-edit-replace-word '("1" "
2" "3")
"用于搜索并替换的hook-word 比如 \1
1 等")
(defun my-edit-of-select () "得到用户的选定行 如果有区间就用区间 否则当前的行" (let (ret (region (region-active-p))) (if region (buffer-substring (region-beginning)(region-end)) (buffer-substring (line-beginning-position)(line-end-position)))))
(defun my-edit-of-tokens (edit-line) "用逗号将句子分开 可以用 => 表示关联" (when (string-match "def\s+[a-zA-Z0-9_!?=]+(\(.\))" edit-line) (setq edit-line (match-string 1 edit-line))) (let ((tokens (split-string edit-line "\s,\s*"))) (print tokens) (mapcar (lambda (str) (with-temp-buffer (insert str) (while (looking-back "\s") (delete-char -1 ) ) (goto-char 1) (while (looking-at "\s") (delete-char 1 ) ) (buffer-string))) tokens) )) ;; (my-edit-of-tokens " zhou ,chong ") ;; (define-key popup-isearch-keymap [return] 'popup-isearch-done)
(defun* edit-arg-chong (tokens &key (cursor-color popup-isearch-cursor-color) (keymap popup-isearch-keymap) callback help-delay) "编辑各个单词 并用 pattern 替换" (interactive "P") (let ((list (or tokens (my-edit-of-tokens (my-edit-of-select)))) (pattern "") (main-win (selected-window)) prompt key binding) (unwind-protect (block nil (while t (setq prompt (concat "Use:" pattern)) (setq key (popup-menu-read-key-sequence keymap prompt help-delay)) (if (null key) (unless (funcall popup-menu-show-quick-help-function popup nil :prompt prompt) (clear-this-command-keys) (push (read-event prompt) unread-command-events)) (setq binding (lookup-key keymap key)) (cond ((and (stringp key) (popup-isearch-char-p (aref key 0))) (setq pattern (concat pattern key))) ((eq binding 'popup-isearch-done) (my-edit-done pattern list) (return nil)) ((eq binding 'popup-isearch-cancel) (return t)) ((eq binding 'popup-isearch-delete) (if (> (length pattern) 0) (setq pattern (substring pattern 0 (1- (length pattern)))))) (t (setq unread-command-events (append (listify-key-sequence key) unread-command-events)) (return nil))) (my-main-buf-popup main-win pattern list)))))))
(defun ruby-new-line () "缩进并回车" (interactive) (ruby-indent-line) (newline) (ruby-indent-line) )
(defun my-edit-done (pattern tokens) "在你补全之后应该 insert 了" (let ((ret (my-edit-result pattern tokens)) pos end) (end-of-line) (insert "\n")(setq pos (point)) (insert ret "\nend") (setq end (point-marker)) (goto-char pos) (while (< (point) end) (ruby-indent-line) (line-move 1 t) ) (beginning-of-line) (left-char 1) (ruby-new-line)))
(defun my-main-buf-popup (main-win pattern tokens) "显示你所修改的" (let ((cur-win (selected-window))) (select-window main-win) ;;(message "pattern:%s " pattern )(print tokens) (popup-tip (my-edit-result pattern tokens))))
(defun my-edit-result (pattern tokens) "用于得到结果的 对 tokens 做处理" (mapconcat (lambda (token) (let (words) (setq words (split-string token "\s*=>\s*")) (with-temp-buffer (insert pattern) (dotimes (i (length words)) ;; 从 0 开始 不包含 COUNT (goto-char 1) (while (search-forward (nth i my-edit-replace-word) nil t) (replace-match (nth i words)))) (buffer-string)))) tokens "\n") )
(provide 'company-chong) ;;; company-chong.el ends here