lua-mode
lua-mode copied to clipboard
completion-at-point
我把python-mode中的completion-at-point的代码粘贴到了lua-mode中
能做点简单的completion,没有经过测试,肯定是有bug
以下是新加的代码
(eval-and-compile
(defconst lua-rx-constituents
`((block-start . ,(rx symbol-start
(or "def" "class" "if" "elif" "else" "try"
"except" "finally" "for" "while" "with"
;; Lua 3.5+ PEP492
(and "async" (+ space)
(or "def" "for" "with")))
symbol-end))
(dedenter . ,(rx symbol-start
(or "elif" "else" "except" "finally")
symbol-end))
(block-ender . ,(rx symbol-start
(or
"break" "continue" "pass" "raise" "return")
symbol-end))
(decorator . ,(rx line-start (* space) ?@ (any letter ?_)
(* (any word ?_))))
(defun . ,(rx symbol-start
(or "def" "class"
;; Lua 3.5+ PEP492
(and "async" (+ space) "def"))
symbol-end))
(if-name-main . ,(rx line-start "if" (+ space) "__name__"
(+ space) "==" (+ space)
(any ?' ?\") "__main__" (any ?' ?\")
(* space) ?:))
(symbol-name . ,(rx (any letter ?_) (* (any word ?_))))
(open-paren . ,(rx (or "{" "[" "(")))
(close-paren . ,(rx (or "}" "]" ")")))
(simple-operator . ,(rx (any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%)))
;; FIXME: rx should support (not simple-operator).
(not-simple-operator . ,(rx
(not
(any ?+ ?- ?/ ?& ?^ ?~ ?| ?* ?< ?> ?= ?%))))
;; FIXME: Use regexp-opt.
(operator . ,(rx (or "+" "-" "/" "&" "^" "~" "|" "*" "<" ">"
"=" "%" "**" "//" "<<" ">>" "<=" "!="
"==" ">=" "is" "not")))
;; FIXME: Use regexp-opt.
(assignment-operator . ,(rx (or "=" "+=" "-=" "*=" "/=" "//=" "%=" "**="
">>=" "<<=" "&=" "^=" "|=")))
(string-delimiter . ,(rx (and
;; Match even number of backslashes.
(or (not (any ?\\ ?\' ?\")) point
;; Quotes might be preceded by an escaped quote.
(and (or (not (any ?\\)) point) ?\\
(* ?\\ ?\\) (any ?\' ?\")))
(* ?\\ ?\\)
;; Match single or triple quotes of any kind.
(group (or "\"" "\"\"\"" "'" "'''")))))
(coding-cookie . ,(rx line-start ?# (* space)
(or
;; # coding=<encoding name>
(: "coding" (or ?: ?=) (* space) (group-n 1 (+ (or word ?-))))
;; # -*- coding: <encoding name> -*-
(: "-*-" (* space) "coding:" (* space)
(group-n 1 (+ (or word ?-))) (* space) "-*-")
;; # vim: set fileencoding=<encoding name> :
(: "vim:" (* space) "set" (+ space)
"fileencoding" (* space) ?= (* space)
(group-n 1 (+ (or word ?-))) (* space) ":")))))
"Additional Lua specific sexps for `lua-rx'")
(defmacro lua-rx (&rest regexps)
"Lua mode specialized rx macro.
This variant of `rx' supports common Lua named REGEXPS."
(let ((rx-constituents (append lua-rx-constituents rx-constituents)))
(cond ((null regexps)
(error "No regexp"))
((cdr regexps)
(rx-to-string `(and ,@regexps) t))
(t
(rx-to-string (car regexps) t))))))
(defun lua-util-comint-last-prompt ()
"Return comint last prompt overlay start and end.
This is for compatibility with Emacs < 24.4."
(cond ((bound-and-true-p comint-last-prompt-overlay)
(cons (overlay-start comint-last-prompt-overlay)
(overlay-end comint-last-prompt-overlay)))
((bound-and-true-p comint-last-prompt)
comint-last-prompt)
(t nil)))
(defcustom lua-shell-completion-native-output-timeout 5.0
"Time in seconds to wait for completion output before giving up."
:version "25.1"
:type 'float)
(defcustom lua-shell-completion-native-enable t
"Enable readline based native completion."
:version "25.1"
:type 'boolean)
(defcustom lua-shell-prompt-pdb-regexp "[(<]*[Ii]?[Pp]db[>)]+ "
"Regular expression matching pdb input prompt of Python shell.
It should not contain a caret (^) at the beginning."
:type 'string)
(defvar lua-shell--block-prompt nil
"Input block prompt for inferior lua shell.
Do not set this variable directly, instead use
`lua-shell-prompt-set-calculated-regexps'.")
(defun lua-shell-completion-get-completions (process import input)
"Do completion at point using PROCESS for IMPORT or INPUT.
When IMPORT is non-nil takes precedence over INPUT for
completion."
(setq input (or import input))
(with-current-buffer (process-buffer process)
(let ((completions
(lua-util-strip-string
(lua-shell-send-string-no-output
(format
(concat lua-shell-completion-setup-code
"\nprint (" lua-shell-completion-string-code ")")
input) process))))
(when (> (length completions) 2)
(split-string completions
"^'\\|^\"\\|;\\|'$\\|\"$" t)))))
(defvar lua-shell-completion-native-redirect-buffer
" *Lua completions redirect*"
"Buffer to be used to redirect output of readline commands.")
(defun lua-shell-accept-process-output (process &optional timeout regexp)
"Accept PROCESS output with TIMEOUT until REGEXP is found.
Optional argument TIMEOUT is the timeout argument to
`accept-process-output' calls. Optional argument REGEXP
overrides the regexp to match the end of output, defaults to
`comint-prompt-regexp'. Returns non-nil when output was
properly captured.
This utility is useful in situations where the output may be
received in chunks, since `accept-process-output' gives no
guarantees they will be grabbed in a single call. An example use
case for this would be the CLua shell start-up, where the
banner and the initial prompt are received separately."
(let ((regexp (or regexp comint-prompt-regexp)))
(catch 'found
(while t
(when (not (accept-process-output process timeout))
(throw 'found nil))
(when (looking-back
regexp (car (lua-util-comint-last-prompt)))
(throw 'found t))))))
(defun lua-get-command (input)
;;(print input)
(cond
((string-match "\\." input)
(let ((words (split-string input "\\.")))
(format "for i in pairs(%s) do if string.find(i,\"%s\") then print(\"%s.\" .. i) end end\n"
(nth 0 words)
(nth 1 words)
(nth 0 words))))
((string-match ":" input)
(let ((words (split-string input ":")))
(format "for i in pairs(%s) do if string.find(i,\"%s\") then print(\"%s:\"i) end end\n"
(nth 0 words)
(nth 1 words)
(nth 0 words))))
(t (format "for i in pairs(_G) do if string.find(i,\"%s\") then print(i) end end\n" input))
))
(defun lua-shell-completion-native-get-completions (process import input)
"Get completions using native readline for PROCESS.
When IMPORT is non-nil takes precedence over INPUT for
completion."
(with-current-buffer (process-buffer process)
(let* ((input (or import input))
(original-filter-fn (process-filter process))
(redirect-buffer (get-buffer-create
lua-shell-completion-native-redirect-buffer))
;;(command "for i in pairs(_G) do if string.find(i,\"%s\") then print(i) end end\n" )
(input-to-send (lua-get-command input))
)
;; Ensure restoring the process filter, even if the user quits
;; or there's some other error.
(unwind-protect
(with-current-buffer redirect-buffer
;; Cleanup the redirect buffer
(erase-buffer)
;; Mimic `comint-redirect-send-command', unfortunately it
;; can't be used here because it expects a newline in the
;; command and that's exactly what we are trying to avoid.
(let ((comint-redirect-echo-input nil)
(comint-redirect-completed nil)
(comint-redirect-perform-sanity-check nil)
(comint-redirect-insert-matching-regexp t)
(comint-redirect-finished-regexp
"> ")
(comint-redirect-output-buffer redirect-buffer))
;; Compatibility with Emacs 24.x. Comint changed and
;; now `comint-redirect-filter' gets 3 args. This
;; checks which version of `comint-redirect-filter' is
;; in use based on its args and uses `apply-partially'
;; to make it up for the 3 args case.
(if (= (length
(help-function-arglist 'comint-redirect-filter)) 3)
(set-process-filter
process (apply-partially
#'comint-redirect-filter original-filter-fn))
(set-process-filter process #'comint-redirect-filter))
(process-send-string process input-to-send)
;; Grab output until our dummy completion used as
;; output end marker is found.
(when (lua-shell-accept-process-output
process lua-shell-completion-native-output-timeout
comint-redirect-finished-regexp)
(cl-remove-duplicates
(split-string
(buffer-substring-no-properties
(line-beginning-position) (point-min))
"[ \f\t\n\r\v()]+" t)
:test #'string=))))
(set-process-filter process original-filter-fn)))))
(defun lua-shell-completion-at-point (&optional process)
"Function for `completion-at-point-functions' in `inferior-lua-mode'.
Optional argument PROCESS forces completions to be retrieved
using that one instead of current buffer's process."
(setq process (or process (get-buffer-process (current-buffer))))
(let* ((line-start (if (derived-mode-p 'inferior-lua-mode)
;; Working on a shell buffer: use prompt end.
(cdr (lua-util-comint-last-prompt))
(line-beginning-position)))
(import-statement
(when (string-match-p
(rx (* space) word-start (or "require") word-end space)
(buffer-substring-no-properties line-start (point)))
(buffer-substring-no-properties line-start (point))))
(start
(save-excursion
(if (not (re-search-backward
(lua-rx ;; find the current-word
(or whitespace open-paren close-paren string-delimiter))
line-start
t 1))
line-start
(forward-char (length (match-string-no-properties 0)))
(point))))
(end (point))
(prompt-boundaries
(with-current-buffer (process-buffer process)
(lua-util-comint-last-prompt)))
(prompt
(with-current-buffer (process-buffer process)
(when prompt-boundaries
(buffer-substring-no-properties
(car prompt-boundaries) (cdr prompt-boundaries)))))
(completion-fn
(with-current-buffer (process-buffer process)
(cond ((or (null prompt)
(< (point) (cdr prompt-boundaries)))
#'ignore)
((or (not lua-shell-completion-native-enable)
;; Even if native completion is enabled, for
;; pdb interaction always use the fallback
;; mechanism since the completer is changed.
;; Also, since pdb interaction is single-line
;; based, this is enough.
(string-match-p lua-shell-prompt-pdb-regexp prompt)
)
(if (or (equal lua-shell--block-prompt prompt)
(string-match-p
lua-shell-prompt-block-regexp prompt))
;; The non-native completion mechanism sends
;; newlines to the interpreter, so we can't use
;; it during a multiline statement (Bug#28051).
#'ignore
#'lua-shell-completion-get-completions))
(t
#'lua-shell-completion-native-get-completions)))))
(list start end
(completion-table-dynamic
(apply-partially
completion-fn
process import-statement)))))
以下是更新的代码
;;;###autoload
(defun lua-start-process (&optional name program startfile &rest switches)
"Start a Lua process named NAME, running PROGRAM.
PROGRAM defaults to NAME, which defaults to `lua-default-application'.
When called interactively, switch to the process buffer."
(interactive)
(or switches
(setq switches lua-default-command-switches))
(setq name (or name (if (consp lua-default-application)
(car lua-default-application)
lua-default-application)))
(setq program (or program lua-default-application))
(setq lua-process-buffer (apply 'make-comint name program startfile switches))
(setq lua-process (get-buffer-process lua-process-buffer))
(set-process-query-on-exit-flag lua-process nil)
(with-current-buffer lua-process-buffer
;; wait for prompt
(while (not (lua-prompt-line))
(accept-process-output (get-buffer-process (current-buffer)))
(goto-char (point-max)))
;; send initialization code
(lua-send-string lua-process-init-code)
(add-hook 'completion-at-point-functions
#'lua-shell-completion-at-point nil 'local)
;; enable error highlighting in stack traces
(require 'compile)
(setq lua--repl-buffer-p t)
(make-local-variable 'compilation-error-regexp-alist)
(setq compilation-error-regexp-alist
(cons (list lua-traceback-line-re 1 2)
compilation-error-regexp-alist))
(compilation-shell-minor-mode 1))
;; when called interactively, switch to process buffer
(if (called-interactively-p 'any)
(switch-to-buffer lua-process-buffer)))