This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-21
Channels
- # announcements (13)
- # babashka (63)
- # babashka-sci-dev (64)
- # beginners (37)
- # biff (1)
- # calva (10)
- # cider (7)
- # clj-kondo (15)
- # cljsrn (6)
- # clojure (26)
- # clojure-dev (10)
- # clojure-europe (34)
- # clojure-france (9)
- # clojure-nl (2)
- # clojure-norway (36)
- # clojure-uk (5)
- # clojurescript (142)
- # community-development (1)
- # conjure (3)
- # datalevin (5)
- # datalog (2)
- # datomic (5)
- # events (11)
- # fulcro (40)
- # gratitude (9)
- # guix (32)
- # honeysql (10)
- # jobs (2)
- # lsp (32)
- # malli (15)
- # meander (5)
- # membrane (43)
- # missionary (3)
- # nextjournal (9)
- # off-topic (38)
- # pathom (3)
- # polylith (30)
- # portal (78)
- # programming-beginners (4)
- # quil (6)
- # re-frame (20)
- # reagent (21)
- # remote-jobs (2)
- # shadow-cljs (7)
- # tools-deps (6)
- # xtdb (23)
New questions. My workflow is amazing in the JVM since when I started using functions like:
(defun portal.ui.commands/select-next ()
(interactive)
(portal/invoke-portal-command
"(portal.ui.commands/select-next portal.ui.state/state)"))
but these don't work when I open portal from a cljs repl. Is there any known reason for this @djblue?If for the cljs repl, you are using portal.web, you may need to conditionally swap out portal.api/eval-str
to portal.web/eval-str
in your command via a reader condition š
If for the cljs repl, you are using the remote api and sending taps to a remote instance of portal hosted via the jvm, the commands would need to be executed against a jvm repl.
yes that was indeed the case, and I messed up my emacs file, so I wasn't seeing it š. The other question was: usually I start portal from a user.clj
file, but here if I try to use it from a user.cljs
file, which is not imported by the main file of my project, the repl will say:
Execution error (ReferenceError) at (<cljs repl>:1).
user is not defined
what's the correct way of using a user.cljs namespace?it's possible that's shadow.user
, by reading the shadow docs, but do people just use that?
(defun portal/invoke-portal-command (command-str)
(cider-nrepl-sync-request:eval
(concat "(#?(:clj portal.api/eval-str :cljs portal.web/eval-str) \"" command-str "\")")))
This is for doom emacs, but the core functions should be usable anywhere.
Wait. Are you controlling portal - outside of Emacs - with a hydra - inside Emacs? I have to try this.
yes, that's the purpose of all this line of thinking. It started because I couldn't control the shortcuts, but then I understood the brilliant design decision of accepting UI commands from an external source
Very nice! Thanks! I had super simple setup an advice function to tap the things I evaluated. This is much better! Do you have to click on any element before using the hydra for it to start working? Mine isn't working until I click an element inside portal, then r,h,j,l,k start working.
@UJCC6CE9E No I don't need to click anything, basically the function select-root
is used to select the top level element in case nothing is selected (and then I can use h,j,l,k)
@UA7E6DU04 Yes, thanks! Yesterday I got it working, I think that maybe I had an older version of portal because I didn't see the select-root
function in the command palette. Btw, have you tried calling copy | copy-path | copy-json
from emacs?
Oh yes, that's it, select root was added very recently! Unfortunately I never had a compelling use case that forced me to set up copy | copy-path | copy-json
for now, how are you using them?
I sometimes use copy with data that comes from a db/http request or even from taps that I've added. I havent had use cases for the other 2. Calling
(portal/invoke-portal-command
"(portal.ui.commands/copy portal.ui.state/state)")
isn't working for me . I'm trying to figure out why.Might be a clipboard permission issue or because copy is returning a #object[HTMLTextAreaElement [object HTMLTextAreaElement]]
:thinking_face:. Try wrapping it in a (do ... nil)
and see if that works.
@djblue what should be wrapped in a (do ... nil)
?
(portal.web/eval-str
"(do (portal.ui.commands/copy portal.ui.state/state) nil)")
this returns nil
but nothing gets put in the clipboardI can get:
(portal.web/eval-str
"(.-value (portal.ui.commands/copy portal.ui.state/state))")
to show me the text value, but not to copy it to the clipboardok, now I explicitly granted clipboard permissions to localhost:3000
and that didn't seems to change anything
@UJCC6CE9E is this working for you?
Weird, it's the same https://github.com/djblue/portal/blob/master/src/portal/ui/commands.cljs#L624-L646
doesn't that lack something like:
navigator.clipboard.writeText(copyText.value);
https://www.w3schools.com/howto/howto_js_copy_clipboard.aspThis doesn't copy anything for me:
(let [el (js/document.createElement "textarea")]
(set! (.-value el) "Hey there")
(js/document.body.appendChild el)
(.select el)
)
No worries, this method of copying might be outdated and we could switch to a modern approach
Mind switching to navigator.clipboard.writeText(copyText.value);
and see if that works in linux?
(let [el (js/document.createElement "textarea")]
(set! (.-value el) "Buongiorno signore")
(js/document.body.appendChild el)
(.select el)
(.-value el)
(js/Promise.resolve (.writeText (.-clipboard js/navigator) "HEEEEY")))
the problem with the clipboard API anyway is that:
Don't try the above code in the console. To use the Clipboard API, the document needs to be in a focused state. Otherwise, a DOMException will be thrown.
thinking generally though, this just means that maybe I shouldn't try to call that command from emacs. Instead I could just select the bit I'm interested in, and arrange emacs to insert @p
in the buffer
it's a pleasure, thank you for answering all my questions! Btw I just fixed the definition of the clear
function
the only thing that I still feel could have a bit more support from the portal side, is having nice commands to change the viewers of the data (my code isn't yet working properly for that my code works but I would prefer if it was cleaner š)
I'm also curious about why this approach doesn't work, when I call the function from the portal ui
(defn add-pprint-viewer-meta [thing]
(with-meta thing {:portal.viewer/default :portal.viewer/pprint}))
(p/register! #'add-pprint-viewer-meta)
I think it has to do with how portal is capturing runtime objects. Portal is only checking value equality, not metadata. Since the UI has already received this value, the UI receives the ID of the previous value with the old metadata.
hmm I see. Do we have a way of setting new predicates from the user side? Like, if you have data of this form [[{:a :b}]]
I feel having to traverse two layers of vector is rarely the first choice I'd make
I think https://github.com/djblue/portal/commit/42c1ce934d38b9c2e171659e4b7b54467eae02da should fix the metadata issue
I've been thinking about adding a user defined way to specify a function which can pick a default viewer
yes, that's the kind of think I have in mind. The expectation I would have is being able to easily "patch" the default behavior; so, if none of viewers apply, I fall back to the viewers as they are now
also, I'd like to know how to write more complex visualizers; for example, I'd love to write a visualizer for music or for the custom objects in my code
For custom viewers, there are a few options:
ā¢ hiccup + existing viewers - only allows composition of existing viewers, no new behavior
ā¢ vega / vega-lite - pretty extensive data dsl for viz
ā¢ full reagent component registered via portal.ui.api/register-viewer!
and code loading is handled via eval-str
, however no direct support for npm libs
So, regarding equality. If I evaluate (list 1 2 3)
and then [1 2 3]
the second result will be displayed as (1 2 3)
probably because it's already cached and (= (1 2 3) [1 2 3])
, but I think it's an extremely confusing effect