<commit_before>;;; fsharp-mode-completion.el --- Autocompletion support for F#

;; Copyright (C) 2012-2013 <NAME>

;; Author: <NAME> <<EMAIL>>
;; Maintainer: <NAME> <<EMAIL>>
;; Keywords: languages

;; This file is not part of GNU Emacs.

;; This file 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, or (at your option)
;; any later version.

;; This file 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; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

(require 's)
(require 'dash)
(require 'fsharp-mode-indent)
(require 'auto-complete)
(require 'json)

(autoload 'pos-tip-fill-string "pos-tip")
(autoload 'pos-tip-show "pos-tip")
(autoload 'popup-tip "popup")

;;; User-configurable variables

(defvar fsharp-ac-executable "fsautocomplete.exe")

(defvar fsharp-ac-complete-command
  (let ((exe (or (executable-find fsharp-ac-executable)
                 (concat (file-name-directory (or load-file-name buffer-file-name))
                         "bin/" fsharp-ac-executable))))
    (case system-type
      (windows-nt (list exe))
      (otherwise (list "mono" exe)))))

(defvar fsharp-ac-use-popup t
  "Display tooltips using a popup at point. If set to nil,
display in a help buffer instead.")

(defvar fsharp-ac-intellisense-enabled t
  "Whether autocompletion is automatically triggered on '.'")

(defface fsharp-error-face
  '((t :inherit error))
  "Face used for marking an error in F#"
  :group 'fsharp)

(defface fsharp-warning-face
  '((t :inherit warning))
  "Face used for marking a warning in F#"
  :group 'fsharp)

;;; Both in seconds. Note that background process uses ms.
(defvar fsharp-ac-blocking-timeout 0.4)
(defvar fsharp-ac-idle-timeout 1)

;;; ----------------------------------------------------------------------------

(defvar fsharp-ac-debug nil)
(defvar fsharp-ac-status 'idle)
(defvar fsharp-ac-completion-process nil)
(defvar fsharp-ac-project-files nil)
(defvar fsharp-ac-idle-timer nil)
(defvar fsharp-ac-verbose nil)
(defvar fsharp-ac-current-candidate nil)
(defvar fsharp-ac-current-helptext (make-hash-table :test 'equal))

(defconst fsharp-ac--log-buf "*fsharp-debug*")

(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 (format "%s: %s" (float-time) str))
        (unless atend
          (goto-char pt))))))

(defun log-psendstr (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)
      (fsharp-ac--log (format "Parsing \"%s\"\n" file))
      (process-send-string
       fsharp-ac-completion-process
       (format "parse \"%s\"\n%s\n<<EOF>>\n"
               file
               (buffer-substring-no-properties (point-min) (point-max)))))))

(defun fsharp-ac-parse-file (file)
  (with-current-buffer (find-file-noselect file)
    (fsharp-ac-parse-current-buffer)))


(defun fsharp-ac--isIdChar (c)
  (let ((gc (get-char-code-property c 'general-category)))
    (or
     (-any? (lambda (x) (string= gc x)) '("Lu" "Ll" "Lt" "Lm" "Lo" "Nl" "Nd" "Pc" "Mn" "Mc"))
     (eq c 39))))

(defun fsharp-ac--isNormalId (s)
  (-all? (lambda (x) x) (mapcar 'fsharp-ac--isIdChar s)))

;;; ----------------------------------------------------------------------------
;;; File Parsing and loading

(defun fsharp-ac/load-project (file)
  "Load the specified F# file as a project"
  (interactive
  ;; Prompt user for an fsproj, searching for a default.
   (list (read-file-name
          "Path to project: "
          (fsharp-mode/find-fsproj buffer-file-name)
          (fsharp-mode/find-fsproj buffer-file-name))))

  (when (fsharp-ac--valid-project-p file)
    (fsharp-ac--reset)
    (when (not (fsharp-ac--process-live-p))
      (fsharp-ac/start-process))
    ;; Load given project.
    (when (fsharp-ac--process-live-p)
      (log-psendstr fsharp-ac-completion-process
                    (format "project \"%s\"\n" (expand-file-name file))))
    file))

(defun fsharp-ac/load-file (file)
  "Start the compiler binding for an individual F# script."
  (when (fsharp-ac--script-file-p file)
    (if (file-exists-p file)
        (when (not (fsharp-ac--process-live-p))
          (fsharp-ac/start-process))
      (add-hook 'after-save-hook 'fsharp-ac--load-after-save nil 'local))))

(defun fsharp-ac--load-after-save ()
  (remove-hook 'fsharp-ac--load-after-save 'local)
  (fsharp-ac/load-file (buffer-file-name)))

(defun fsharp-ac--valid-project-p (file)
  (and file
       (file-exists-p file)
       (string-match-p (rx "." "fsproj" eol) file)))

(defun fsharp-ac--script-file-p (file)
  (and file
       (string-match-p (rx (or "fsx" "fsscript"))
                       (file-name-extension file))))

(defun fsharp-ac--reset ()
  (setq fsharp-ac-project-files nil
        fsharp-ac-status 'idle
        fsharp-ac-current-candidate nil)
  (clrhash fsharp-ac-current-helptext)
  (fsharp-ac-clear-errors))

;;; ----------------------------------------------------------------------------
;;; Display Requests

(defun fsharp-ac-send-pos-request (cmd file line col)
  (log-psendstr fsharp-ac-completion-process
                (format "%s \"%s\" %d %d %d\n" cmd file line col
                        (* 1000 fsharp-ac-blocking-timeout))))

(defun fsharp-ac--process-live-p ()
  "Check whether the background process is live"
  (and fsharp-ac-completion-process
       (process-live-p fsharp-ac-completion-process)))

(defun fsharp-ac/stop-process ()
  (interactive)
  (fsharp-ac-message-safely "Quitting fsharp completion process")
  (when (fsharp-ac--process-live-p)
    (log-psendstr fsharp-ac-completion-process "quit\n")
    (sleep-for 1)
    (when (process-live-p fsharp-ac-completion-process)
      (kill-process fsharp-ac-completion-process)))
  (when fsharp-ac-idle-timer
    (cancel-timer fsharp-ac-idle-timer))
  (setq fsharp-ac-status 'idle
        fsharp-ac-completion-process nil
        fsharp-ac-project-files nil
        fsharp-ac-idle-timer nil
        fsharp-ac-verbose nil)
  (fsharp-ac-clear-errors))

(defun fsharp-ac/start-process ()
  "Launch the F# completion process in the background"
  (interactive)

  (when (fsharp-ac--process-live-p)
    (kill-process fsharp-ac-completion-process))

  (condition-case nil
      (progn
        (setq fsharp-ac-completion-process (fsharp-ac--configure-proc))
        (fsharp-ac--reset-timer))
    (error
     (setq fsharp-ac-intellisense-enabled nil)
     (message "Failed to start fsautocomplete. Disabling intellisense."))))

(defun fsharp-ac--configure-proc ()
  (let ((proc (let (process-connection-type)
                (apply 'start-process "fsharp-complete" "*fsharp-complete*"
                       fsharp-ac-complete-command))))
    (sleep-for 0.1)
    (if (process-live-p proc)
        (progn
          (set-process-filter proc 'fsharp-ac-filter-output)
          (set-process-query-on-exit-flag proc nil)
          (setq fsharp-ac-status 'idle
                fsharp-ac-project-files nil)
          (with-current-buffer (process-buffer proc)<commit_msg>Set process coding system to utf-8-auto<commit_after>;;; fsharp-mode-completion.el --- Autocompletion support for F#

;; Copyright (C) 2012-2013 <NAME>

;; Author: <NAME> <<EMAIL>>
;; Maintainer: <NAME> <<EMAIL>>
;; Keywords: languages

;; This file is not part of GNU Emacs.

;; This file 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, or (at your option)
;; any later version.

;; This file 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; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

(require 's)
(require 'dash)
(require 'fsharp-mode-indent)
(require 'auto-complete)
(require 'json)

(autoload 'pos-tip-fill-string "pos-tip")
(autoload 'pos-tip-show "pos-tip")
(autoload 'popup-tip "popup")

;;; User-configurable variables

(defvar fsharp-ac-executable "fsautocomplete.exe")

(defvar fsharp-ac-complete-command
  (let ((exe (or (executable-find fsharp-ac-executable)
                 (concat (file-name-directory (or load-file-name buffer-file-name))
                         "bin/" fsharp-ac-executable))))
    (case system-type
      (windows-nt (list exe))
      (otherwise (list "mono" exe)))))

(defvar fsharp-ac-use-popup t
  "Display tooltips using a popup at point. If set to nil,
display in a help buffer instead.")

(defvar fsharp-ac-intellisense-enabled t
  "Whether autocompletion is automatically triggered on '.'")

(defface fsharp-error-face
  '((t :inherit error))
  "Face used for marking an error in F#"
  :group 'fsharp)

(defface fsharp-warning-face
  '((t :inherit warning))
  "Face used for marking a warning in F#"
  :group 'fsharp)

;;; Both in seconds. Note that background process uses ms.
(defvar fsharp-ac-blocking-timeout 0.4)
(defvar fsharp-ac-idle-timeout 1)

;;; ----------------------------------------------------------------------------

(defvar fsharp-ac-debug nil)
(defvar fsharp-ac-status 'idle)
(defvar fsharp-ac-completion-process nil)
(defvar fsharp-ac-project-files nil)
(defvar fsharp-ac-idle-timer nil)
(defvar fsharp-ac-verbose nil)
(defvar fsharp-ac-current-candidate nil)
(defvar fsharp-ac-current-helptext (make-hash-table :test 'equal))

(defconst fsharp-ac--log-buf "*fsharp-debug*")

(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 (format "%s: %s" (float-time) str))
        (unless atend
          (goto-char pt))))))

(defun log-psendstr (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)
      (fsharp-ac--log (format "Parsing \"%s\"\n" file))
      (process-send-string
       fsharp-ac-completion-process
       (format "parse \"%s\"\n%s\n<<EOF>>\n"
               file
               (buffer-substring-no-properties (point-min) (point-max)))))))

(defun fsharp-ac-parse-file (file)
  (with-current-buffer (find-file-noselect file)
    (fsharp-ac-parse-current-buffer)))


(defun fsharp-ac--isIdChar (c)
  (let ((gc (get-char-code-property c 'general-category)))
    (or
     (-any? (lambda (x) (string= gc x)) '("Lu" "Ll" "Lt" "Lm" "Lo" "Nl" "Nd" "Pc" "Mn" "Mc"))
     (eq c 39))))

(defun fsharp-ac--isNormalId (s)
  (-all? (lambda (x) x) (mapcar 'fsharp-ac--isIdChar s)))

;;; ----------------------------------------------------------------------------
;;; File Parsing and loading

(defun fsharp-ac/load-project (file)
  "Load the specified F# file as a project"
  (interactive
  ;; Prompt user for an fsproj, searching for a default.
   (list (read-file-name
          "Path to project: "
          (fsharp-mode/find-fsproj buffer-file-name)
          (fsharp-mode/find-fsproj buffer-file-name))))

  (when (fsharp-ac--valid-project-p file)
    (fsharp-ac--reset)
    (when (not (fsharp-ac--process-live-p))
      (fsharp-ac/start-process))
    ;; Load given project.
    (when (fsharp-ac--process-live-p)
      (log-psendstr fsharp-ac-completion-process
                    (format "project \"%s\"\n" (expand-file-name file))))
    file))

(defun fsharp-ac/load-file (file)
  "Start the compiler binding for an individual F# script."
  (when (fsharp-ac--script-file-p file)
    (if (file-exists-p file)
        (when (not (fsharp-ac--process-live-p))
          (fsharp-ac/start-process))
      (add-hook 'after-save-hook 'fsharp-ac--load-after-save nil 'local))))

(defun fsharp-ac--load-after-save ()
  (remove-hook 'fsharp-ac--load-after-save 'local)
  (fsharp-ac/load-file (buffer-file-name)))

(defun fsharp-ac--valid-project-p (file)
  (and file
       (file-exists-p file)
       (string-match-p (rx "." "fsproj" eol) file)))

(defun fsharp-ac--script-file-p (file)
  (and file
       (string-match-p (rx (or "fsx" "fsscript"))
                       (file-name-extension file))))

(defun fsharp-ac--reset ()
  (setq fsharp-ac-project-files nil
        fsharp-ac-status 'idle
        fsharp-ac-current-candidate nil)
  (clrhash fsharp-ac-current-helptext)
  (fsharp-ac-clear-errors))

;;; ----------------------------------------------------------------------------
;;; Display Requests

(defun fsharp-ac-send-pos-request (cmd file line col)
  (log-psendstr fsharp-ac-completion-process
                (format "%s \"%s\" %d %d %d\n" cmd file line col
                        (* 1000 fsharp-ac-blocking-timeout))))

(defun fsharp-ac--process-live-p ()
  "Check whether the background process is live"
  (and fsharp-ac-completion-process
       (process-live-p fsharp-ac-completion-process)))

(defun fsharp-ac/stop-process ()
  (interactive)
  (fsharp-ac-message-safely "Quitting fsharp completion process")
  (when (fsharp-ac--process-live-p)
    (log-psendstr fsharp-ac-completion-process "quit\n")
    (sleep-for 1)
    (when (process-live-p fsharp-ac-completion-process)
      (kill-process fsharp-ac-completion-process)))
  (when fsharp-ac-idle-timer
    (cancel-timer fsharp-ac-idle-timer))
  (setq fsharp-ac-status 'idle
        fsharp-ac-completion-process nil
        fsharp-ac-project-files nil
        fsharp-ac-idle-timer nil
        fsharp-ac-verbose nil)
  (fsharp-ac-clear-errors))

(defun fsharp-ac/start-process ()
  "Launch the F# completion process in the background"
  (interactive)

  (when (fsharp-ac--process-live-p)
    (kill-process fsharp-ac-completion-process))

  (condition-case nil
      (progn
        (setq fsharp-ac-completion-process (fsharp-ac--configure-proc))
        (fsharp-ac--reset-timer))
    (error
     (setq fsharp-ac-intellisense-enabled nil)
     (message "Failed to start fsautocomplete. Disabling intellisense."))))

(defun fsharp-ac--configure-proc ()
  (let ((proc (let (process-connection-type)
                (apply 'start-process "fsharp-complete" "*fsharp-complete*"
                       fsharp-ac-complete-command))))
    (sleep-for 0.1)
    (if (process-live-p proc)
        (progn
	  (set-process-coding-system proc 'utf-8-auto)
          (set-process-filter proc 'fsharp-ac-filter-output)
          (set-process-query-on-exit-flag proc nil)
          (setq fsharp-ac-status 'idle
                fsharp-ac-project-files nil)
          (with-current-buffer (process-buffer proc)
{'fraction_non_alphanumeric': 0.17548354041245037, 'fraction_numerical': 0.004226975790956834, 'mean_word_length': 2.628863583546363, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4098999', 'n_tokens_mistral': 5540, 'n_tokens_neox': 5210, 'n_words': 1321}