Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

completion-at-point #145

Open
ChongQing520 opened this issue Mar 27, 2019 · 0 comments
Open

completion-at-point #145

ChongQing520 opened this issue Mar 27, 2019 · 0 comments

Comments

@ChongQing520
Copy link

我把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)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant