This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-07-06
Channels
- # announcements (3)
- # biff (13)
- # cider (11)
- # clojure (4)
- # clojure-dev (6)
- # clojure-europe (96)
- # clojure-norway (14)
- # clojure-spec (1)
- # clojure-sweden (1)
- # clojurescript (7)
- # conjure (2)
- # core-logic (2)
- # events (1)
- # hyperfiddle (8)
- # introduce-yourself (9)
- # nbb (12)
- # off-topic (70)
- # pedestal (3)
- # releases (1)
- # squint (2)
- # tools-deps (20)
- # yamlscript (1)
any regex masters to help with a https://github.com/afucher/clojure-repl-intellij/issues/79 😅?
There is a regex (`.*>\s+([^>]+)$`) that should catch what the user wanna eval, but it's missing some cases like in the print: Test strings:
user> foo
foo> 12
foo> asdasd
asd
asdas?
asd
foo> 123123
foo> sdsd->asd
fga> (tap> 232)
foo> 123*&$#!?<+-
foo> (bar [1 2 3])
https://regex101.com/the hard part is to match a code with \n
too, but the issue bug is that we are not matching >
, (because of the [^>]
), my idea is that I want to match anything until the next \n.*>
or all if there is none.
But... if you like a puzzle... maybe this would work?:
(?m)(^\w+>\s*)([\s\S]*?)(?=\n^\w+>\s*|\z)
Yeah, I definitely would prefer avoid the regex, but the way clojure-repl-intellij works ATM, we don't have much choice, we only have a raw text of the reply content
https://github.com/afucher/clojure-repl-intellij/blob/b4a3d089cb19629fbc9460c4ff69d07a31e31619/src/main/clojure/com/github/clojure_repl/intellij/ui/repl.clj#L16 is the current code
I tested the above over at http://regex101.com against your sample input. Seems to work, at least there!
yes, it works on the regex101! thank you
for some reason in the clojure it works differently :thinking_face:
I mean, for this case, it should return the last foo
only (the code that needs to be evaluated)
For your original sample I'm finding it works, I think. I'm really not sure exactly what you need. But:
(def sample (slurp "sample.txt"))
(def matcher (re-matcher #"(?m)(^\w+>\s*)([\s\S]*?)(?=\n^\w+>\s*|\z)" sample))
(re-find matcher)
;; => ["user> foo" "user> " "foo"]
(re-find matcher)
;; => ["foo> 12" "foo> " "12"]
(re-find matcher)
;; => ["foo> asdasd\nasd\nasdas?\n\nasd" "foo> " "asdasd\nasd\nasdas?\n\nasd"]
(re-find matcher)
;; => ["foo> 123123" "foo> " "123123"]
(re-find matcher)
;; => ["foo> sdsd->asd" "foo> " "sdsd->asd"]
(re-find matcher)
;; => ["fga> (tap> 232)" "fga> " "(tap> 232)"]
(re-find matcher)
;; => ["foo> 123*&$#!?<+-" "foo> " "123*&$#!?<+-"]
(re-find matcher)
;; => ["foo> (bar [1 2 3])\n" "foo> " "(bar [1 2 3])\n"]
(re-find matcher)
;; => nil
Interesting, I think it's a corner case with repl results ;; => 1
this is the sample I'm using:
";; some text here
user> 1
;; => 1
user> foo"
using that regex, the last group returned is: "i\n;; => 1"
but it should be foo
Here's my results for your new sample (which I plunked in a file):
(re-find matcher)
;; => ["user> 1\n;; => 1" "user> " "1\n;; => 1"]
(re-find matcher)
;; => ["user> foo\n" "user> " "foo\n"]
(re-find matcher)
;; => nil
Did you want to match the ;;
lines differently somehow?ah got it, TBH I didn't know re-find and re-matcher behave that different, so yeah, I'd want the second result of (re-find matcher)
, is tere any way to get that using re-find
? Otherwise I don't know how I can use it like you showed because I'd need to always get the last result that is not nil I suppose
Without understanding the constraints you are up against, could you use re-seq
like so? (I have your 2nd sample in sample2.txt
)
(->> "sample2.txt"
slurp
(re-seq #"(?m)(^\w+>\s*)([\s\S]*?)(?=\n^\w+>\s*|\z)")
last)
;; => ["user> foo\n" "user> " "foo\n"]
Actually, this regex is complicated enough to merit comments (note the x
in (?mx)
):
(->> "sample2.txt"
slurp
(re-seq #"(?mx) # match multiline and allow comments
(^\w+>\s*) # group1: match the prompt
([\s\S]*?) # group2: match entry
# - we use [\s\S] instead of . because . does not match newlines
(?=\n^\w+>\s*|\z) # lookahead for next prompt or end of string")
last)
;; => ["user> foo\n" "user> " "foo\n"]
If I come to understand what you are really trying to extract, we can probably simplify
sorry for the delay, and thanks for the help so far!
Let me explain how the feature works, we have https://github.com/afucher/clojure-repl-intellij plugin which is basically cider for intellij, so we have a REPL output where the user can see and interact with a repl (print1).
https://github.com/afucher/clojure-repl-intellij/blob/b4a3d089cb19629fbc9460c4ff69d07a31e31619/src/main/clojure/com/github/clojure_repl/intellij/ui/repl.clj#L79 that builds that REPL is basically some seesaw
which is java swing under the hood.
The way it works ATM is that is a fancy JTextField, and when user inputs the code that wants to evaluate we need to know that code, but since it's a JTextField all the previous written and outputed content will be there, so we use a regex to extract the code user wants to send to repl, I know it's not pretty, but I tried to create a cider similar xp, than have a output window and a input one, does that makes sense?
Oh cool! As an old colleague and I used to joke sometimes, "A job all done!" (instead of "A job well done!")
yeah, I with we didn't need the regex, as "If you solve a problem with regex, now you have 2 problems" 😂

There is also https://github.com/lambdaisland/regal which provides a different way to doc regexes.
hehe found a corner case with -
:
for ns with -
or .
on its name
(extract-code-to-eval ";; some text here
user> 1
;; => 1
user-bar.a> foo")
=> "1\n;; => 1\nuser-bar.a> foo"
manage to fix it with this regex:
#"(?mx) # match multiline and allow comments
(^.+>\s*) # group1: match the prompt
([\s\S]*?) # group2: match entry
# - we use [\s\S] instead of . because . does not match newlines
(?=\n^.+>\s*|\z) # lookahead for next prompt or end of string"
not sure I'll break other casesalthough would be safer to check for -
and .
as I don't think namespaces can have other crazy chars
also that breaks the original issue:
(extract-code-to-eval ";; some text here
user> 1
;; => 1
user> (tap> 1)")
as we want to fix the usage of functions with >
on their namethat seems to fix for ns with -
but not with .
:thinking_face:
#"(?mx) # match multiline and allow comments
(^[\w|-|\.]+>\s*) # group1: match the prompt
([\s\S]*?) # group2: match entry
# - we use [\s\S] instead of . because . does not match newlines
(?=\n^[\w|-|\.]+>\s*|\z) # lookahead for next prompt or end of string"
You character class looks off. Just list the chars, no need for the |
bars or the escapes \
, so maybe [\w.-]
ok, new corner case, but seems it's almost there
(defn code [& strings]
(string/join "\n" strings))
(deftest foo
(is (= (code "(defn foo []"
" (tap> 123)"
" 123)")
(#'ui.repl/extract-code-to-eval (code ";; some text here"
"user-bar.baz> 1"
";; => 1"
"user-bar.baz> (defn foo []"
" (tap> 123)"
" 123)")))))
hum, actually it's related with the ns name as well, because changing from user-bar.baz
to user
works
I think I covered all discussed cases, enough to solve the issue, I'll create more unit tests later thank you so much for the help @UE21H2HHD! will co-author you if you don't mind but need your github email
I'm gonna guess you'll uncover more edge cases! If you don't absolutely have to use regexes, you might consider something like https://github.com/Engelberg/instaparse. Or just parse line by line if you can. I think that would be easier.
yeah, I thought about parsing each line but sounded harder, but it probably worth the try
I'm starting to think that we should just create drastically less stuff. Perhaps I'm late to the party. But. Write less code. Move slower. Actually know what we're doing. Not try to make anyone work as fast as they can, rather give and encourage slack.
There was a Dan North talk where he said something like "the goal of the software industry isn't to produce software, it's to solve problems... if you can solve problems without creating software, you win at software"

I was going over my OSS projects today and seeing what "needed" doing and in the end I just did some editorial stuff on http://clojure-doc.org -- the rest was either "not needed" or "I haven't figured out a good solution" so I'd rather not add code unless I really have a purely additive and fairly minimal change.
I've been thinking about this lately as well. At work, it tends to be that there's a project, with a deadline, and you work towards it. And it seems the solution to make those deadlines has become brute force and sheer will power. Some kinds of: work longer, work harder, hire more people, get some contractors, pull people off from other less important projects, etc. And this has been going for a long time. But it creates a result where the next one you need to work even more hard, more long, bring in even more people, or accept that the deadline won't happen. And I can't help but feel like, you don't need that many people, you don't need to work hard and long. You need to be smarter. When you make a change, it's got to be impactful, and well thought through, keep things simple, decomplected and won't mess up with the integrity of the system. And you need to work on having good teams, that know what they are doing. In my opinion, good teams that know what they are doing and allowing for changes to be well thought out, actually results in a much higher velocity and ending up delivering a lot more quickly and with way better results. My conclusion is it's really hard from a management/hiring point of view to build good teams like that, and trust them that them "taking their time" will in fact make projects launch faster and better.
I remember this picture going around bashing open floorplans then the creator of react commented they would have never been able to create react in any other environment Sort of making the point there, bud
I would argue that making breaking API changes every 20 minutes isn't "agile" either, but it all comes down to how people view "agile". It can be a case of "just 2 days of bugfixes and deployments and mad customers saved us 2 hours of design conversation". This sort of reminds me of the hammock-driven development talk - it's faster to fix the bugs in design, so it's often not slower, but it can appear slower if the metric of speed is counting deployments or stories (without noting how many of those deployments/stories are re-work).
Being ‘agile’ is commonly used as an excuse for having no plan. Facebook ended up dropping ‘move fast and break things.’ Maybe because they had a terrible codebase or they broke democracy
I feel actually there's a version of move fast and break things that is more like about not hesitating to make ambitious changes and refactoring. The alternative sometimes is people actually prefer to hack, as it might involve needing less major refactoring or changes, and they do that as they worry they might "break" things. When in my opinion the refactor is needed. And this is where an effective team has everything needed for this as well, a good test suite, and continuous integration that they trust. So they don't have to worry about "breaking" things, and still can feel like they can take ambitious refactors when needed.