Expectations for tools.build keep growing 😂
Anyone know of a good Clojure(not script) TUI library? Bonus points for GraalVM compatibility
Seems like it. I had some trouble getting it to work. Also I'm not sure why they need to open a port (I guess for remote sessions). I'm going to build a project using membrane for now and see how well it works
I asked in #lambdaisland. It's far from ready, it's more like a hobby status and no release on the horizon
trikl
probably forking lanterna and updating it might be a worthwhile effort
(clojure-lanterna)
Yeah that would be beneficial for sure. But contributing back might be a problem https://github.com/MultiMUD/clojure-lanterna/issues/24
We could have a graalvm compatible fork possibly. Then provide clojure-lanterna with bb, which I think would be a nice balance between low / high level functionality
Possibly fork to the babashka github org?
Yes
forked here: https://github.com/babashka/clojure-lanterna and invited you
Thanks 👍
I'll update my bb branch to use this version, then create a WIP PR
Having trouble compiling a simple example with 3.0.3
. I keep getting undefined reference to Java_java_util_prefs_FileSystemPreferences_chmod
. Which might be related to this issue: https://github.com/mabe02/lanterna/issues/499
And possibly fixed in Graal recently https://github.com/oracle/graal/issues/2063
oh, hm. compiling with java8 graalvm does work :thinking_face:
@kevin.van.rooijen I also had this issue with 20.2.0 JDK 11 with the tetris repo, but it started working when I avoided the Swing stuff
So avoid all awt references
Ah I guess the DefaultTerminal class is automatically including swing stuff
That's a pain
Ah really, then maybe not use that class?
Yeah I'd have to look into it. Basically it does all the heavy lifting in terms of OS / terminal / capabilities
It figures out what you need related to your platform
OK, you can try to compile with 20.3.0-dev and see what happens
Cool thanks, installing now
Sadly that crashes with something new.
Fatal error:com.oracle.svm.core.util.VMError$HostedError: Option name "TruffleMultiThreaded" has multiple definitions: com.oracle.svm.truffle.api.SubstrateTruffleOptions.TruffleMultiThreaded and com.oracle.svm.truffle.api.SubstateTruffleOptions.TruffleMultiThreaded
at com.oracle.svm.core.util.VMError.shouldNotReachHere(VMError.java:68)
at com.oracle.svm.hosted.option.HostedOptionParser.collectOptions(HostedOptionParser.java:89)
at com.oracle.svm.hosted.option.HostedOptionParser.<init>(HostedOptionParser.java:62)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:238)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:509)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:115)
at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:541)
Error: Image build request failed with exit status 1
com.oracle.svm.driver.NativeImage$NativeImageError: Image build request failed with exit status 1
at com.oracle.svm.driver.NativeImage.showError(NativeImage.java:1632)
at com.oracle.svm.driver.NativeImage.build(NativeImage.java:1382)
at com.oracle.svm.driver.NativeImage.performBuild(NativeImage.java:1343)
at com.oracle.svm.driver.NativeImage.main(NativeImage.java:1302)
at com.oracle.svm.driver.NativeImage$JDK9Plus.main(NativeImage.java:1814)
Can't find much about this
Are you using the reflector fix library?
That only works for a specific version
I'm not sure what you're compiling here
are you compiling bb or the fork of the lib?
or some other thing?
Compiling my own project, and yeah that was the problem. Still no results though. I'm just trying to get a minimal build going
I can host the code
OK. I'll be out for an hour and then I can take a look
https://github.com/kwrooijen/test-lanterna If getting defaultterminal to work then maybe it is a good idea to avoid it and all swing stuff (For now)
Sorry, had something else on my mind.
So you are trying to use lanterna 3 directly. Why not try to update the clojure-lanterna lib and e.g. build the tetris one?
It seems clojure-lanterna isn't using that class directly: https://github.com/MultiMUD/clojure-lanterna/blob/master/src/lanterna/terminal.clj#L1-L10 so maybe this is why compiling does work with that code
While trying to port clojure-laterna I noticed a lot of things are either renamed / deprecated. e.g. the Facade no longer exists. It felt a bit like a rabbit hole so I decided to first get a minimal snippet working
:thumbsup:
Is it possible to not use the DefaultTerminal but something like a TextTerminal instead?
Yeah that's probably the best option for now. Building my app right now so I'll get to it eventually, then move it to the babashka repo
https://github.com/mabe02/lanterna/issues/499#issuecomment-663584383
https://github.com/kwrooijen/test-lanterna/commit/bc7085a7db83eea4e7ae760874b01ee5fc69eb8e This compiles now
Haven't tested Windows though
Hacking in the clojure-lanterna fork to get it to compile with bb
I think you have write access yourself, or do you want me to look at it?
It's just a WIP at the moment, but just to let you know. Going to make a PR for bb to include this (turned off by default)
excellent :)
Je kunt alvast wat CircleCI config neerzetten in die babashka lanterna repo. Ik kan dan een token aanmaken en zo wordt het automatisch gedeployed naar clojars.
👍
Zie babashka.nrepl als voorbeeld
.circleci/config.yml etc
https://github.com/babashka/clojure-lanterna/pull/1/files#diff-1d37e48f9ceff6d8030570cd36286a61 Er zijn nog geen tests, waarschijnlijk kunnen er nog wat dingen uit de circleci file. Maar de belangrijkste lijkt me de deploy job?
Zijn er in de originele clojure lanterna ook geen tests?
Nope
aha ok
There's also: https://github.com/MultiMUD/clojure-lanterna
Thanks, I'll take a look at these options
@kevin.van.rooijen Quickly tried to compile tetris: https://github.com/borkdude/console-tetris#graalvm It seems it gets quite far, but there's an error in the final link step.
I'll make a graalvm issue
I think that Lanterna version is pretty outdated. Laterna seems to have updated to 3.1 recently
Maybe interop would be a better option
I'll take a look after work
yeah. would also be interesting to see if this may work for bb
If you could seamlessly build tui apps with bb, that would be amazing
@kevin.van.rooijen Ah, this guy made it work somehow: https://github.com/phronmophobic/terminal-todo-mvc
Totally forgot about that one
He uses the new lanterna and made his own wrapper
Very cool, this project https://github.com/phronmophobic/membrane
@kevin.van.rooijen Would also be interesting to try out trilk: https://github.com/lambdaisland/trikl#graal-compatibility
Will do, though I think Lanterna looks more promising since it's a bit more maintained. I think this is built from scratch and commits look a bit quiet
Also seems to be a work in progress and not on clojars
(seems to be another branch that's being worked on, by bad)
yeah
oh
The code looks quite minimal, and minimal is good imo ;)
Very true
maybe it doesn't support mouse clicks etc
so maybe lantera is a better option in that regard
I'll keep an eye on your experimentation
or: feel free to keep me posted
Will do
Hi Folks.. New to clojure looking for some help
I'm trying to build a discord bot and in the example code of discljord defines a state
variable
(def state (atom nil))
That is then used in the event handler
(defmethod handle-event :message-create
[event-type {{bot :bot} :author :keys [channel-id content]}]
(if (= content "!disconnect")
(c/disconnect-bot! (:connection @state))
(when-not bot
(m/create-message! (:messaging @state) channel-id :content "Hello, World!"))))
I'm looking to create multiple event-handler each of those inside it's own namespace to be able to develop different commands that can be attached to the the bot ..., but not sure about the clojure way to pass that state
variable across the namespaces. Should I just create the event handler and accept the state as argument? like
(defn get-on-brd-handler
[event-type {{bot :bot} :author :keys [channel-id content]} state]
)
This question might be a better fit in #beginners, but you don’t need to pass it across namespaces. You can just reference it directly. For example:
(ns foo.bar)
(def state (atom nil))
And:
(ns bar.baz
(:require [foo.bar :as bar]))
(defn handler
[,,,]
(do-something-with @bar/state))
@kevin.van.rooijen Works: https://github.com/borkdude/console-tetris#graalvm
Nice, good catch on the :text
instead of :swing
How would you integrate something like this in bb? Would you have to write an impl
like with jdbc?
yes, just check the other libraries that are included
Thanks.
Progress!
wut!
I'll continue on this after dinner, maybe open a WIP PR?
Sure. Can you make a feature toggle for it like in: https://github.com/borkdude/babashka/blob/master/doc/build.md#feature-flags and then turn it off by default?
We can turn it on after some experimentation, but I'm always conservative with adding things by default, since CI is memory constraint
Also binary size is something I monitor
Is there any clojure/java equivalent to rails ActiveSupport::Inflector
?
But adding something under a feature flag is always good for a PR
I just want to make some strings singular
clojure.pprint/cl-format can do some of that
cl-format can hold rules for it
but specifically I am looking to name my sql tables plural and just have a result builder that changes :users/id
to :user/id
user=> (clojure.pprint/cl-format nil "~D tr~:@P/~D win~:P" 7 1)
"7 tries/1 win"
yeah but that only works if I have a certain amount of times something appears in mind and also deconstruct the string into the format
like I can manually write {"users" "user"}
and do a mapping - but I'm looking to see if I can "solve" the problem
given your actual use case, I suspect the amount of effort that would go into automating it exceeds the effort of just having a conversion layer that knows about each table
Thats true, but there are "cool" and "fun" bars that only apply when unemployed and working on hobby projects
also YMMV but many people consider that kind of magic conversion part of what's wrong with rails
and one day you'll end up with a table called Librarys
rather than the proper plural because its simpler than building an override mechanism to whatever you're doing
I've got a result body coming out of a clj-http call that I'm needing to parse. I wrote a simple ANTLR grammar for the body that compiles using clj-antlr/parser with no issues. The problem comes when I try to actually apply the generated parser function to an input string. At this point, the parse errors out with the following message: Execution error (NullPointerException) at org.antlr.v4.runtime.atn.ATNSerializer/serialize (ATNSerializer.java:73). null. Any idea on how to even start debugging this? Or does anyone have a recommendation for a different parser library that is perhaps not so opaque?
Does the exception has any stack trace?
Have you looked at Instaparse? https://github.com/Engelberg/instaparse
Instaparse doesn't handle ANTLR grammars.
Stack trace is as follows: [[org.antlr.v4.runtime.atn.ATNSerializer serialize ATNSerializer.java 73] [org.antlr.v4.runtime.atn.ATNSerializer getSerialized ATNSerializer.java 601] [org.antlr.v4.runtime.atn.ATNSerializer getSerializedAsChars ATNSerializer.java 605] [org.antlr.v4.tool.Grammar createParserInterpreter Grammar.java 1337] [clj_antlr.interpreted$singlethreaded_parser invokeStatic interpreted.clj 111] [clj_antlr.interpreted$singlethreaded_parser invoke interpreted.clj 107] [clj_antlr.interpreted.ThreadLocalParser parse interpreted.clj 119] [clj_antlr.core.ParserWrapper parse core.clj 13] [clj_antlr.core$parse_STAR_ invokeStatic core.clj 28] [clj_antlr.core$parse_STAR_ invoke core.clj 19] [clj_antlr.core$parse invokeStatic core.clj 35] [clj_antlr.core$parse invoke core.clj 30] [clj_antlr.core.ParserWrapper invoke core.clj 17] [cql_p arser.core$parse_RAS_results invokeStatic form-init5406870106907233552.clj 822] [cql_parser.core$parse_RAS_results invoke form-init5406870106907233552.clj 820] [cql_parser.core$run_cql_file invokeStatic form-init5406870106907233552.clj 122] [cql_parser.core$run_cql_file invoke form-init5406870106907233552.clj 109] [cql_parser.core$run_cql_tests$fn__231 invoke core.clj 132] [clojure.core$map$fn__5866 invoke core.clj 2755] [clojure.lang.LazySeq sval LazySeq.java 42] [clojure.lang.LazySeq seq LazySeq.java 51] [clojure.lang.RT seq RT.java 535] [clojure.core$seq__5402 invokeStatic core.clj 137] [clojure.core$dorun invokeStatic core.clj 3133] [clojure.core$doall invokeStatic core.clj 3148] [clojure.core$doall invoke core.clj 3148] [cql_parser.core$run_cql_tests invokeStatic core.clj 132] [cql_parser.core$run_cql_tests invoke core.clj 128] [cql_parser.core$_main invokeStatic core.clj 142] [cql_parser.core$_main doInvoke core.clj 136] [clojure.lang.RestFn invoke RestFn.java 397] [c ql_parser.core$eval46620 invokeStatic form-init5406870106907233552.clj 1] [cql_parser.core$eval46620 invoke form-init5406870106907233552.clj 1] [clojure.lang.Compiler eval Compiler.java 7177] [clojure.lang.Compiler eval Compiler.java 7132] [clojure.core$eval invokeStatic core.clj 3214] [clojure.core$eval invoke core.clj 3210] [nrepl.middleware.interruptible_eval$evaluate$fn__944 invoke interruptible_eval.clj 91] [clojure.main$repl$read_eval_print__9086$fn__9089 invoke main.clj 437] [clojure.main$repl$read_eval_print__9086 invoke main.clj 437] [clojure.main$repl$fn__9095 invoke main.clj 458] [clojure.main$repl invokeStatic main.clj 458] [clojure.main$repl doInvoke main.clj 368] [clojure.lang.RestFn invoke RestFn.java 1523] [nrepl.middleware.interruptible_eval$evaluate invokeStatic interruptible_eval.clj 84] [nrepl.middleware.interruptible_eval$evaluate invoke interruptible_eval.clj 56] [nrepl.middleware.interruptible_eval$interruptible_eval$fn__970$fn__974 invoke interruptible_eva l.clj 155] [clojure.lang.AFn run AFn.java 22] [nrepl.middleware.session$session_exec$main_loop__1071$fn__1075 invoke session.clj 190] [nrepl.middleware.session$session_exec$main_loop__1071 invoke session.clj 189] [clojure.lang.AFn run AFn.java 22] [java.lang.Thread run Thread.java 745]]} CqlArithmeticFunctionsTest.cql #error { :cause nil :via [{:type java.lang.NullPointerException :message nil :at [org.antlr.v4.runtime.atn.ATNSerializer serialize ATNSerializer.java 73]}] :trace [[org.antlr.v4.runtime.atn.ATNSerializer serialize ATNSerializer.java 73] [org.antlr.v4.runtime.atn.ATNSerializer getSerialized ATNSerializer.java 601] [org.antlr.v4.runtime.atn.ATNSerializer getSerializedAsChars ATNSerializer.java 605] [org.antlr.v4.tool.Grammar createParserInterpreter Grammar.java 1337] [clj_antlr.interpreted$singlethreaded_parser invokeStatic interpreted.clj 111] [clj_antlr.interpreted$singlethreaded_parser invoke interpreted.clj 107] [clj_antlr.interpreted.ThreadLocalParser parse interpreted.clj 119] [clj_antlr.core.ParserWrapper parse core.clj 13] [clj_antlr.core$parse_STAR_ invokeStatic core.clj 28] [clj_antlr.core$parse_STAR_ invoke core.clj 19] [clj_antlr.core$parse invokeStatic core.clj 35] [clj_antlr.core$parse invoke core.clj 30] [clj_antlr.core.ParserWrapper invoke core.clj 17] [cql_p arser.core$parse_RAS_results invokeStatic form-init5406870106907233552.clj 822] [cql_parser.core$parse_RAS_results invoke form-init5406870106907233552.clj 820] [cql_parser.core$run_cql_file invokeStatic form-init5406870106907233552.clj 122] [cql_parser.core$run_cql_file invoke form-init5406870106907233552.clj 109] [cql_parser.core$run_cql_tests$fn__231 invoke core.clj 132] [clojure.core$map$fn__5866 invoke core.clj 2755] [clojure.lang.LazySeq sval LazySeq.java 42] [clojure.lang.LazySeq seq LazySeq.java 51] [clojure.lang.Cons next Cons.java 39] [clojure.lang.RT next RT.java 713] [clojure.core$next__5386 invokeStatic core.clj 64] [clojure.core$dorun invokeStatic core.clj 3142] [clojure.core$doall invokeStatic core.clj 3148] [clojure.core$doall invoke core.clj 3148] [cql_parser.core$run_cql_tests invokeStatic core.clj 132] [cql_parser.core$run_cql_tests invoke core.clj 128] [cql_parser.core$_main invokeStatic core.clj 142] [cql_parser.core$_main doInvoke core.clj 136] [clojure .lang.RestFn invoke RestFn.java 397] [cql_parser.core$eval46620 invokeStatic form-init5406870106907233552.clj 1] [cql_parser.core$eval46620 invoke form-init5406870106907233552.clj 1] [clojure.lang.Compiler eval Compiler.java 7177] [clojure.lang.Compiler eval Compiler.java 7132] [clojure.core$eval invokeStatic core.clj 3214] [clojure.core$eval invoke core.clj 3210] [nrepl.middleware.interruptible_eval$evaluate$fn__944 invoke interruptible_eval.clj 91] [clojure.main$repl$read_eval_print__9086$fn__9089 invoke main.clj 437] [clojure.main$repl$read_eval_print__9086 invoke main.clj 437] [clojure.main$repl$fn__9095 invoke main.clj 458] [clojure.main$repl invokeStatic main.clj 458] [clojure.main$repl doInvoke main.clj 368] [clojure.lang.RestFn invoke RestFn.java 1523] [nrepl.middleware.interruptible_eval$evaluate invokeStatic interruptible_eval.clj 84] [nrepl.middleware.interruptible_eval$evaluate invoke interruptible_eval.clj 56] [nrepl.middleware.interruptible_eval$interruptible_eval $fn__970$fn__974 invoke interruptible_eval.clj 155] [clojure.lang.AFn run AFn.java 22] [nrepl.middleware.session$session_exec$main_loop__1071$fn__1075 invoke session.clj 190] [nrepl.middleware.session$session_exec$main_loop__1071 invoke session.clj 189] [clojure.lang.AFn run AFn.java 22] [java.lang.Thread run Thread.java 745]]
I've looked at Instaparse. If I can't get clj-antlr working (it has worked for me in previous projects), I'll start looking at alternatives. The language only has about a dozen productions so no matter how I do it, it'll eventually work - it's just that there are some complicated date-time formats to parse that I already have ANTLR code for.
the only duck duck go hit for the exeception messages looks relevant https://stackoverflow.com/questions/60002238/antl4-grammar-compile-nullpointer-exception
Huh. I wonder how can data.add(atn.grammarType.ordinal());
throw an NPE given that none of the values are null.
@hiredman - I checked that out, too. I'm not using skip anywhere in the grammar as far as I know, which I believe is what the error in this case hinges on.
Here's the grammar, if that helps.
grammar RASResults; value : tuple | list | interval | literal ; interval : 'Interval' leftInterval literal ',' literal rightInterval ; leftInterval : '[' | '(' ; rightInterval : ']' | ')' ; list : '[' valueList ']' ; valueList : | value | value ',' valueList ; tuple : 'Tuple' '{' pair '}' | '{' STRING ':' STRING '}' ; pair : identifier '->' value ; literal : '{' '}' #emptyListLiteral | 'null' #nullLiteral | ('true' | 'false') #booleanLiteral | STRING #stringLiteral | NUMBER #numberLiteral | DATETIME #dateTimeLiteral | TIME #timeLiteral ; identifier : IDENTIFIER ; / Lexical rules */ DATETIME : '@' [0-9][0-9][0-9][0-9] // year ( ( '-'[0-9][0-9] // month ( ( '-'[0-9][0-9] // day ('T' TIMEFORMAT?)? ) | 'T' )? ) | 'T' )? ('Z' | ('+' | '-') [0-9][0-9]':'[0-9][0-9])? // timezoneOffset ; TIME : '@' 'T' TIMEFORMAT ; fragment TIMEFORMAT : [0-9][0-9] (':'[0-9][0-9] (':'[0-9][0-9] ('.'[0-9]+)?)?)? ; IDENTIFIER : ([A-Za-z] | '')([A-Za-z0-9] | '')* // Added _ to support CQL (FHIR could constrain it out) ; STRING : '"' (ESC | .)*? '"' ; // Also allows leading zeroes now (just like CQL and XSD) NUMBER : [0-9]+('.' [0-9]+)? ; // Pipe whitespace to the HIDDEN channel to support retrieving source text through the parser. WS : [ \r\n\t]+ -> channel(HIDDEN) ; fragment ESC : '\\' ([`'\\/fnrt] | UNICODE) // allow \`, \', \\, \/, \f, etc. and \uXXX ; fragment UNICODE : 'u' HEX HEX HEX HEX ; fragment HEX : [0-9a-fA-F] ;
but it points to it not being a clojure specific issue, but some issue with antlr, which means you'll have better luck asking people who know antlr, not people who know clojure
@fadrian FWIW your grammar worked just fine for me with value
being the root and with "{\"a\":\"b\"}"
as an input.
I tried "49" as an input to get the error. But if you can parse that string, it may just be something in the NUMBER token that's screwing up. Let me try a few other inputs. Thanks for everyone's suggestions and assistance.
"49"
also worked just fine for me.
Perhaps it's a version issue. I have clj-antlr
0.2.6 and antlr4
4.8-1.
It's also a question what we want to actually supply. the clojure-lanterna lib is a bit outdated and unmaintained(?)
That may be. I'm still using clj-antlr 0.2.5 and I'm not sure which version of ANTLR it's using. I'll make sure everything's updated. But you've given me a couple of leads. Thanks.
There were some things in clojure-lanterna which didn't work with GraalVM. e.g. some functions read the file system I think, and resulted in com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of <http://sun.nio.ch|sun.nio.ch>.FileChannelImpl
Not sure how to fix that in GraalVM
Reagent for Lanterna sounds like a fun project. On the otherhand we also have Membrane which could be an option
Upgrading clj-antlr to 0.2.6 seemed to do the trick. Thanks again, all.
Isn't trikl intented as a reagent for the terminal kind of maybe?
There are pretty extensive libraries around everything natural language, icu4j springs to mind. Looking at the docs, it has pluralization.
But; I guess thats something to consider when you have extensively translatable apps with dozens of languages 😛
But yeah, some people have gone above and beyond in encoding natural language inconsistencies in every imaginable aspect 😛