227 lines
8.4 KiB
EmacsLisp

;(add-to-list 'load-path (expand-file-name "~/lib/elisp/omnisharp-emacs"))
(require 'flycheck)
(require 'flymake)
(require 'omnisharp)
(setq omnisharp-server-executable-path "~/sandbox/apps/omnisharp-server/OmniSharp/bin/Debug/OmniSharp.exe")
(defvar nunit-runner (executable-find "nunit-console")
"NUnit console runner command")
(defvar msbuild-runner (executable-find "xbuild")
"MSBuild console runner command")
(defvar mono-configuration "Debug"
"The default configuration to use when building a mono solution.")
(defun jwall:set-mono-configuration (configuration)
"Set the configuration for the current buffer to use when building a
mono solution."
(interactive "MConfiguration: ")
(setq mono-configuration configuration))
;; TODO(jwall): Standardize these with my jwall: prefix
;; utility functions for dealing with the msbuild and VS sln files.
(defun csharp-find-project-directory ()
(interactive)
(walk-up-dirs default-directory
(lambda (f)
;; (message "testing %s" f)
(string-match "\\.csproj$" f 0))))
(defun csharp-find-project-file ()
(interactive)
(let ((project-file nil))
(walk-up-dirs default-directory
(lambda (f)
;; (message "testing %s" f)
(let ((found (string-match "\\.csproj$" f 0)))
(if found
(setq project-file f)))))
(concat (csharp-find-project-directory) "/" project-file)))
(defun mono-find-solution-file ()
(interactive)
(let ((solution-file nil))
;; TODO(jeremy): Make this configurable.
(walk-up-dirs default-directory
(lambda (f)
;; (message "testing %s" f)
(let ((found (string-match "\\.sln$" f 0)))
(if found
(setq solution-file f)))))
(concat (mono-find-solution-directory) "/" solution-file)))
(defun mono-find-solution-directory ()
(interactive)
(walk-up-dirs default-directory
(lambda (f)
;; (message "testing %s" f)
(string-match "\\.sln$" f 0))))
(defun csharp-build-project-cmd (project-file configuration)
(concat msbuild-runner
" /property:Configuration=" configuration
" /property:GenerateFullPaths=true"
" " project-file))
(defvar csharp-build-project-history nil
"History for the csharp-build-project command.")
(defvar csharp-build-project-configuration-history nil
"History for the csharp-build-project command.")
(defun csharp-build-project (project-file configuration)
"Builds the current csharp project as defined by the csproj file.
Uses xbuild for the compile command."
(interactive
(progn
(list (read-shell-command "Project File: "
(csharp-find-project-file)
'csharp-build-project-history))
(list (read-shell-command "Configuration: "
(mono-configuration)
'csharp-build-project-configuration-history))
))
(message (concat "building: " project-file))
(compile (csharp-build-project-cmd project-file configuration)))
(defvar mono-build-solution-history nil
"History for the mono-build-solution command.")
(defvar mono-build-solution-configuration-history nil
"History for the mono-build-solution command.")
(defun mono-build-solution-cmd (solution-file configuration)
(concat msbuild-runner
" /property:Configuration=" configuration
" /property:GenerateFullPaths=true"
" " solution-file))
(defun mono-build-solution (solution-file configuration)
"Builds the current Visual Studio Solution as defined by the sln file.
Uses xbuild for the compile command."
(interactive
(progn
(list (read-shell-command "Solution File: "
(mono-find-solution-file)
'mono-build-solution-history)
(read-shell-command "Configuration: "
mono-configuration
'mono-build-solution-configuration-history))))
(omnisharp--recognize-mono-compilation-error-format)
(compile (mono-build-solution-cmd solution-file configuration)))
(defun mono-build-solution-default ()
(interactive)
(mono-build-solution (mono-find-solution-file) mono-configuration))
(defun csharp-get-project-dll (project-file)
(interactive
(progn
(list (read-shell-command "Project File: "
(csharp-find-project-file)
'csharp-build-project-history))))
(let* ((base-name (file-name-base project-file))
(dir-name (file-name-directory project-file))
(dll-name (concat dir-name "bin/Debug/" base-name ".dll")))
dll-name))
;; automation functions
(defun csharp-repl ()
"Switch to the CSharpRepl buffer, creating it if necessary."
(interactive)
(let ((buf (get-buffer "*csharp*")))
(if buf
(pop-to-buffer buf)
(progn
(split-window)
(other-window 1)
(comint-run "csharp")))))
(defun jwall:csharp-dwim ()
(interactive)
(let ((file (buffer-file-name))
(project-file (csharp-find-project-file)))
(message (concat "Running dwim with " file " and " project-file))
(if (string-match ".*Test[^\\.]*\.cs" file)
(progn
(message "Apparently I think this is a unit test.")
(jwall:csharp-run-single-unit-test))
(progn
(if (string-match ".*\\.cs" file)
(progn
(message "It's a regular file!")
(csharp-build-project project-file mono-configuration)))
(message "I didn't match for regular")
(message "I didn't match for test")))))
(defun jwall:csharp-run-single-unit-test ()
(interactive)
(jwall:omnisharp-unit-test "single" (csharp-find-project-file)))
(defvar mono-nunit-run-mode-history nil
"History for the mono-build-solution command.")
;; Shamelessly stolen from the https://github.com/sp3ctum/omnisharp-emacs/
(defun jwall:omnisharp-unit-test (mode project-file)
"Run tests after building the solution. Mode should be one of 'single', 'fixture' or 'all'"
(interactive
(progn
(list (read-shell-command "Mode: "
"single"
'mono-nunit-run-mode-history)
(read-shell-command "Project File: "
(csharp-find-project-file)
'mono-build-project-history))))
(let* ((build-command
(csharp-build-project-cmd project-file mono-configuration))
(test-command
(omnisharp--fix-build-command-if-on-windows
(cdr (assoc 'TestCommand
(omnisharp-post-message-curl-as-json
(concat (omnisharp-get-host) "gettestcontext")
(cons `("Type" . ,mode) (omnisharp--get-common-params)))))))
(all-command (concat "cd " (mono-find-solution-directory)" && " build-command " && " test-command)))
(message all-command)
(compile all-command)))
(defun jwall:mono-omnisharp-load ()
(interactive)
(omnisharp-stop-server)
(omnisharp-start-omnisharp-server (mono-find-solution-file))
;; TODO(jwall): Wait for omnisharp server to start up.
;(run-at-time 5 nil 'flycheck-mode)
)
(defun my-csharp-mode-hook ()
(setq-local company-idle-delay 0.5)
(setq-local flycheck-idle-change-delay 1)
; inherit out offset length for csharp code from tab-width
(setq-local c-basic-offset tab-width)
; don't autoindent braces in regular statements.
;(add-to-list 'c-hanging-braces-alist '(statement))
; don't indent the braces in a stubstatement e.g:
; if
; {
(c-set-offset 'substatement-open 0)
;; setup keybindings
(local-set-key (kbd "<f4>") 'jwall:csharp-dwim)
(local-set-key (kbd "<f6>") 'mono-build-solution-default)
(local-set-key (kbd "<f7>") (lambda () (jwall:omnisharp-unit-test "Fixture")))
(local-set-key (kbd "C-x C-c R") 'mono-build-solution-default)
(local-set-key (kbd "C-c C-z") 'csharp-repl)
(omnisharp-mode)
(company-mode)
(eldoc-mode)
(flycheck-mode)
)
(add-hook 'csharp-mode-hook 'my-csharp-mode-hook)
(setq omnisharp-debug nil)
;(setq omnisharp-auto-complete-want-documentation nil)
(autoload 'csharp-mode "csharp-mode" "Major mode for editing C# code.")
(setq auto-mode-alist (append '(("\\.cs$" . csharp-mode)) auto-mode-alist))
(eval-after-load 'company
'(add-to-list 'company-backends 'company-omnisharp))