Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Use an intermediate buffer for processing

This replaces use of a string with possibly expensive
append operations. Could potentially be optimized further
with handle functions operating on the buffer directly.

Also update tests to match.
  • Loading branch information...
commit 44c058ef6a81ff4d690e05683dd913a81e548fcc 1 parent 599ed0d
@rneatherway rneatherway authored
View
118 emacs/fsharp-mode-completion.el
@@ -72,37 +72,34 @@ display in a help buffer instead.")
(defvar fsharp-ac-debug nil)
(defvar fsharp-ac-status 'idle)
(defvar fsharp-ac-completion-process nil)
-(defvar fsharp-ac-partial-data "")
(defvar fsharp-ac-project-files nil)
(defvar fsharp-ac-idle-timer nil)
(defvar fsharp-ac-verbose nil)
(defvar fsharp-ac-current-candidate)
+(defconst fsharp-ac--log-buf "*fsharp-debug*")
-(defun log-to-proc-buf (proc str)
- (when (processp proc)
- (let ((buf (process-buffer proc))
- (atend (with-current-buffer (process-buffer proc)
- (eq (marker-position (process-mark proc)) (point)))))
- (when (buffer-live-p buf)
- (with-current-buffer buf
- (goto-char (process-mark proc))
- (insert-before-markers str))
- (if atend
- (with-current-buffer buf
- (goto-char (process-mark proc))))))))
+(defun fsharp-ac--log (str)
+ (when fsharp-ac-debug
+ (unless (get-buffer fsharp-ac--log-buf)
+ (generate-new-buffer fsharp-ac--log-buf))
+ (with-current-buffer fsharp-ac--log-buf
+ (let ((pt (point))
+ (atend (eq (point-max) (point))))
+ (goto-char (point-max))
+ (insert-before-markers str)
+ (unless atend
+ (goto-char pt))))))
(defun log-psendstr (proc str)
- (when fsharp-ac-debug
- (log-to-proc-buf proc str))
+ (fsharp-ac--log str)
(process-send-string proc str))
(defun fsharp-ac-parse-current-buffer ()
(save-restriction
(let ((file (expand-file-name (buffer-file-name))))
(widen)
- (log-to-proc-buf fsharp-ac-completion-process
- (format "Parsing \"%s\"\n" file))
+ (fsharp-ac--log (format "Parsing \"%s\"\n" file))
(process-send-string
fsharp-ac-completion-process
(format "parse \"%s\" full\n%s\n<<EOF>>\n"
@@ -159,8 +156,7 @@ display in a help buffer instead.")
(file-name-extension file))))
(defun fsharp-ac--reset ()
- (setq fsharp-ac-partial-data nil
- fsharp-ac-project-files nil
+ (setq fsharp-ac-project-files nil
fsharp-ac-status 'idle
fsharp-ac-current-candidate nil)
(fsharp-ac-clear-errors))
@@ -190,7 +186,6 @@ display in a help buffer instead.")
(cancel-timer fsharp-ac-idle-timer))
(setq fsharp-ac-status 'idle
fsharp-ac-completion-process nil
- fsharp-ac-partial-data ""
fsharp-ac-project-files nil
fsharp-ac-idle-timer nil
fsharp-ac-verbose nil)
@@ -216,8 +211,9 @@ display in a help buffer instead.")
(set-process-filter proc 'fsharp-ac-filter-output)
(set-process-query-on-exit-flag proc nil)
(setq fsharp-ac-status 'idle
- fsharp-ac-partial-data ""
fsharp-ac-project-files nil)
+ (with-current-buffer (process-buffer proc)
+ (delete-region (point-min) (point-max)))
(add-to-list 'ac-modes 'fsharp-mode)
proc)
(fsharp-ac-message-safely "Failed to launch: '%s'"
@@ -280,6 +276,7 @@ display in a help buffer instead.")
(defun fsharp-ac-can-make-request ()
(and (fsharp-ac--process-live-p)
+ (not ac-completing)
(or
(member (expand-file-name (buffer-file-name)) fsharp-ac-project-files)
(string-match-p (rx (or "fsx" "fsscript"))
@@ -297,11 +294,11 @@ display in a help buffer instead.")
"Display the type signature for the F# symbol at POINT."
(interactive)
(when (fsharp-ac-can-make-request)
- (fsharp-ac-parse-current-buffer)
- (fsharp-ac-send-pos-request "tooltip"
- (expand-file-name (buffer-file-name))
- (- (line-number-at-pos) 1)
- (current-column))))
+ (fsharp-ac-parse-current-buffer)
+ (fsharp-ac-send-pos-request "tooltip"
+ (expand-file-name (buffer-file-name))
+ (- (line-number-at-pos) 1)
+ (current-column))))
(defun fsharp-ac/gotodefn-at-point ()
"Find the point of declaration of the symbol at point and goto it"
@@ -320,11 +317,24 @@ display in a help buffer instead.")
(ac-auto-show-menu t))
(apply 'ac-start ac-start-args)))
-(defun fsharp-ac/electric-key ()
+
+(defun fsharp-ac/electric-dot ()
(interactive)
- (self-insert-command 1)
+ (when ac-completing
+ (ac-complete))
+ (when (not (eq (string-to-char ".") (char-before)))
+ (self-insert-command 1))
(fsharp-ac/complete-at-point))
+
+(defun fsharp-ac/electric-backspace ()
+ (interactive)
+ (when (eq (char-before) (string-to-char "."))
+ (ac-stop))
+ (delete-backward-char 1))
+
+(define-key ac-completing-map (kbd "<backspace>") 'fsharp-ac/electric-backspace)
+
(defun fsharp-ac/complete-at-point ()
(interactive)
(if (and (fsharp-ac-can-make-request)
@@ -475,29 +485,39 @@ around to the start of the buffer."
(defconst fsharp-ac-eom "\n<<EOF>>\n")
+(defun fsharp-ac--get-msg (proc)
+ (with-current-buffer (process-buffer proc)
+ (goto-char (point-min))
+ (let ((eofloc (search-forward fsharp-ac-eom nil t)))
+ (when eofloc
+ (let ((msg (buffer-substring-no-properties (point-min) (match-beginning 0))))
+ (delete-region (point-min) (match-end 0))
+ msg)))))
+
(defun fsharp-ac-filter-output (proc str)
"Filter output from the completion process and handle appropriately."
- (when fsharp-ac-debug
- (log-to-proc-buf proc str))
- (setq fsharp-ac-partial-data (concat fsharp-ac-partial-data str))
-
- (let ((eofloc (string-match-p fsharp-ac-eom fsharp-ac-partial-data)))
- (while eofloc
- (let ((msg (substring fsharp-ac-partial-data 0 eofloc))
- (part (substring fsharp-ac-partial-data (+ eofloc (length fsharp-ac-eom)))))
- (cond
- ((s-starts-with? "DATA: completion" msg) (fsharp-ac-handle-completion msg))
- ((s-starts-with? "DATA: finddecl" msg) (fsharp-ac-visit-definition msg))
- ((s-starts-with? "DATA: tooltip" msg) (fsharp-ac-handle-tooltip msg))
- ((s-starts-with? "DATA: errors" msg) (fsharp-ac-handle-errors msg))
- ((s-starts-with? "DATA: project" msg) (fsharp-ac-handle-project msg))
- ((s-starts-with? "ERROR: " msg) (fsharp-ac-handle-process-error msg))
- ((s-starts-with? "INFO: " msg) (when fsharp-ac-verbose (fsharp-ac-message-safely msg)))
- (t
- (fsharp-ac-message-safely "Error: unrecognised message: '%s'" msg)))
-
- (setq fsharp-ac-partial-data part))
- (setq eofloc (string-match-p fsharp-ac-eom fsharp-ac-partial-data)))))
+ (fsharp-ac--log str)
+
+ (with-current-buffer (process-buffer proc)
+ (save-excursion
+ (goto-char (process-mark proc))
+ (insert-before-markers str)))
+
+ (let ((msg (fsharp-ac--get-msg proc)))
+ (while msg
+ ;(message "[filter] length(msg) = %d" (length msg))
+ (cond
+ ((s-starts-with? "DATA: completion" msg) (fsharp-ac-handle-completion msg))
+ ((s-starts-with? "DATA: finddecl" msg) (fsharp-ac-visit-definition msg))
+ ((s-starts-with? "DATA: tooltip" msg) (fsharp-ac-handle-tooltip msg))
+ ((s-starts-with? "DATA: errors" msg) (fsharp-ac-handle-errors msg))
+ ((s-starts-with? "DATA: project" msg) (fsharp-ac-handle-project msg))
+ ((s-starts-with? "ERROR: " msg) (fsharp-ac-handle-process-error msg))
+ ((s-starts-with? "INFO: " msg) (when fsharp-ac-verbose (fsharp-ac-message-safely msg)))
+ (t
+ (fsharp-ac-message-safely "Error: unrecognised message: '%s'" msg)))
+
+ (setq msg (fsharp-ac--get-msg proc)))))
(defun fsharp-ac-handle-completion (str)
(setq str
View
2  emacs/fsharp-mode.el
@@ -88,7 +88,7 @@ and whether it is in a project directory.")
(define-key fsharp-mode-map "\C-c:" 'fsharp-guess-indent-offset)
(define-key fsharp-mode-map [delete] 'fsharp-electric-delete)
(define-key fsharp-mode-map [backspace] 'fsharp-electric-backspace)
- (define-key fsharp-mode-map (kbd ".") 'fsharp-ac/electric-key)
+ (define-key fsharp-mode-map (kbd ".") 'fsharp-ac/electric-dot)
(define-key fsharp-mode-map (kbd "C-c <up>") 'fsharp-goto-block-up)
View
17 emacs/test/fsharp-mode-completion-tests.el
@@ -63,13 +63,16 @@ Try indenting this token further or using standard formatting conventions."
"Test properties of filtered output from the ac-process."
(declare (indent 1))
`(check ,desc
- (stubbing-process-functions
- (find-file (concat fs-file-dir "Program.fs"))
- (fsharp-ac-filter-output nil err-brace-str))
- ,@body))
+ (using-file "*fsharp-complete*"
+ (stubbing-process-functions
+ (find-file (concat fs-file-dir "Program.fs"))
+ (fsharp-ac-filter-output nil err-brace-str)
+ ,@body))))
(check-filter "error clears partial data"
- (should (equal "" fsharp-ac-partial-data)))
+ (should (equal "" (with-current-buffer (process-buffer
+ fsharp-ac-completion-process)
+ (buffer-string)))))
(check-filter "errors cause overlays to be drawn"
(should (equal 3 (length (overlays-in (point-min) (point-max))))))
@@ -130,7 +133,9 @@ Stubs out functions that call on the ac process."
(fsharp-ac-parse-current-buffer () t)
(process-send-string (p s))
(fsharp-ac-can-make-request () t)
- (expand-file-name (x &rest _) x))
+ (expand-file-name (x &rest _) x)
+ (process-buffer (proc) "*fsharp-complete*")
+ (process-mark (proc) (point-max)))
,@body)))
(defmacro stub-fn (sym var &rest body)
View
8 emacs/test/integration-tests.el
@@ -111,7 +111,7 @@
(lambda ()
(let ((tiptext)
(fsharp-ac-use-popup t))
- (flet ((popup-tip (s) (setq tiptext s)))
+ (flet ((fsharp-ac/show-popup (s) (setq tiptext s)))
(find-file "Test1/Program.fs")
(fsharp-ac/load-project "Test1.fsproj")
(while (eq nil fsharp-ac-project-files)
@@ -120,6 +120,8 @@
(backward-char 2)
(call-process "sleep" nil nil nil "3")
(fsharp-ac/show-tooltip-at-point)
+ (call-process "sleep" nil nil nil "1")
+ (fsharp-ac/show-tooltip-at-point)
(with-timeout (5)
(while (eq nil tiptext)
(sleep-for 1)))
@@ -153,12 +155,14 @@
(lambda ()
(let ((tiptext)
(fsharp-ac-use-popup t))
- (flet ((popup-tip (s) (setq tiptext s)))
+ (flet ((fsharp-ac/show-popup (s) (setq tiptext s)))
(find-file "Test1/Script.fsx")
(fsharp-ac-parse-current-buffer)
(call-process "sleep" nil nil nil "3")
(search-forward "XA.fun")
(fsharp-ac/show-tooltip-at-point)
+ (call-process "sleep" nil nil nil "1")
+ (fsharp-ac/show-tooltip-at-point)
(with-timeout (waittime)
(while (null tiptext)
(accept-process-output fsharp-ac-completion-process sleeptime)))
View
4 emacs/test/test-common.el
@@ -29,7 +29,9 @@
(start-process (&rest args))
(set-process-filter (&rest args))
(set-process-query-on-exit-flag (&rest args))
- (process-send-string (&rest args)))
+ (process-send-string (&rest args))
+ (process-buffer (proc) "*fsharp-complete*")
+ (process-mark (proc) (point-max)))
,@body))
(defun should-match (regex str)
Please sign in to comment.
Something went wrong with that request. Please try again.