Skip to content
This repository has been archived by the owner on Jan 3, 2019. It is now read-only.

Commit

Permalink
Use an intermediate buffer for processing
Browse files Browse the repository at this point in the history
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
rneatherway committed Mar 30, 2013
1 parent 599ed0d commit 44c058e
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 59 deletions.
118 changes: 69 additions & 49 deletions emacs/fsharp-mode-completion.el
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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)
Expand All @@ -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'"
Expand Down Expand Up @@ -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"))
Expand All @@ -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"
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion emacs/fsharp-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
17 changes: 11 additions & 6 deletions emacs/test/fsharp-mode-completion-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -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))))))
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 6 additions & 2 deletions emacs/test/integration-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)))
Expand Down Expand Up @@ -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)))
Expand Down
4 changes: 3 additions & 1 deletion emacs/test/test-common.el
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 44c058e

Please sign in to comment.