This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-10-08
Channels
- # announcements (20)
- # aws (16)
- # babashka (63)
- # beginners (75)
- # calva (35)
- # cider (2)
- # clj-commons (5)
- # clj-kondo (2)
- # cljs-dev (1)
- # clojure (90)
- # clojure-australia (3)
- # clojure-europe (16)
- # clojure-france (1)
- # clojure-nl (4)
- # clojure-uk (5)
- # clojurescript (7)
- # data-science (2)
- # datahike (1)
- # datomic (39)
- # emacs (31)
- # events (2)
- # figwheel-main (1)
- # fulcro (15)
- # gratitude (8)
- # helix (17)
- # holy-lambda (1)
- # introduce-yourself (1)
- # jobs (3)
- # kaocha (2)
- # liquid (1)
- # malli (1)
- # nrepl (2)
- # other-languages (1)
- # portal (76)
- # react (19)
- # reagent (9)
- # remote-jobs (1)
- # rewrite-clj (9)
- # shadow-cljs (31)
- # tools-deps (5)
- # xtdb (11)
@djblue How's the VS Code work coming along? Any early .vsix
files for eager pre-alpha testers to try out? 🙂
Pretty close to being done. I've been trying to get the syntax colors but I guess those aren't available to extensions 😭
To avoid some confusion: The vscode extension mainly acts as a launcher so you only have to have it installed, there aren't any commands you run from within vscode
For a fun feature preview, try using the new keyboard shortcut g d
on a selected var 😏
Finally got around to actually trying it -- AWESOME!!!
I've added a task to my (Clover) config that launches Portal inside VS Code and bound it to ctrl-; shift-p
and I'm off to the races! 🙂

My own customizations no longer seem to work (that were messing with those internal hash maps of functions) -- I guess that's been changed now and I need to customize it a different way?
OK, figured that out and updated my setup.
g
o to d
efinition 🙂 very nice!
Seems like the webview panel inside VS Code isn't a full browser, in terms of CSS rendering? When I slurp a Java doc URL and view as HTML, it's pretty much an unstyled HTML page. Still usable, but not as clean as viewing docs in a browser.
Cool. I'm just calling portal.runtime/register!
right now but will switch to an API version once it's there. It's working really nicely for me. Once 0.16.0 is on Clojars, I'll publish my updated dot-clojure and vscode-clover-setup.
Here's what I have in Clover's config.cljs
:
(defn portal-start []
(p/let [here (editor/get-selection)]
(editor/eval-and-render
(assoc here :text
(str "(do"
" (in-ns 'dev)"
" (def portal"
" ((requiring-resolve 'portal.api/open)"
" {:launcher :vs-code}))"
" (install-portal-extras)"
" (add-tap (requiring-resolve 'portal.api/submit)))")))))
(defn portal-clear []
(p/let [here (editor/get-selection)]
(editor/eval-and-render (assoc here :text "(portal.api/clear)"))))
and here's my key bindings for that
{
"key": "ctrl+; shift+k",
"command": "workbench.action.tasks.runTask",
"args": "Clover: Portal clear"
},
{
"key": "ctrl+; shift+P",
"command": "workbench.action.tasks.runTask",
"args": "Clover: Portal start"
},
and the dev/install-portal-extras
is
(defn- install-portal-extras
[]
(try
(let [r! (requiring-resolve 'portal.runtime/register!)
html (fn [url]
(with-meta
[:div
{:style {:background :white}}
[:portal.viewer/html (slurp url)]]
{:portal.viewer/default :portal.viewer/hiccup}))]
;; install extra functions:
(run! (fn [[k f]] (r! f {:name k}))
{'dev/->file (requiring-resolve ')
'dev/->html html
'dev/->map (partial into {})
'dev/->set (partial into #{})
'dev/->vector (partial into [])}))
(catch Throwable _)))
I originally had :portal.launcher/window-title (System/getProperty "user.dir")
in the open
invocation which works great for the Chrome browser version but seems to prevent the VS Code panel from opening? Is there a way to set the Portal tab name in VS Code? Or could it just ignore options that don't work?
Interesting, I'm able to use :portal.launcher/window-title (System/getProperty "user.dir")
without issue :thinking_face:
OK, it was an unrelated issue: if I open a workspace in VS Code rather than just a project, the launcher doesn't open.
So something like code .
then connect to a REPL then portal.api/open
-- that works.
But code some.code-workspace
then connect to the same REPL then portal.api/open
-- nothing happens.
I don't have a workspace that has just one folder (project). All my workspaces have multiple projects (folders). So that seems to be confusing the VS Code launcher. If I run the regular launcher, it works, and I get a browser window.
Yeah, I can reproduce that reliably. code some.code-workspace
can open a regular (Chrome) Portal window but cannot open a VS Code window. The code "runs" but doesn't open a window.
portal.api/open
returns #portal.runtime.jvm.client.Portal {:session-id #uuid "9807ae4d-5d75-489f-816f-2eeb5e1768d0"}
as expected but nothing opens in VS Code.
((requiring-resolve 'portal.api/open)) ; works in standalone project and workspace
((requiring-resolve 'portal.api/open) {:launcher :vs-code}) ; works in standalone project but NOT in a workspace
Hope that helps @djblue LMK if I can do more testing for you.Does those separate projects represent separate processes / repl connections? Or just multiple libraries as part of a single process?
(defn- get-workspace-folder []
(-> vscode/workspace
.-workspaceFolders
(aget 0)
(.. -uri -path)))
This is the bit that's problematic in the vs-code extensionIf it helps, I figured out that if I copy .portal/vs-code.edn
from the workspace root folder (where it is created once Portal is activated) to the folder where the REPL is started, then it works.
So it seems to get confused by the fact that the REPL is running in a different folder to the workspace root (which will just happen to be the first folder in the workspace).
Yeah, I might invert the relationship and have the repl process drop a file and the extension watch for it in all workspaces folders :thinking_face:
That won't work for setups where the REPL is started in a different folder -- that is not a root folder.
At work, we have a workspace with two folders: wsmain
and worldsingles
. But the REPL is always started in wsmain/clojure
.
In the general case, I may well start a REPL in a folder that is completely outside any VS Code workspace.
The other idea I had was limiting the vs-code http-server port range and doing a broadcast from the repl process
So the server process started in Portal (as an extension) is a VS Code HTTP server? Interesting.
Well there are two. One in the extension waiting for a call to open a webview and another in the repl process hosting everything else.
Oh, I guess I was confused by the add-tap
in the extension code... That's for you to debug the extension?
Well, I guess for my use case, it would work if the JVM launcher walked up the file system looking for .portal
?
That would at least allow a REPL to be started in a subfolder which is common in monorepo situations.
Is it common the have two process for a single mono repo? I wonder if one repl would clobber another
In the more general case, I don't think Portal could possibly know how to bridge a REPL started in an arbitrary different folder tho'...
For monorepos, you typically have just one REPL. It just isn't always started in the root.
But I can imagine people having multiple Clojure projects in a workspace and having multiple REPLs -- one from each Clojure project -- but Calva/Clover is only going to be connected to one of them at any point in time.
If I leave the .portal/vs-code.edn
file around (and .gitignore
it), will Portal always just reuse that server/port?
Not currently, but it could. Although I do thing the parent walking trick should be easy enough to do
OK, so one problem you'd have is that if you started two instances of VS Code -- one in a folder and one for a workspace for which that is the root folder -- it would overwrite the vs-code.edn
file in that folder.
And in fact if you reload VS Code, it reactivates the extensions and would overwrite the workspace root vs-code.edn
file anyway with a new port number -- and then the REPL still running would try to talk to the old server which has gone away, right?
So I think you need to have the extension code reuse vs-code.edn
to avoid that scenario?
(I reload/restart VS Code a lot more often than I restart a REPL)
Would I have to do portal.api/close
on the JVM every time I restarted VS Code in order to clear the old server information and get the JVM Portal to connect to the (new) VS Code server?
The vs-code.edn file is only used for the initial portal.api/open function. So if you restart and a new file is available and you call portal.api/open again it should be wired against the new instance of vs-code.
I think https://github.com/djblue/portal/commit/92310049ddd2cce0ace8f19f1d54950bfb153b14 might be good enough for now
I did a symlink between the two folders to test what happens if I reload VS Code (and that puts a different port into vs-code.edn
) but leave the REPL running -- and the answer is: that works just fine, so the REPL does not "lose" the Portal connection.
I'll remove the symlink and try that updated JAR next.
Perfect! Yup, that finds the .portal/vs-code.edn
up the file tree and works "as expected". Thank you!

I'll have to think about what to do with the multi-project workspace thing. I suspect I can solve that with symlinks (so all the REPL-based projects in the workspace talk to the same VS Code Portal instance...).
With the multi-project workspace, it seems like I need to open a separate Portal view in VS Code for each backend REPL, if I want to switch between them -- because there's no way to just tell the backend "Oh, yeah, Portal is open and it's on port XYZ". But that's fine. I can definitely live with that (and it is a very unusual setup).
(and that was part of why I wanted the Portal window title to include the directory where the open
call was made so I could keep track of which Portal was attached to which REPL anyway).
(and, yes, that's with symlinks in place for all the folders in the workspace, pointing to a "master" .portal
folder elsewhere 🙂 )
Yeah, currently the portal client ui can only handle a connection to a single runtime. In the future I might remove this limitation
Clover can only connect to one REPL so that's fine.
Here's what my OSS project workspace looks like with two REPLs in the background (for honeysql and next.jdbc) and two Portal views:
One more question if you have the time. Would you rather specify :launcher :vs-code
or have portal assume you want to use vs-code if it can find the .portal/vs-code.edn
file?
I would rather it was explicit. I may still want to launch a browser-based Portal window sometimes.