;(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 "") 'jwall:csharp-dwim) (local-set-key (kbd "") 'mono-build-solution-default) (local-set-key (kbd "") (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))