ChanServ changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Fund Crystal's development: https://crystal-lang.org/sponsors | GH: https://github.com/crystal-lang/crystal | Docs: https://crystal-lang.org/docs | Gitter: https://gitter.im/crystal-lang/crystal
<FromGitter> <jrei:matrix.org> straight-shoota monkey patching HTTP::Server::Context is obviously bad. If I use Kemal, which monkey patch it, your lib, then another one, issues like name clash can raise. And a the end, we don't even know what's stdlib or not
<straight-shoota> not sure I agree on "obviously bad"
<FromGitter> <jrei:matrix.org> particularly in this context
<FromGitter> <jrei:matrix.org> at least, passing a "monkey patchable" context or hash around would be cleaner. Handler could add properties to the hash, which is then fetched by another one
<straight-shoota> but if you use a session library like http-session there's no reason to use another one which would also occupy the session name
<straight-shoota> the difference between monkey patching additional properties and a hash is that the latter is more complexity, less performance and errors at runtime
<straight-shoota> but potential for name collision is the same
<FromGitter> <jrei:matrix.org> or passing a named tuple or an other more efficient object
<straight-shoota> doesn't change anything
<FromGitter> <jrei:matrix.org> so, I don't understand something: what's the point of monkey patching to be reusable on other handlers, if they don't know this added method?
<straight-shoota> Crystal allows re-opening types for a reason. It should not avoided, if possible. But I do believe it's possible to use it for enhancing types from stdlib (or other libraries)
<straight-shoota> as long as it's within reason
<FromGitter> <jrei:matrix.org> I don't see how it is valid here - it can be avoided
<FromGitter> <jrei:matrix.org> The handlers knowing the added method are custom made by the users, not from stdlib/other libs
<straight-shoota> yes, so?
<FromGitter> <oprypin:matrix.org> look let's say you made this library
<FromGitter> <jrei:matrix.org> So, the SessionManager can be passed to the handler initializer
<FromGitter> <oprypin:matrix.org> then another person made a competing library that also monkeypatches
<FromGitter> <oprypin:matrix.org> and then you pull in both of them unknowingly through two different dependencies transitively
<FromGitter> <oprypin:matrix.org> it will break, right?
<straight-shoota> @jrei: If you pass the session manager, but not the session, every handler that accesses the session needs to load it
<straight-shoota> opyrpin: if you do that, probably yes
<FromGitter> <jrei:matrix.org> straight-shoota unless you call method which pass the session ;)
<FromGitter> <jrei:matrix.org> could be problematic in some cases
<straight-shoota> but as long as it's not hard wired to include any of the respective libraries, you can make sure to only include one
<straight-shoota> if they follow the same API, they could even be interchangeable
<FromGitter> <oprypin:matrix.org> straight-shoota, no you don't understand
<straight-shoota> jrei: what method with what session?
<FromGitter> <jrei:matrix.org> anyway, overall, all of this works. Kemal works, your approach too.
<FromGitter> <oprypin:matrix.org> there are 2 different session libraries like yours. then a library depending on yours that does some unique thing. then another library depending on the competitor library.
<straight-shoota> kemal-session does exactly the same thing:
<FromGitter> <oprypin:matrix.org> some person wants to use these 2 unique libraries at the same time but for an arbitrary reason they cannot
<FromGitter> <oprypin:matrix.org> they never depended on either of the monkeypatching libs and they can't prevent it
<FromGitter> <jrei:matrix.org> exactly: I'm on Kemal-session, I want to migrate to your lib - boom
<straight-shoota> and what would be the purpose of using two different session libraries?
<straight-shoota> no boom
<FromGitter> <oprypin:matrix.org> straight-shoota, again you don't understand
<FromGitter> <jrei:matrix.org> try it before migrate it in production
<straight-shoota> remove kemal-session, add http-session, migrate your app and dependencies
<FromGitter> <oprypin:matrix.org> unique library C uses session library A
<FromGitter> <oprypin:matrix.org> unique library D uses session library B
<FromGitter> <oprypin:matrix.org> i want to use library C and library D
<FromGitter> <oprypin:matrix.org> i can't
<FromGitter> <jrei:matrix.org> what @oprypin says is true too
<straight-shoota> when C depends on session management A and D depends on session management B, there's no way they are both going to work together, no matter if A and B could work alongside each other or no
<FromGitter> <oprypin:matrix.org> who says they work together
<FromGitter> <oprypin:matrix.org> they are in completely different code paths
<FromGitter> <oprypin:matrix.org> but it still breaks
<FromGitter> <oprypin:matrix.org> very simple real example
<FromGitter> <jrei:matrix.org> it is easier to keep 2 libs alongside and migrate progressively, particularly for huge monoliths
<FromGitter> <oprypin:matrix.org> library C is a library interfacing with GitHub and library D is interfacing with GitLab
<FromGitter> <oprypin:matrix.org> i use both in 1 app. not at the same time, sure
<straight-shoota> is that the entire example?
<straight-shoota> then I don't understand why these libraries are coupled to a session system at all, and why you wouldn't want to use the same sessions for both?
<FromGitter> <jrei:matrix.org> they need to, they abstract this logic I guess
<straight-shoota> what logic?
<FromGitter> <jrei:matrix.org> the point is still valid: you could have a hug monolith with different parts needing different equivalent libs, which has their pros/cons
<straight-shoota> this would need to be libraries that not only connect to external services, but also handle the HTTP processing directly
<straight-shoota> there's always potential for conflict when several libraries are suppose to work together. That's why http-session is proposal for a standardized interface.
<straight-shoota> I mean an even more realistic scenario than unrelated sessions in different code paths is libraries sharing access to the same sessions
<straight-shoota> because different features of a website require storing data in the user session
<straight-shoota> that's a huge potential for conflict
<straight-shoota> hence, the recommendation to prefix session properties with the shard name
<straight-shoota> For example: there's another shard I'm working on which provides authentication via OpenID Connect. Its session properties are prefixed with `openid_connect_`.
<straight-shoota> but it also doesn't automatically require http-session once you use openid-connect
<straight-shoota> so you can easily integrate it with a different session mechanism
<FromGitter> <jrei:matrix.org> the library can't be standard, Lucky does it way, Amber too. For Athena, I don't think it will be an idiomatic way
<straight-shoota> I'd definitely like to see alternative approaches to the session management
<FromGitter> <jrei:matrix.org> one issue is it depends of the framework
<FromGitter> <jrei:matrix.org> yours is the best for Kemal
<straight-shoota> yeah, but I just find all existing solutions, be it lucky, amber, kemal-session lacking type safety
<FromGitter> <jrei:matrix.org> I think for Athena, with its typing philosophy, will make a session only available for certain paths
<straight-shoota> I mean this is crystal, not ruby or PHP, yet they store session values by string names
<straight-shoota> which doesn't make any sense to me
<FromGitter> <jrei:matrix.org> but with your approach all paths using a `HTTP::Server::Context` can call `session` methods
<straight-shoota> that's the beauty of it. It just works. Simple.
<FromGitter> <jrei:matrix.org> but not very type safe then 😕
<straight-shoota> why not?
<FromGitter> <jrei:matrix.org> ideally, a session should only be available on paths which require them, not all - of course
<straight-shoota> why?
<straight-shoota> some handlers may not need request or response, yet it's still available to all
<FromGitter> <jrei:matrix.org> they don't need it - calling it by mistake is an error
<straight-shoota> sry, I don't follow. What is the mistake?
<FromGitter> <jrei:matrix.org> yeah, again, that's not how Athena, Lucky or Amber work
<FromGitter> <jrei:matrix.org> I guess it is hard to make a compile time error instead of a runtime one
<straight-shoota> you mean when a handler accesses the session but the session handler didn't initialize it=
<straight-shoota> ?
<FromGitter> <jrei:matrix.org> with handlers, à la Kemal/stdlib, it is not doable
<FromGitter> <jrei:matrix.org> but with the Controller approach I think it could
<straight-shoota> yeah, well that's an entirely different architecture
<straight-shoota> so something like this could be an alternative approach for handlers: https://carc.in/#/r/ah5e
<FromGitter> <jrei:matrix.org> yes that's what I was proposing afterwards
<FromGitter> <jrei:matrix.org> one issue is if we have, CustomHandler -> stdlibHandler -> CustomHandler - it won't work
<straight-shoota> why not?
<straight-shoota> the external interface for the handler chain is just call(context)
<FromGitter> <jrei:matrix.org> because the `call(context : HTTP::Server::Context, session : T)` is not present in other handlers
<straight-shoota> call_next(context) would obviously call the interface method, not the internal overload with session parameter
<FromGitter> <jrei:matrix.org> ha, you want to keep both the monkey patch and have this method call?
<FromGitter> <jrei:matrix.org> right, indeed...
<straight-shoota> I don't think you would combine both approaches
<FromGitter> <jrei:matrix.org> the handlers approach is such a pain for auth :/
<straight-shoota> is it?
<FromGitter> <jrei:matrix.org> yeah, I've an app using Kemal, we needed custom macros/methods to put routes behind auth
<FromGitter> <jrei:matrix.org> *I had
<straight-shoota> ah yeah for custom logic you need a macro in order to exit the handler with next
* FromGitter * Blacksmoke16 is glad he went with event/listener approach
<FromGitter> <jrei:matrix.org> not sure it has to do with the paradigm
oprypin has quit [Quit: Bye]
oprypin has joined #crystal-lang
<FromGitter> <jrei:matrix.org> more to do of the way to declare routes and grouping them. ⏎ Handler has none of this concept, Kemal only the first
<straight-shoota> If only the event/listener approach would be easily approachable :P
<straight-shoota> No seriously, I like it. But it's more complexity to set up
<FromGitter> <jrei:matrix.org> agree too, IMHO not *needed*
<FromGitter> <Blacksmoke16> > more to do of the way to declare routes and grouping them. ⏎ > Handler has none of this concept, Kemal only the first ⏎ ⏎ yes, but if you had a way to attach metadata to a route *AND* know what route a current request would invoke, you can more easily handle that side of things [https://gitter.im/crystal-lang/crystal?at=603c4189457d6b4a94950262]
<FromGitter> <jrei:matrix.org> why not use regular callbacks?
<FromGitter> <Blacksmoke16> > *<straight-shoota>* No seriously, I like it. But it's more complexity to set up ⏎ ⏎ for sure, benefit is it's not required, and fairly easy concept when you get the how things work. is a graphic/dedicated walkthru how it works
<FromGitter> <Blacksmoke16> i.e. only need to know it if you need it
<FromGitter> <Blacksmoke16> how would that work?
<FromGitter> <Blacksmoke16> but yea, im not proposing the stdlib adopt it
<FromGitter> <jrei:matrix.org> instead of emitting an event, call the methods which will receive it in place
<FromGitter> <jrei:matrix.org> works fine for simple cases. I believe more complex ones would benefit more with a service like RabbitMQ
<FromGitter> <Blacksmoke16> got an example?
<FromGitter> <Blacksmoke16> because an event to tap into the request/response life-cycle is not really the same idea as using rabbit
<FromGitter> <jrei:matrix.org> hum, yeah nvm
<FromGitter> <jrei:matrix.org> not familiar with Athena
<FromGitter> <Blacksmoke16> esp since the events are emitted by the framework itself
<FromGitter> <Blacksmoke16> you *can* have custom events however
<FromGitter> <Blacksmoke16> https://athenaframework.org/components is a good high level overview
<FromGitter> <Blacksmoke16> the flowchart helps a lot imo
<FromGitter> <jrei:matrix.org> I think I got it
<FromGitter> <jrei:matrix.org> for example, instead of describing which events are subscribed
<FromGitter> <jrei:matrix.org> have this the other way around, declare which event goes where
<FromGitter> <jrei:matrix.org> essentially a list of methods, so callbacks
<FromGitter> <jrei:matrix.org> I don't say it is better or worse though
<FromGitter> <Blacksmoke16> to be fair im pretty sure thats how it works under the hood
<FromGitter> <Blacksmoke16> each listener is stored as a proc (callback), and invoked?
<FromGitter> <jrei:matrix.org> ok! So that's just a shortcut
<FromGitter> <jrei:matrix.org> yeah
<FromGitter> <Blacksmoke16> the dedicated type is needed to support dependencies
<FromGitter> <Blacksmoke16> i.e. each request gets its own listener instance, which comes with its own set of dependencies etc
<FromGitter> <jrei:matrix.org> I see, interesting
<FromGitter> <jrei:matrix.org> one way to solve the global handlers limitations, it so have a list of handlers per controller/route
<FromGitter> <jrei:matrix.org> at the end, Athena approach or others, that's the missing granularity which hurts
postmodern has joined #crystal-lang
<FromGitter> <jrei:matrix.org> ...in Kemal
<FromGitter> <jrei:matrix.org> or, HTTP::Server
<FromGitter> <Blacksmoke16> granularity of what?
<FromGitter> <Blacksmoke16> like knowing what listeners should be scoped to a particular controller/route?
<FromGitter> <jrei:matrix.org> being able to execute a common set of actions for a set of routes
<FromGitter> <jrei:matrix.org> yes exactly
<FromGitter> <Blacksmoke16> yea by default in Athena, and esp for `HTTP::Handler`, the listener would be invoked for every route. But there are ways around that. E.g. https://athenaframework.org/cookbook/listeners/#pagination this noops if the route doesn't have the related annotation
<FromGitter> <Blacksmoke16> could also do a similar thing with modules. I.e. return unless the controller class includes some "interface" module or what haveyou
<FromGitter> <Blacksmoke16> could use that in the stdlib case as well
<FromGitter> <Blacksmoke16> well maybe as part of lucky/amber given stdlib/kemal doesnt have controller concept so there wouldnt be a thing to add it to
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
<watzon> Any ideas on the most efficient way to make a Slice as small as possible by eliminating trailing null bytes?
<watzon> I guess I basically need `String#strip`, but for enumerables
<FromGitter> <naqvis> ```code paste, see link``` ⏎ ⏎ I've no clue on how performant it would be compare to other methods [https://gitter.im/crystal-lang/crystal?at=603c7a0495e23446e4045070]
<FromGitter> <naqvis> so you better do a quick benchmark to check that
<FromGitter> <void-witch> how do i run specs with shards? `crystal spec` gives me errors about missing libraries
<FromGitter> <naqvis> did you run `shards install`?
<watzon> Thanks @naqvis :)
<watzon> Turns out the bytes are actually in big endian format though, so I was able to just use index to find the first non null byte and then get a new slice from that position.
<FromGitter> <naqvis> :P
<FromGitter> <naqvis> yeah, that would definitely work
<FromGitter> <naqvis> another thought i had was doing something like binary search to find the first index of null byte and then do the truncation from that
<FromGitter> <naqvis> as binary search like algorithm will prevent sequential traversal
<FromGitter> <naqvis> for smaller slice, sequential traversal is ok, but for bigger ones, that will have the benefit
<watzon> Yeah, in this case we're dealing with 8 bytes though so it's not a big deal
<watzon> Also figured out that my generated abstract classes aren't useless either
<watzon> I need a way to determine the returned type of an RPC method, and that's where this comes in. Granted I'm now up to 42000 lines of generated code.
_ht has joined #crystal-lang
hendursa1 has joined #crystal-lang
hendursaga has quit [Ping timeout: 268 seconds]
hendursa1 has quit [Ping timeout: 268 seconds]
DTZUZU has quit [Read error: Connection reset by peer]
hendursaga has joined #crystal-lang
DTZUZU has joined #crystal-lang
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
<frojnd> Hi there. What would be equivalent to the bash's `grep -B 1 "$date" file.ics` in crystal? Basically I would like to grep a line but above the one that matches "$date"
<straight-shoota> maybe sth like `last_line = nil; File.each_line("file.ics") do |line| if line ~= date then puts last_line; last_line = line end`
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
postmodern has quit [Quit: Leaving]
Xeago has quit [Ping timeout: 256 seconds]
Xeago has joined #crystal-lang
<frojnd> straight-shoota: what is `~=` in crystal lang I get: `unexpected token: =`
<FromGitter> <Blacksmoke16> it's `=~`
<frojnd> Ok
<straight-shoota> sry, typo
<frojnd> Np
<frojnd> What's called this `=~` it seems it doesn't match date where date is date="2021.5.5" in a string like this`some string blabla date=2021.5.5`
<FromGitter> <jrei:matrix.org> that's a regex
<FromGitter> <jrei:matrix.org> you need to add wildcards
<straight-shoota> >> "some string blabla date=2021.5.5" =~ "2021.5.5"
<DeBot> straight-shoota: # => nil - https://carc.in/#/r/ah5v
<frojnd> Sryy... I wanna match lines where line includes `date=2021.5.5`
<straight-shoota> >> "some string blabla date=2021.5.5" =~ /2021.5.5/
<DeBot> straight-shoota: # => 24 - https://carc.in/#/r/ah5w
<straight-shoota> >> "some string blabla date=2021.5.5".includes?("date=2021.5.5")
<DeBot> straight-shoota: # => true - https://carc.in/#/r/ah5x
<frojnd> Ah includes! Thank you straight-shoota
andremedeiros has quit [Quit: ZNC 1.8.2 - https://znc.in]
andremedeiros has joined #crystal-lang
DTZUZU has quit [Read error: Connection reset by peer]
fifr` has quit [Ping timeout: 272 seconds]
fifr` has joined #crystal-lang
yxhuvud has quit [Read error: Connection reset by peer]
yxhuvud has joined #crystal-lang
<FromGitter> <watzon> BigInt is killing me
<FromGitter> <watzon> I need `String#to_u128`
<frojnd> Hm I have this regular expression: `.*\\n\K.*(?=\\n)` I tried in regex 101 and it works as it should. But when I try this with .match I get nil: `/.*\\n\K.*(?=\\n)/.match("DESCRIPTION:4 blaallala\nblalal alalala\nbla bla\nfoo bar\n»Hlorem ipsum« (baz baz)") I expect `foo bar`
<straight-shoota> drop the double escapes
<straight-shoota> \n instead of \\n
<frojnd> I would like to match "foo bar" which is in the last \n
<frojnd> Between last two \n
<straight-shoota> you need to set the multiline flag for that
<straight-shoota> `/.*\n\K.*(?=\n)/m`
<frojnd> I see
<frojnd> Thank you
<FromGitter> <watzon> @oprypin great job on the mkdocs changes. The tourmaline docs are looking better than ever.
<frojnd> Just wondering... I get `reg = Regex::MatchData("foo bar")` how do I get "foo bar" as a string. I did it as reg.to_a.first but is there any other better way?
<FromGitter> <Blacksmoke16> `reg[0]`
<FromGitter> <Blacksmoke16> or depending on the context you might be able to just do like `$1`
<frojnd> Great
<FromGitter> <oprypin:matrix.org> :>
<frojnd> What should I do? https://carc.in/#/r/ah7k
<frojnd> If I set `last_line = ""` I get: `Unhandled exception: Nil assertion failed (NilAssertionError)`
<FromGitter> <Daniel-Worrall> because there isn't a match
entel has quit [Quit: Connection closed for inactivity]
_ht has quit [Remote host closed the connection]
<FromGitter> <watzon> @frojnd `match` returns either `Regex::MatchData` or nil, so you need to make sure the match was successful first
<FromGitter> <watzon> Easiest way to do that is with a guard clause
<FromGitter> <watzon> ```if match = str.match(/your regex/) ⏎ # match won't be nil here ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=603d662ae8267a46f2e68f27]
duane has quit [Ping timeout: 276 seconds]
<FromGitter> <kingsleyh> evening - are there any tools for Crystal that can indicate unused code in my project so I can delete it?
<straight-shoota> kcov works to some extend
<FromGitter> <kingsleyh> thanks :)
<Andriamanitra> is there anything like https://github.com/Shopify/cli-ui for crystal?
<FromGitter> <jrei:matrix.org> that's more a terminal UI than a CLI builder
<Andriamanitra> yeah i looked at those but they seem to be more for parsing arguments rather than building interfaces
<FromGitter> <jrei:matrix.org> I don't think a crystal equivalent, combining both, exist
<FromGitter> <Blacksmoke16> oh my bad, I just saw `cli` 😬
<FromGitter> <jrei:matrix.org> a bit like https://github.com/crystallabs/crysterm?
<FromGitter> <jrei:matrix.org> your best luck it to combine a CLI builder with a terminal UI lib
<Andriamanitra> exactly like that! thanks
<FromGitter> <Blacksmoke16> @watzon had something related to terminal ui too but I can't remember the name again
<Andriamanitra> shards.yml for crysterm seems a bit broken
<FromGitter> <Blacksmoke16> --ignore-crystal-version
<FromGitter> <Blacksmoke16> Or something like that...