A hard simple thing
Bugs that originate in reliable subsystems are hard to spot because we don’t expect them to fail. A filesystem path usually just works. This has bit me a few times before. While renovating my backup script I found that I provide quite a few status and debug messages that basically call .gist
on an IO::Path
instance. Since one might want to use a hypothetical path, Raku can’t complain on non-existing paths until they are used. Further, it can be quite useful to know that a path is a symlink. Bash and friends help here with colour coding. Since I have plenty of say
-calls, it would be nice to change them all in one go. So wrap
ing it is!
my &RED = sub (*@s) { "\e[31m{@s.join('')}\e[0m" }
my &GREEN = sub (*@s) { "\e[32m{@s.join('')}\e[0m" }
my &CYAN = sub (*@s) { "\e[36m{@s.join('')}\e[0m" }
my &io-path-gist = IO::Path.^can('gist')[0];
&io-path-gist = &io-path-gist.wrap(my method gist (Mu: --> Str ) {
nextsame unless self ~~ IO::Path;
my $s = self.Str;
$s = self.e && self.r ?? $s !! RED($s);
$s = self.l ?? CYAN($s) !! $s;
$s = self.x && !self.d ?? GREEN($s) !! $s;
$s = self.d ?? $s ~ ‚/‘ !! $s;
"⟨$s⟩"
}).&{ -> { .restore } };
We get a handle on the proto of .gist
because .wrap
never operates on multi candidates (this might change, see here). I’m using a method with Mu
as the invocant for clarity. A sub with a single positional would do as well. Since the wrapper is called by the proto, we need to redispatch on anything but IO::Path
. The returned WrapHandle
isn’t really useful and neither is the unwrapped handle to .gist
. By storing a closure we can restore the default by calling io-path-gist()
. The rest is some colouring and adding a /
to mark directories. I like to put a path into fancy quotes to make it easy to spot leading and trailing white spaces.
Declaring class-methods and calling them is a hard thing that is easy because the implementer was sufficiently tormented. Getting hold of methods at runtime is a simple thing that is hard. Huffmanizing applies. We call methods much more often then wrapping them. Sometimes it is good to break a design principle.
Hi @gfldex, please can you elaborate a few things (I can’t quite follow) – (i) why the ‘my’ for method in signature? (ii) what is the invocant of this method? (iii) why go “($s)” at the end – are you returning a list? Thanks in anticipation !
i) I’m wrapping a method so I use a method as a wrapper.
ii) The invocant can be any type that inherits .gist from Mu because the wrapper is wrapping the proto. The proto for .gist is defined in Mu.
iii) It’s actually a string with fancy quotes sandwiching the path.