Skip to content
Browse files

Add F# mode

  • Loading branch information...
1 parent 3385bd7 commit 07afaff6b6ca2dc03125b992ff12d048a293cdd7 @michaelklishin committed Oct 13, 2012
View
166 bundles/fsharp/fsharp-font.el
@@ -0,0 +1,166 @@
+;(***********************************************************************)
+;(* *)
+;(* Objective Caml *)
+;(* *)
+;(* Jacques Garrigue and Ian T Zimmerman *)
+;(* *)
+;(* Copyright 1997 Institut National de Recherche en Informatique et *)
+;(* en Automatique. All rights reserved. This file is distributed *)
+;(* under the terms of the GNU General Public License. *)
+;(* *)
+;(***********************************************************************)
+
+;(* $Id: fsharp-font.el,v 1.19 2004/08/20 17:04:35 doligez Exp $ *)
+
+;; useful colors
+
+(cond
+ ((x-display-color-p)
+ (require 'font-lock)
+ (cond
+ ((not (boundp 'font-lock-type-face))
+ ;; make the necessary faces
+ (make-face 'Firebrick)
+ (set-face-foreground 'Firebrick "firebrick")
+ (make-face 'RosyBrown)
+ (set-face-foreground 'RosyBrown "RosyBrown")
+ (make-face 'Purple)
+ (set-face-foreground 'Purple "Purple")
+ (make-face 'MidnightBlue)
+ (set-face-foreground 'MidnightBlue "MidnightBlue")
+ (make-face 'DarkGoldenRod)
+ (set-face-foreground 'DarkGoldenRod "DarkGoldenRod")
+ (make-face 'DarkOliveGreen)
+ (set-face-foreground 'DarkOliveGreen "DarkOliveGreen4")
+ (make-face 'CadetBlue)
+ (set-face-foreground 'CadetBlue "CadetBlue")
+ ; assign them as standard faces
+ (setq font-lock-comment-face 'Firebrick)
+ (setq font-lock-string-face 'RosyBrown)
+ (setq font-lock-keyword-face 'Purple)
+ (setq font-lock-function-name-face 'MidnightBlue)
+ (setq font-lock-variable-name-face 'DarkGoldenRod)
+ (setq font-lock-type-face 'DarkOliveGreen)
+ (setq font-lock-reference-face 'CadetBlue)))
+ ; extra faces for documention
+ (make-face 'Stop)
+ (set-face-foreground 'Stop "White")
+ (set-face-background 'Stop "Red")
+ (make-face 'Doc)
+ (set-face-foreground 'Doc "Red")
+ (setq font-lock-stop-face 'Stop)
+ (setq font-lock-doccomment-face 'Doc)
+))
+
+
+(defconst fsharp-font-lock-keywords
+ (list
+;stop special comments
+ '("\\(^\\|[^\"]\\)\\((\\*\\*/\\*\\*)\\)"
+ 2 font-lock-stop-face)
+;doccomments
+ '("\\(^\\|[^\"]\\)\\((\\*\\*[^*]*\\([^)*][^*]*\\*+\\)*)\\)"
+ 2 font-lock-doccomment-face)
+;comments
+ '("\\(^\\|[^\"]\\)\\((\\*[^*]*\\*+\\([^)*][^*]*\\*+\\)*)\\)"
+ 2 font-lock-comment-face)
+
+;; '("(\\*IF-OCAML\\([^)*][^*]*\\*+\\)+ENDIF-OCAML\\*)"
+;; 2 font-lock-comment-face)
+
+;; '("\\(^\\|[^\"]\\)\\((\\*[^F]\\([^)*][^*]*\\*+\\)+)\\)"
+;; . font-lock-comment-face)
+; '("(\\*.*\\*)\\|(\\*.*\n.*\\*)"
+; . font-lock-comment-face)
+
+
+;character literals
+ (cons (concat "'\\(\\\\\\([ntbr'\\]\\|"
+ "[0-9][0-9][0-9]\\)\\|.\\)'"
+ "\\|\"[^\"\\]*\\(\\\\\\(.\\|\n\\)[^\"\\]*\\)*\"")
+ 'font-lock-string-face)
+
+ '("//.*" . font-lock-comment-face)
+
+;modules and constructors
+ '("`?\\<[A-Z][A-Za-z0-9_']*\\>" . font-lock-function-name-face)
+;definition
+
+ (cons (concat "\\(\\<"
+ (mapconcat 'identity
+ '(
+ ;; F# keywords
+ "abstract" "and" "as" "assert" "base" "begin"
+ "class" "default" "delegate" "do" "done" "downcast"
+ "downto" "elif" "else" "end" "exception" "extern"
+ "false" "finally" "for" "fun" "function" "global"
+ "if" "in" "inherit" "inline" "interface" "internal"
+ "lazy" "let" "match" "member" "module" "mutable"
+ "namespace" "new" "null" "of" "open" "or" "override"
+ "private" "public" "rec" "return" "sig" "static"
+ "struct" "then" "to" "true" "try" "type" "upcast"
+ "use" "val" "void" "when" "while" "with" "yield"
+
+ ;; F# reserved words for future use
+ "atomic" "break" "checked" "component" "const"
+ "constraint" "constructor" "continue" "eager"
+ "fixed" "fori" "functor" "include" "measure"
+ "method" "mixin" "object" "parallel" "params"
+ "process" "protected" "pure" "recursive" "sealed"
+ "tailcall" "trait" "virtual" "volatile"
+ )
+ "\\>\\|\\<")
+ "\\>\\)")
+ 'font-lock-type-face)
+
+;blocking
+;; '("\\<\\(begin\\|end\\|module\\|namespace\\|object\\|sig\\|struct\\)\\>"
+;; . font-lock-keyword-face)
+;control
+ (cons (concat
+ "\\<\\(asr\\|false\\|land\\|lor\\|lsl\\|lsr\\|lxor"
+ "\\|mod\\|new\\|null\\|object\\|or\\|sig\\|true\\)\\>"
+ "\\|\|\\|->\\|&\\|#")
+ 'font-lock-reference-face)
+;labels (and open)
+ '("\\<\\(assert\\|open\\|include\\|module\\|namespace\\|extern\\|void\\)\\>\\|[~?][ (]*[a-z][a-zA-Z0-9_']*"
+ . font-lock-variable-name-face)))
+
+(defconst inferior-fsharp-font-lock-keywords
+ (append
+ (list
+;inferior
+ '("^[#-]" . font-lock-comment-face)
+ '("^>" . font-lock-variable-name-face))
+ fsharp-font-lock-keywords))
+
+;; font-lock commands are similar for fsharp-mode and inferior-fsharp-mode
+(add-hook 'fsharp-mode-hook
+ '(lambda ()
+ (cond
+ ((fboundp 'global-font-lock-mode)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults
+ '(fsharp-font-lock-keywords nil nil ((?' . "w") (?_ . "w")))))
+ (t
+ (setq font-lock-keywords fsharp-font-lock-keywords)))
+ (make-local-variable 'font-lock-keywords-only)
+ (setq font-lock-keywords-only t)
+ (font-lock-mode 1)))
+
+(defun inferior-fsharp-mode-font-hook ()
+ (cond
+ ((fboundp 'global-font-lock-mode)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults
+ '(inferior-fsharp-font-lock-keywords
+ nil nil ((?' . "w") (?_ . "w")))))
+ (t
+ (setq font-lock-keywords inferior-fsharp-font-lock-keywords)))
+ (make-local-variable 'font-lock-keywords-only)
+ (setq font-lock-keywords-only t)
+ (font-lock-mode 1))
+
+(add-hook 'inferior-fsharp-mode-hooks 'inferior-fsharp-mode-font-hook)
+
+(provide 'fsharp-font)
View
1,636 bundles/fsharp/fsharp-indent.el
1,636 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
324 bundles/fsharp/fsharp.el
@@ -0,0 +1,324 @@
+;(***********************************************************************)
+;(* *)
+;(* Objective Caml *)
+;(* *)
+;(* Jacques Garrigue and Ian T Zimmerman *)
+;(* *)
+;(* Copyright 1997 Institut National de Recherche en Informatique et *)
+;(* en Automatique. All rights reserved. This file is distributed *)
+;(* under the terms of the GNU General Public License. *)
+;(* *)
+;(***********************************************************************)
+
+;(* $Id: fsharp.el,v 1.39 2005/02/04 17:19:21 remy Exp $ *)
+
+;; Xavier Leroy, july 1993.
+;;copying: covered by the current FSF General Public License.
+
+;; adapted for F# by Laurent Le Brun <laurent@le-brun.eu>
+
+
+;;user customizable variables
+
+(defvar fsharp-version 0.3
+ "Version of this fsharp-mode")
+
+(defvar inferior-fsharp-program "fsi"
+ "Program name for invoking an inferior fsharp from Emacs.")
+
+(defvar fsharp-compiler "fsc"
+ "Program name for compiling a F# file")
+
+(defvar fsharp-shell-active nil
+ "Non nil when a subshell is running.")
+
+(defvar running-xemacs (string-match "XEmacs" emacs-version)
+ "Non-nil if we are running in the XEmacs environment.")
+
+(defvar fsharp-mode-map nil
+ "Keymap used in fsharp mode.")
+
+(if fsharp-mode-map
+ ()
+ (setq fsharp-mode-map (make-sparse-keymap))
+ (if running-xemacs
+ (define-key fsharp-mode-map 'backspace 'backward-delete-char-untabify)
+ (define-key fsharp-mode-map "\177" 'backward-delete-char-untabify))
+
+ ;; F# bindings
+ (define-key fsharp-mode-map "\C-c\C-a" 'fsharp-find-alternate-file)
+ (define-key fsharp-mode-map "\C-c\C-c" 'compile)
+ (define-key fsharp-mode-map "\C-cx" 'fsharp-run-executable-file)
+ (define-key fsharp-mode-map "\M-\C-x" 'fsharp-eval-phrase)
+ (define-key fsharp-mode-map "\C-c\C-e" 'fsharp-eval-phrase)
+ (define-key fsharp-mode-map "\C-c\C-r" 'fsharp-eval-region)
+ (define-key fsharp-mode-map "\C-c\C-s" 'fsharp-show-subshell)
+ (define-key fsharp-mode-map "\M-\C-h" 'fsharp-mark-phrase)
+
+ (define-key fsharp-mode-map "\C-cl" 'fsharp-shift-region-left)
+ (define-key fsharp-mode-map "\C-cr" 'fsharp-shift-region-right)
+
+ (define-key fsharp-mode-map "\C-m" 'fsharp-newline-and-indent)
+ (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 "C-c <up>") 'fsharp-goto-block-up)
+
+
+ (if running-xemacs nil ; if not running xemacs
+ (let ((map (make-sparse-keymap "fsharp"))
+ (forms (make-sparse-keymap "Forms")))
+ (define-key fsharp-mode-map [menu-bar] (make-sparse-keymap))
+ (define-key fsharp-mode-map [menu-bar fsharp] (cons "F#" map))
+
+ (define-key map [goto-block-up] '("Goto block up" . fsharp-goto-block-up))
+ (define-key map [mark-phrase] '("Mark phrase" . fsharp-mark-phrase))
+ (define-key map [shift-left] '("Shift region to right" . fsharp-shift-region-right))
+ (define-key map [shift-right] '("Shift region to left" . fsharp-shift-region-left))
+ (define-key map [separator-2] '("---"))
+
+ ;; others
+ (define-key map [run] '("Run..." . fsharp-run-executable-file))
+ (define-key map [compile] '("Compile..." . compile))
+ (define-key map [switch-view] '("Switch view" . fsharp-find-alternate-file))
+ (define-key map [separator-1] '("--"))
+ (define-key map [show-subshell] '("Show subshell" . fsharp-show-subshell))
+ (define-key map [eval-region] '("Eval region" . fsharp-eval-region))
+ (define-key map [eval-phrase] '("Eval phrase" . fsharp-eval-phrase))
+ )))
+
+(defvar fsharp-mode-syntax-table nil
+ "Syntax table in use in fsharp mode buffers.")
+(if fsharp-mode-syntax-table
+ ()
+ (setq fsharp-mode-syntax-table (make-syntax-table))
+ ; backslash is an escape sequence
+ (modify-syntax-entry ?\\ "\\" fsharp-mode-syntax-table)
+
+ ; ( is first character of comment start
+ (modify-syntax-entry ?\( "()1n" fsharp-mode-syntax-table)
+ ; * is second character of comment start,
+ ; and first character of comment end
+ (modify-syntax-entry ?* ". 23n" fsharp-mode-syntax-table)
+ ; ) is last character of comment end
+ (modify-syntax-entry ?\) ")(4n" fsharp-mode-syntax-table)
+
+ ; // is the beginning of a comment "b"
+ (modify-syntax-entry ?\/ ". 12b" fsharp-mode-syntax-table)
+ ; // \nis the beginning of a comment "b"
+ (modify-syntax-entry ?\n "> b" fsharp-mode-syntax-table)
+
+ ; backquote was a string-like delimiter (for character literals)
+ ; (modify-syntax-entry ?` "\"" fsharp-mode-syntax-table)
+ ; quote and underscore are part of words
+ (modify-syntax-entry ?' "w" fsharp-mode-syntax-table)
+ (modify-syntax-entry ?_ "w" fsharp-mode-syntax-table)
+ ; ISO-latin accented letters and EUC kanjis are part of words
+ (let ((i 160))
+ (while (< i 256)
+ (modify-syntax-entry i "w" fsharp-mode-syntax-table)
+ (setq i (1+ i)))))
+
+;; Other internal variables
+
+(defvar fsharp-last-noncomment-pos nil
+ "Caches last buffer position determined not inside a fsharp comment.")
+(make-variable-buffer-local 'fsharp-last-noncomment-pos)
+
+;;last-noncomment-pos can be a simple position, because we nil it
+;;anyway whenever buffer changes upstream. last-comment-start and -end
+;;have to be markers, because we preserve them when the changes' end
+;;doesn't overlap with the comment's start.
+
+(defvar fsharp-last-comment-start nil
+ "A marker caching last determined fsharp comment start.")
+(make-variable-buffer-local 'fsharp-last-comment-start)
+
+(defvar fsharp-last-comment-end nil
+ "A marker caching last determined fsharp comment end.")
+(make-variable-buffer-local 'fsharp-last-comment-end)
+
+(make-variable-buffer-local 'before-change-function)
+
+
+(defvar fsharp-mode-hook nil
+ "Hook for fsharp-mode")
+
+(defun fsharp-mode ()
+ "Major mode for editing fsharp code.
+
+\\{fsharp-mode-map}"
+ (interactive)
+
+ (require 'fsharp-indent)
+ (require 'fsharp-font)
+ (kill-all-local-variables)
+ (use-local-map fsharp-mode-map)
+ (set-syntax-table fsharp-mode-syntax-table)
+ (make-local-variable 'paragraph-start)
+ (make-local-variable 'require-final-newline)
+ (make-local-variable 'paragraph-separate)
+ (make-local-variable 'paragraph-ignore-fill-prefix)
+ (make-local-variable 'comment-start)
+ (make-local-variable 'comment-end)
+ (make-local-variable 'comment-column)
+ (make-local-variable 'comment-start-skip)
+ (make-local-variable 'parse-sexp-ignore-comments)
+ (make-local-variable 'indent-line-function)
+ (make-local-variable 'add-log-current-defun-function)
+
+ (setq major-mode 'fsharp-mode
+ mode-name "fsharp"
+ local-abbrev-table fsharp-mode-abbrev-table
+ paragraph-start (concat "^$\\|" page-delimiter)
+ paragraph-separate paragraph-start
+ paragraph-ignore-fill-prefix t
+ require-final-newline t
+ indent-tabs-mode nil
+ comment-start "//"
+ comment-end ""
+ comment-column 40
+ comment-start-skip "///* *"
+ comment-indent-function 'fsharp-comment-indent-function
+ indent-region-function 'fsharp-indent-region
+ indent-line-function 'fsharp-indent-line
+
+ ;itz Fri Sep 25 13:23:49 PDT 1998
+ add-log-current-defun-function 'fsharp-current-defun
+ ;itz 03-25-96
+ before-change-function 'fsharp-before-change-function
+ fsharp-last-noncomment-pos nil
+ fsharp-last-comment-start (make-marker)
+ fsharp-last-comment-end (make-marker))
+
+ ;garrigue july 97
+ (if running-xemacs ; from Xemacs lisp mode
+ (if (and (featurep 'menubar)
+ current-menubar)
+ (progn
+ ;; make a local copy of the menubar, so our modes don't
+ ;; change the global menubar
+ (set-buffer-menubar current-menubar)
+ (add-submenu nil fsharp-mode-xemacs-menu))))
+ (run-hooks 'fsharp-mode-hook)
+
+ (if fsharp-smart-indentation
+ (let ((offset fsharp-indent-offset))
+ ;; It's okay if this fails to guess a good value
+ (if (and (fsharp-safe (fsharp-guess-indent-offset))
+ (<= fsharp-indent-offset 8)
+ (>= fsharp-indent-offset 2))
+ (setq offset fsharp-indent-offset))
+ (setq fsharp-indent-offset offset)
+ ;; Only turn indent-tabs-mode off if tab-width !=
+ ;; fsharp-indent-offset. Never turn it on, because the user must
+ ;; have explicitly turned it off.
+ (if (/= tab-width fsharp-indent-offset)
+ (setq indent-tabs-mode nil))
+ )))
+
+(defun fsharp-set-compile-command ()
+ "Hook to set compile-command locally, unless there is a Makefile in the
+ current directory."
+ (interactive)
+ (unless (or (null buffer-file-name)
+ (file-exists-p "makefile")
+ (file-exists-p "Makefile"))
+ (let* ((filename (file-name-nondirectory buffer-file-name))
+ (basename (file-name-sans-extension filename))
+ (command nil))
+ (cond
+ ((string-match ".*\\.fs\$" filename)
+ (setq command fsharp-compiler) ; (concat "fsc -o " basename)
+ )
+ ((string-match ".*\\.fsl\$" filename) ;FIXME
+ (setq command "fslex"))
+ ((string-match ".*\\.fsy\$" filename) ;FIXME
+ (setq command "fsyacc"))
+ )
+ (if command
+ (progn
+ (make-local-variable 'compile-command)
+ (setq compile-command (concat command " " filename))))
+ )))
+
+(add-hook 'fsharp-mode-hook 'fsharp-set-compile-command)
+
+;;; Auxiliary function. Garrigue 96-11-01.
+
+(defun fsharp-find-alternate-file ()
+ (interactive)
+ (let ((name (buffer-file-name)))
+ (if (string-match "^\\(.*\\)\\.\\(fs\\|fsi\\)$" name)
+ (find-file
+ (concat
+ (fsharp-match-string 1 name)
+ (if (string= "fs" (fsharp-match-string 2 name)) ".fsi" ".fs"))))))
+
+;;; subshell support
+
+(defun fsharp-eval-region (start end)
+ "Send the current region to the inferior fsharp process."
+ (interactive"r")
+ (require 'inf-fsharp)
+ (inferior-fsharp-eval-region start end))
+
+
+(defun fsharp-show-subshell ()
+ (interactive)
+ (require 'inf-fsharp)
+ (inferior-fsharp-show-subshell))
+
+
+(defconst fsharp-error-regexp-fs
+ "^\\([^(\n]+\\)(\\([0-9]+\\),\\([0-9]+\\)):"
+ "Regular expression matching the error messages produced by fsc.")
+
+(if (boundp 'compilation-error-regexp-alist)
+ (or (assoc fsharp-error-regexp-fs
+ compilation-error-regexp-alist)
+ (setq compilation-error-regexp-alist
+ (cons (list fsharp-error-regexp-fs 1 2 3)
+ compilation-error-regexp-alist))))
+
+;; Usual match-string doesn't work properly with font-lock-mode
+;; on some emacs.
+
+(defun fsharp-match-string (num &optional string)
+
+ "Return string of text matched by last search, without properties.
+
+NUM specifies which parenthesized expression in the last regexp.
+Value is nil if NUMth pair didn't match, or there were less than NUM
+pairs. Zero means the entire text matched by the whole regexp or
+whole string."
+
+ (let* ((data (match-data))
+ (begin (nth (* 2 num) data))
+ (end (nth (1+ (* 2 num)) data)))
+ (if string (substring string begin end)
+ (buffer-substring-no-properties begin end))))
+
+(defun fsharp-find-alternate-file ()
+ (interactive)
+ (let ((name (buffer-file-name)))
+ (if (string-match "^\\(.*\\)\\.\\(fs\\|fsi\\)$" name)
+ (find-file
+ (concat
+ (fsharp-match-string 1 name)
+ (if (string= "fs" (fsharp-match-string 2 name)) ".fsi" ".fs"))))))
+
+(defun fsharp-run-executable-file ()
+ (interactive)
+ (let ((name (buffer-file-name)))
+ (if (string-match "^\\(.*\\)\\.\\(fs\\|fsi\\)$" name)
+ (shell-command (concat (match-string 1 name) ".exe")))))
+
+(defun fsharp-version ()
+ "Echo the current version of `fsharp-mode' in the minibuffer."
+ (interactive)
+ (message "Using `fsharp-mode' version %s" fsharp-version)
+ (fsharp-keep-region-active))
+
+(provide 'fsharp)
View
372 bundles/fsharp/inf-fsharp.el
@@ -0,0 +1,372 @@
+;(***********************************************************************)
+;(* *)
+;(* Objective fsharp *)
+;(* *)
+;(* Xavier Leroy and Jacques Garrigue *)
+;(* *)
+;(* Copyright 1997 Institut National de Recherche en Informatique et *)
+;(* en Automatique. All rights reserved. This file is distributed *)
+;(* under the terms of the GNU General Public License. *)
+;(* *)
+;(***********************************************************************)
+
+;(* $Id: inf-fsharp.el,v 1.11 2004/08/20 17:04:35 doligez Exp $ *)
+
+;;; inf-fsharp.el --- run the fsharp toplevel in an Emacs buffer
+
+;; Xavier Leroy, july 1993.
+
+;; modified by Jacques Garrigue, july 1997.
+
+;; modified by Laurent Le Brun for F#, 2010
+
+(require 'comint)
+(require 'fsharp)
+
+;; User modifiable variables
+
+;; Whether you want the output buffer to be diplayed when you send a phrase
+
+(defvar fsharp-display-when-eval t
+ "*If true, display the inferior fsharp buffer when evaluating expressions.")
+
+
+;; End of User modifiable variables
+
+
+(defvar inferior-fsharp-mode-map nil)
+(if inferior-fsharp-mode-map nil
+ (setq inferior-fsharp-mode-map
+ (copy-keymap comint-mode-map)))
+
+;; Augment fsharp mode, so you can process fsharp code in the source files.
+
+(defvar inferior-fsharp-program "fsharp"
+ "*Program name for invoking an inferior fsharp from Emacs.")
+
+(defun inferior-fsharp-mode ()
+ "Major mode for interacting with an inferior fsharp process.
+Runs a fsharp toplevel as a subprocess of Emacs, with I/O through an
+Emacs buffer. A history of input phrases is maintained. Phrases can
+be sent from another buffer in fsharp mode.
+
+\\{inferior-fsharp-mode-map}"
+ (interactive)
+ (comint-mode)
+ (setq comint-prompt-regexp "^# ?")
+ (setq major-mode 'inferior-fsharp-mode)
+
+ (setq mode-name "Inferior fsharp")
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat "^$\\|" page-delimiter))
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate paragraph-start)
+ (make-local-variable 'paragraph-ignore-fill-prefix)
+ (setq paragraph-ignore-fill-prefix t)
+ (make-local-variable 'require-final-newline)
+ (setq require-final-newline t)
+ (make-local-variable 'comment-start)
+ (setq comment-start "(*")
+ (make-local-variable 'comment-end)
+ (setq comment-end "*)")
+ (make-local-variable 'comment-column)
+ (setq comment-column 40)
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "(\\*+ *")
+ (make-local-variable 'parse-sexp-ignore-comments)
+ (setq parse-sexp-ignore-comments nil)
+ (use-local-map inferior-fsharp-mode-map)
+ (run-hooks 'inferior-fsharp-mode-hooks)
+
+ (define-key inferior-fsharp-mode-map [M-return] 'fsharp-comint-send)
+
+ ;; use compilation mode to parse errors, but RET and C-cC-c should still be from comint-mode
+ (compilation-minor-mode)
+ (make-local-variable 'minor-mode-map-alist)
+ (setq minor-mode-map-alist (assq-delete-all 'compilation-minor-mode (copy-list minor-mode-map-alist)))
+)
+
+
+(defconst inferior-fsharp-buffer-subname "inferior-fsharp")
+(defconst inferior-fsharp-buffer-name
+ (concat "*" inferior-fsharp-buffer-subname "*"))
+
+;; for compatibility with xemacs
+
+(defun fsharp-sit-for (second &optional mili redisplay)
+ (if (and (boundp 'running-xemacs) running-xemacs)
+ (sit-for (if mili (+ second (* mili 0.001)) second) redisplay)
+ (sit-for second mili redisplay)))
+
+;; To show result of evaluation at toplevel
+
+(defvar inferior-fsharp-output nil)
+(defun inferior-fsharp-signal-output (s)
+ (if (string-match "[^ ]" s) (setq inferior-fsharp-output t)))
+
+(defun inferior-fsharp-mode-output-hook ()
+ (setq comint-output-filter-functions
+ (list (function inferior-fsharp-signal-output))))
+(add-hook 'inferior-fsharp-mode-hooks 'inferior-fsharp-mode-output-hook)
+
+;; To launch fsharp whenever needed
+
+(defun fsharp-run-process-if-needed (&optional cmd)
+ (if (comint-check-proc inferior-fsharp-buffer-name) nil
+ (if (not cmd)
+ (if (comint-check-proc inferior-fsharp-buffer-name)
+ (setq cmd inferior-fsharp-program)
+ (setq cmd (read-from-minibuffer "fsharp toplevel to run: "
+ inferior-fsharp-program))))
+ (setq inferior-fsharp-program cmd)
+ (let ((cmdlist (inferior-fsharp-args-to-list cmd))
+ (process-connection-type nil))
+ (set-buffer (apply (function make-comint)
+ inferior-fsharp-buffer-subname
+ (car cmdlist) nil (cdr cmdlist)))
+ (inferior-fsharp-mode)
+ (display-buffer inferior-fsharp-buffer-name)
+ t)
+ (setq fsharp-shell-active t)
+ ))
+
+;; patched to from original run-fsharp sharing code with
+;; fsharp-run-process-when-needed
+
+(defun run-fsharp (&optional cmd)
+ "Run an inferior fsharp process.
+Input and output via buffer `*inferior-fsharp*'."
+ (interactive
+ (list (if (not (comint-check-proc inferior-fsharp-buffer-name))
+ (read-from-minibuffer "fsharp toplevel to run: "
+ inferior-fsharp-program))))
+ (fsharp-run-process-if-needed cmd)
+ (switch-to-buffer-other-window inferior-fsharp-buffer-name))
+
+;; split the command line (e.g. "mono fsi" -> ("mono" "fsi"))
+;; we double the \ before unquoting, so that the user doesn't have to
+(defun inferior-fsharp-args-to-list (string)
+ (split-string-and-unquote (replace-regexp-in-string "\\\\" "\\\\\\\\" string)))
+
+(defun inferior-fsharp-show-subshell ()
+ (interactive)
+ (fsharp-run-process-if-needed)
+ (display-buffer inferior-fsharp-buffer-name)
+ ; Added by Didier to move the point of inferior-fsharp to end of buffer
+ (let ((buf (current-buffer))
+ (fsharp-buf (get-buffer inferior-fsharp-buffer-name))
+ (count 0))
+ (while
+ (and (< count 10)
+ (not (equal (buffer-name (current-buffer))
+ inferior-fsharp-buffer-name)))
+ (next-multiframe-window)
+ (setq count (+ count 1)))
+ (if (equal (buffer-name (current-buffer))
+ inferior-fsharp-buffer-name)
+ (end-of-buffer))
+ (while
+ (> count 0)
+ (previous-multiframe-window)
+ (setq count (- count 1)))
+ )
+)
+
+;; patched by Didier to move cursor after evaluation
+
+(defun inferior-fsharp-eval-region (start end)
+ "Send the current region to the inferior fsharp process."
+ (interactive "r")
+ (save-excursion (fsharp-run-process-if-needed))
+ (save-excursion
+ ;; send location to fsi
+ (let* (
+ (name (buffer-name (current-buffer)))
+ (line (number-to-string (line-number-at-pos start)))
+ (loc (concat "# " line " \"" name "\"\n")))
+ (comint-send-string inferior-fsharp-buffer-name loc))
+ (goto-char end)
+; (fsharp-skip-comments-backward)
+ (comint-send-region inferior-fsharp-buffer-name start (point))
+ ;; normally, ";;" are part of the region
+ (if (and (>= (point) 2)
+ (prog2 (backward-char 2) (looking-at ";;")))
+ (comint-send-string inferior-fsharp-buffer-name "\n")
+ (comint-send-string inferior-fsharp-buffer-name "\n;;\n"))
+ ;; the user may not want to see the output buffer
+ (if fsharp-display-when-eval
+ (display-buffer inferior-fsharp-buffer-name t))))
+
+;; jump to errors produced by fsharp compiler
+
+(defun inferior-fsharp-goto-error (start end)
+ "Jump to the location of the last error as indicated by inferior toplevel."
+ (interactive "r")
+ (let ((loc (+ start
+ (save-excursion
+ (set-buffer (get-buffer inferior-fsharp-buffer-name))
+ (re-search-backward
+ (concat ;; comint-prompt-regexp
+ "(\\([0-9]+\\),\\([0-9]+\\)): error"))
+;; "[ \t]*Characters[ \t]+\\([0-9]+\\)-[0-9]+:$"))
+ (string-to-int (match-string 1))))))
+ (goto-line (- loc 1))))
+;; (goto-char loc)))
+
+
+;;; orgininal inf-fsharp.el ended here
+
+;; as eval-phrase, but ignores errors.
+
+(defun inferior-fsharp-just-eval-phrase (arg &optional min max)
+ "Send the phrase containing the point to the fsharp process.
+With prefix-arg send as many phrases as its numeric value,
+ignoring possible errors during evaluation.
+
+Optional arguments min max defines a region within which the phrase
+should lies."
+ (interactive "p")
+ (let ((beg))
+ (while (> arg 0)
+ (setq arg (- arg 1))
+ (setq beg (fsharp-find-phrase min max))
+ (fsharp-eval-region beg (point)))
+ beg))
+
+(defvar fsharp-previous-output nil
+ "tells the beginning of output in the shell-output buffer, so that the
+output can be retreived later, asynchronously.")
+
+;; enriched version of eval-phrase, to repport errors.
+
+(defun inferior-fsharp-eval-phrase (arg &optional min max)
+ "Send the phrase containing the point to the fsharp process.
+With prefix-arg send as many phrases as its numeric value,
+If an error occurs during evalutaion, stop at this phrase and
+repport the error.
+
+Return nil if noerror and position of error if any.
+
+If arg's numeric value is zero or negative, evaluate the current phrase
+or as many as prefix arg, ignoring evaluation errors.
+This allows to jump other erroneous phrases.
+
+Optional arguments min max defines a region within which the phrase
+should lies."
+ (interactive "p")
+ (if (save-excursion (fsharp-run-process-if-needed))
+ (progn
+ (setq inferior-fsharp-output nil)
+ (fsharp-wait-output 10 1)))
+ (if (< arg 1) (inferior-fsharp-just-eval-phrase (max 1 (- 0 arg)) min max)
+ (let ((proc (get-buffer-process inferior-fsharp-buffer-name))
+ (buf (current-buffer))
+ previous-output orig beg end err)
+ (save-window-excursion
+ (while (and (> arg 0) (not err))
+ (setq previous-output (marker-position (process-mark proc)))
+ (setq fsharp-previous-output previous-output)
+ (setq inferior-fsharp-output nil)
+ (setq orig (inferior-fsharp-just-eval-phrase 1 min max))
+ (fsharp-wait-output)
+ (switch-to-buffer inferior-fsharp-buffer-name nil)
+ (goto-char previous-output)
+ (cond ((re-search-forward
+ " *Characters \\([01-9][01-9]*\\)-\\([1-9][01-9]*\\):\n[^W]"
+ (point-max) t)
+ (setq beg (string-to-int (fsharp-match-string 1)))
+ (setq end (string-to-int (fsharp-match-string 2)))
+ (switch-to-buffer buf)
+ (goto-char orig)
+ (forward-byte end)
+ (setq end (point))
+ (goto-char orig)
+ (forward-byte beg)
+ (setq beg (point))
+ (setq err beg)
+ )
+ ((looking-at
+ "Toplevel input:\n[>]\\([^\n]*\\)\n[>]\\(\\( *\\)^*\\)\n")
+ (let ((expr (fsharp-match-string 1))
+ (column (- (match-end 3) (match-beginning 3)))
+ (width (- (match-end 2) (match-end 3))))
+ (if (string-match "^\\(.*\\)[<]EOF[>]$" expr)
+ (setq expr (substring expr (match-beginning 1) (match-end 1))))
+ (switch-to-buffer buf)
+ (re-search-backward
+ (concat "^" (regexp-quote expr) "$")
+ (- orig 10))
+ (goto-char (+ (match-beginning 0) column))
+ (setq end (+ (point) width)))
+ (setq err beg))
+ ((looking-at
+ "Toplevel input:\n>[.]*\\([^.].*\n\\)\\([>].*\n\\)*[>]\\(.*[^.]\\)[.]*\n")
+ (let* ((e1 (fsharp-match-string 1))
+ (e2 (fsharp-match-string 3))
+ (expr
+ (concat
+ (regexp-quote e1) "\\(.*\n\\)*" (regexp-quote e2))))
+ (switch-to-buffer buf)
+ (re-search-backward expr orig 'move)
+ (setq end (match-end 0)))
+ (setq err beg))
+ (t
+ (switch-to-buffer buf)))
+ (setq arg (- arg 1))
+ )
+ (pop-to-buffer inferior-fsharp-buffer-name)
+ (if err
+ (goto-char (point-max))
+ (goto-char previous-output)
+ (goto-char (point-max)))
+ (pop-to-buffer buf))
+ (if err (progn (beep) (fsharp-overlay-region (point) end))
+ (if inferior-fsharp-output
+ (message "No error")
+ (message "No output yet...")
+ ))
+ err)))
+
+(defun fsharp-overlay-region (beg end &optional wait)
+ (interactive "%r")
+ (cond ((fboundp 'make-overlay)
+ (if fsharp-error-overlay ()
+ (setq fsharp-error-overlay (make-overlay 1 1))
+ (overlay-put fsharp-error-overlay 'face 'region))
+ (unwind-protect
+ (progn
+ (move-overlay fsharp-error-overlay beg end (current-buffer))
+ (beep) (if wait (read-event) (fsharp-sit-for 60)))
+ (delete-overlay fsharp-error-overlay)))))
+
+;; wait some amount for ouput, that is, until inferior-fsharp-output is set
+;; to true. Hence, interleaves sitting for shorts delays and checking the
+;; flag. Give up after some time. Typing into the source buffer will cancel
+;; waiting, i.e. may report 'No result yet'
+
+(defun fsharp-wait-output (&optional before after)
+ (let ((c 1))
+ (fsharp-sit-for 0 (or before 1))
+ (let ((c 1))
+ (while (and (not inferior-fsharp-output) (< c 99) (fsharp-sit-for 0 c t))
+ (setq c (+ c 1))))
+ (fsharp-sit-for (or after 0) 1)))
+
+;; To insert the last output from fsharp at point
+(defun fsharp-insert-last-output ()
+ "Insert the result of the evaluation of previous phrase"
+ (interactive)
+ (let ((pos (process-mark (get-buffer-process inferior-fsharp-buffer-name))))
+ (insert-buffer-substring inferior-fsharp-buffer-name
+ fsharp-previous-output (- pos 2))))
+
+
+(defun fsharp-simple-send (proc string)
+ (comint-simple-send proc (concat string ";;")))
+
+(defun fsharp-comint-send ()
+ (interactive)
+ (let ((comint-input-sender 'fsharp-simple-send))
+ (comint-send-input)))
+
+(provide 'inf-fsharp)
View
9 bundles/fsharp/init.el
@@ -0,0 +1,9 @@
+
+
+(setq auto-mode-alist (cons '("\\.fs[iylx]?$" . fsharp-mode) auto-mode-alist))
+
+(autoload 'fsharp-mode "fsharp" "Major mode for editing F# code." t)
+(autoload 'run-fsharp "inf-fsharp" "Run an inferior F# process." t)
+
+(setq inferior-fsharp-program "mono ~/Tools/fsharp/fsi.exe --readline-")
+(setq fsharp-compiler "mono ~/Tools/fsharp/fsc.exe")
View
1 initializers/bundles_initializer.el
@@ -59,6 +59,7 @@
;; (elbundle/load-elbundle "ocaml")
(elbundle/load-elbundle "joxa")
(elbundle/load-elbundle "haskell")
+(elbundle/load-elbundle "fsharp")
(elbundle/load-elbundle "perl")
(elbundle/load-elbundle "javascript")
(elbundle/load-elbundle "shell-script")

0 comments on commit 07afaff

Please sign in to comment.
Something went wrong with that request. Please try again.