As I understand it, you basically want to run a command in the REPL. That is, I think you're saying you want to press C-M-S-g and have it execute (go) in the REPL.
Emacs interacts with processes through a comint, or command interpreter. For example,
Shell mode is a derivative of Comint mode, a general-purpose mode for communicating with interactive subprocesses. Most of the features of Shell mode actually come from Comint mode...
https://www.gnu.org/software/emacs/manual/html_node/emacs/Shell-Mode.html
The cider REPL must be communicating with a process. Therefore, it must be a comint.
I know next to nothing about Clojure or CIDER. Rather than try to give an answer tailored to those, I will give something general which should address the problem, as I understand it, and be useful elsewhere. This is from my init and is one of my favorite hacks.
A common task for me is copying text from one buffer to another. Sometimes that buffer is just a regular buffer, other times it's a comint. Often, I don't know where I'll need to copy text to. The target must be determined "on demand".
The following defines a new variable, xc/on-demand-window. It defines the target for where text should go. Note that this is defined in terms of windows1. This makes the target location fixed.
(defvar xc/on-demand-window nil "Target on-demand window. An on-demand window is one which you wish to return to within the current Emacs session but whose importance doesn't warrant a permanent binding.")
The next function makes defining the target window more user friendly. Call xc/on-demand-window to set the target to the currently selected window. In your case, once the REPL is up, select that window and call this.
(defun xc/on-demand-window-set () "Set the value of the on-demand window to current window." (interactive) (setq xc/on-demand-window (selected-window)) (message "Set on-demand window to: %s" xc/on-demand-window))
It's handy to jump between the source window and the target. Call xc/on-demand-window-goto to do that.
(defun xc/on-demand-window-goto () "Goto the `xc/on-demand-window'." (interactive) (let ((win xc/on-demand-window)) (unless win (error "No on-demand window set! See `xc/on-demand-window-set'.")) (if (eq (selected-window) xc/on-demand-window) (error "Already in `xc/on-demand-window'")) (let ((frame (window-frame win))) (raise-frame frame) (select-frame frame) (select-window win))))
Ultimately, you want to send text to the REPL. The function xc/send-line-or-region is for interactively sending text. It's a bit of overkill but like I said, it was already in my init. It will send a line or region to the on-demand window (or current window if the on-demand window is not set). If the on-demand window's buffer has no process, the line is simply inserted. However, if the buffer has a process, as should be the case with the REPL, the line will be inserted and sent to the process. It has the added option to insert a new line for non-text buffers.
(defun xc/send-line-or-region (&optional advance buff beg end) "Send region or line to BUFF. If buffer has a process, insert and send line to the process. If no process, then simply insert text at point. Create a new line when ADVANCE is non-nil. Use current region if BEG and END not provided. If no region provided, send entire line. Default BUFF is the buffer associated with `xc/on-demand-window'." (interactive (if (use-region-p) (list nil nil (region-beginning) (region-end)) (list nil nil nil nil))) (let* ((beg (or beg (if (use-region-p) (region-beginning)) nil)) (end (or end (if (use-region-p) (region-end)) nil)) (substr (string-trim (or (and beg end (buffer-substring-no-properties beg end)) (buffer-substring-no-properties (line-beginning-position) (line-end-position))))) (buff (or buff (window-buffer xc/on-demand-window))) (proc (get-buffer-process buff))) (if substr (with-selected-window (get-buffer-window buff t) (let ((window-point-insertion-type t)) ; advance marker on insert (cond (proc (goto-char (process-mark proc)) (insert substr) (comint-send-input nil t)) (t (insert substr) (if advance (progn (end-of-line) (newline-and-indent))))))) (error "Invalid selection"))))
Send a string to the on-demand window with xc/send-string. This is probably more to your question. It works the same way as xc/send-line-or-region, but acts on a fixed string. When called with M-x, it will prompt for what string to send. I also added a history so that you can press up/down or M-p/M-n to see previously sent strings.
(defvar xc--send-string-history nil "History of strings sent via `xc/send-string'") (defun xc/send-string (string &optional advance buff) "Send STRING to BUFF'. Default BUFF is the buffer associated with `xc/on-demand-window' (or current window if not set). If BUFF has an associated process, send region as input, otherwise just insert the region. Create a new line when ADVANCE is non-nil." (interactive (let* ((prompt (format "Send string to % s: " (window-buffer xc/on-demand-window))) (cmd (read-string prompt "" 'xc--on-demand-send-string-history))) (list cmd nil nil))) (let* ((buff (or buff (window-buffer xc/on-demand-window))) (proc (get-buffer-process buff))) (with-selected-window (get-buffer-window buff t) (let ((window-point-insertion-type t)) ; advance marker on insert (cond (proc (goto-char (process-mark proc)) (insert string) (comint-send-input nil t)) (t (insert string) (if advance (progn (end-of-line) (newline-and-indent)))))))))
You can then do what you want with something like:
(global-set-key (kbd "C-M-S-g") '(lambda () (interactive) (xc/send-string "(go)")))
Hopefully that helps! Happy hacking!
NOTE The xc/send-line-or-region and xc/send-string commands use string-trim which doesn't seem to autoload. You may need to call (require 'subr-x) first.
EDIT The previous code handles sending to the REPL. The link you gave on the 5th gives a clue about handling namespaces.
Since namespaces are part of the language used by the comint/REPL, they must be handled within the string sent to the comint/REPL.
I've not used Clojure, but modifying the "essential pattern", the string that needs to be sent is (or is something like):
"(require 'user) (user/go (go))"
So, using xc/send-string,
(global-set-key (kbd "C-M-S-g") '(lambda () (interactive) (xc/send-string "(require 'user) (user/go (go))"))
Honestly, though, it looks like this function from the article you linked would do something comparable if the sexp before point were (go) (and the appropriate some-namespace/some-namespace-fn replacement made):
(defun custom-eval-last-sexp () (interactive) (cider-interactive-eval (format "(require 'some-namespace) (some-namespace/some-fn %s)" (cider-last-sexp))))
Hopefully that's enough for you to modify things to your need.
1 Although we need to send text to a buffer, I've found that it's actually the window I want to interact with. It's somewhat arbitrary since it's possible to get the buffer from a window and vice-versa. I've done it both ways and this is what has survived in my init. Feel free, of course, to try it the other way.