If you are an emacs + cider user and would like tighter integration with portal, the following section may be of interest to you.
;; Leverage an existing cider nrepl connection to evaluate portal.api functions
;; and map them to convenient key bindings.
;; def portal to the dev namespace to allow dereferencing via @dev/portal
(defun portal.api/open ()
(interactive)
(cider-nrepl-sync-request:eval
"(do (ns dev) (def portal ((requiring-resolve 'portal.api/open))) (add-tap (requiring-resolve 'portal.api/submit)))"))
(defun portal.api/clear ()
(interactive)
(cider-nrepl-sync-request:eval "(portal.api/clear)"))
(defun portal.api/close ()
(interactive)
(cider-nrepl-sync-request:eval "(portal.api/close)"))
;; Example key mappings for doom emacs
(map! :map clojure-mode-map
;; cmd + o
:n "s-o" #'portal.api/open
;; ctrl + l
:n "C-l" #'portal.api/clear)
;; NOTE: You do need to have portal on the class path and the easiest way I know
;; how is via a clj user or project alias.
(setq cider-clojure-cli-aliases ":portal")
If you would like to run the Portal UI in emacs itself, you can do so with the following code.
Note You need a build of emacs with Embedded-WebKit-Widgets Also, this method only works if you're using emacs server functionality as it relies on
emacsclient
command
(portal.api/open {:launcher :emacs})
Warning I haven't tested this extensively so you might run into some weird issues
For Monroe nREPL client users.
Add the following to your Emacs config:
; -*- lexical-binding: t; -*-
;; The line above is really important, otherwise things will not work.
;; A little helper to simplify communication between Emacs and the nREPL process
(defun monroe-eval-code-and-callback-with-value (code-str on-value)
(monroe-send-eval-string
code-str
(lambda (response)
(condition-case err
(monroe-dbind-response response
(value status id)
(when value (funcall on-value value))
(when (member "done" status)
(remhash id monroe-requests)))
(error (message "Eval error %s" err))))))
(defun monroe-launch-portal ()
(interactive)
(monroe-eval-code-and-callback-with-value
"(do
(require 'portal.api)
(let [url (portal.api/url (portal.api/open {:launcher false}))]
(add-tap #'portal.api/submit)
url)"
(lambda (value)
;; value is a raw string, so we need to remove " from it
(let ((url (string-replace "\"" "" value)))
(message "Opening portal %s" url)
(xwidget-webkit-browse-url url)))))
Then in the Monroe REPL or Clojure buffer with an active Monroe session run M-x monroe-launch-portal
.
Note
This is just a jump-off point, you might want to customize this function to your liking, e.g. run the code in your
user
namespace, set a different theme and so on. See CIDER section for how you can extend it further.