;;; lang/go/autoload.el -*- lexical-binding: t; -*- (defun +go--spawn (cmd) (save-selected-window (compile cmd))) (defun +go--assert-buffer-visiting () (unless buffer-file-name (user-error "Not in a file-visiting buffer"))) ;;; go test ... (defvar +go-test-last nil "The last test run.") (defun +go--run-tests (args) (let ((cmd (concat "go test -test.v " args))) (setq +go-test-last (concat "cd " default-directory ";" cmd)) (+go--spawn cmd))) ;;;###autoload (defun +go/test-rerun () "Rerun last run test." (interactive) (if +go-test-last (+go--spawn +go-test-last) (+go/test-all))) ;;;###autoload (defun +go/test-all () "Run all tests for this project." (interactive) (+go--run-tests "")) ;;;###autoload (defun +go/test-nested () "Run all tests in current directory and below, recursively." (interactive) (+go--run-tests "./...")) ;;;###autoload (defun +go/test-single () "Run single test at point." (interactive) (+go--assert-buffer-visiting) (unless (string-match-p "_test\\.go$" buffer-file-name) (user-error "Must be in a *_test.go file")) (save-excursion (save-match-data (unless (re-search-backward "^func[ ]+\\(([[:alnum:]]*?[ ]?[*]?[[:alnum:]]+)[ ]+\\)?\\(Test[[:alnum:]_]+\\)(.*)" nil t) (user-error "No detectable test at or after point")) (+go--run-tests (concat "-run" "='^\\Q" (match-string-no-properties 2) "\\E$'"))))) ;;;###autoload (defun +go/test-file () "Run all tests in current file." (interactive) (+go--assert-buffer-visiting) (unless (string-match-p "_test\\.go$" buffer-file-name) (user-error "Must be in a *_test.go file")) (save-excursion (save-match-data (goto-char (point-min)) (let (func-list) (while (re-search-forward "^func[ ]+\\(([[:alnum:]]*?[ ]?[*]?[[:alnum:]]+)[ ]+\\)?\\(Test[[:alnum:]_]+\\)(.*)" nil t) (push (match-string-no-properties 2) func-list)) (unless func-list (user-error "No detectable tests in this file")) (+go--run-tests (concat "-run" "='^(" (string-join func-list "|") ")$'")))))) ;;;###autoload (defun +go/bench-all () "Run all benchmarks in project." (interactive) (+go--run-tests "-test.run=NONE -test.bench=\".*\"")) ;;;###autoload (defun +go/bench-single () "Run benchmark at point." (interactive) (if (string-match "_test\\.go" buffer-file-name) (save-excursion (re-search-backward "^func[ ]+\\(([[:alnum:]]*?[ ]?[*]?[[:alnum:]]+)[ ]+\\)?\\(Benchmark[[:alnum:]_]+\\)(.*)") (+go--run-tests (concat "-test.run=NONE -test.bench" "='^\\Q" (match-string-no-properties 2) "\\E$'"))) (error "Must be in a _test.go file"))) ;;; go generate ... (defun +go--generate (dir args) (unless (file-directory-p dir) (user-error "Directory does not exist: %s" dir)) (+go--spawn (format "cd %s && go generate %s" (shell-quote-argument dir) args))) ;;;###autoload (defun +go/generate-file () "Run \\='go generate' for the current file." (interactive) (+go--assert-buffer-visiting) (+go--generate default-directory (file-name-nondirectory buffer-file-name))) ;;;###autoload (defun +go/generate-dir () "Run \\='go generate' for the current directory, recursively." (interactive) (+go--generate default-directory "./...")) ;;;###autoload (defun +go/generate-all (&optional arg) "Run \\='go generate' for the entire project. Will prompt for the project if you're not in one or if the prefix ARG is non-nil." (interactive "P") (if-let* ((proot (let ((projectile-require-project-root 'prompt)) (projectile-ensure-project (unless arg (doom-project-root)))))) (+go--generate (file-truename proot) "./...") (user-error "Not in a valid project"))) ;;;###autoload (defun +go/play-buffer-or-region (&optional beg end) "Evaluate active selection or buffer in the Go playground." (interactive "r") (if (use-region-p) (go-play-region beg end) (go-play-buffer)))