Fork me on GitHub
#off-topic
<
2024-04-02
>
pesterhazy07:04:06

Hello everyone! I'd like to show a very simple, unobtrusive visual notification on macOS when my tests fail (red) or succeed (green). Any ideas how?

pesterhazy08:04:11

Background: I have a simple script that plays a different sound effect when a process returns zero or nonzero exit status https://github.com/pesterhazy/beep-boop

pesterhazy08:04:02

This gives me immediate feedback about (a) whether my tests run and (b) whether they succeed

pesterhazy08:04:14

However, in cafes or offices people don't always like hearing random sounds from co-workers, so I'd like to show some visual notification. It could be anywhere - systray area, emacs, color popup. All that matters is that it's lightweight and fast

Stephan Renatus08:04:29

wasn’t doing stuff on the touch bar all the rage when it came out? :thinking_face: can’t find anything useful now, though.

Stephan Renatus08:04:35

https://apple.stackexchange.com/a/115373 I guess that’s the simplest thing you can do?

pesterhazy08:04:21

oh please don't mention the touch bar, that triggers painful memories

🙊 1
pesterhazy08:04:31

I'm glad my latest mac doesn't have it anymore

pesterhazy08:04:16

But I like your other suggestion:

osascript -e 'display notification ":red_circle:" with title "‧"'

Niki14:04:08

It was build almost for the same purpose, only instead of tests I was monitoring cljs build status

Stephan Renatus16:04:14

@UFTRLDZEW ha! that’s what I was trying to remember but failed to. thanks!

Ivar Refsdal06:04:20

I wrote something a while back that used the (awt) system tray

Ivar Refsdal07:04:55

It's all java (!) and probably does too much, could be simplified: https://gist.github.com/ivarref/c76a34f734e78496c423c312330d330c

Ivar Refsdal07:04:52

I've only tested in on linux, would be interesting to know if it works on Mac as well (I assume it will)

pesterhazy09:04:14

@UGJE0MM0W awesome, it works fine on macos, though I can't seem to be able to change the tray icon (it's always yellow sleepy guy)

pesterhazy09:04:50

nice how little code is needed even in java

Ivar Refsdal09:04:16

Thanks 🙂 It takes a list of URLs to poll ... and if not enough data is available, it will display the yellow sleepy guy

Ivar Refsdal06:04:39

I wrote a tiny http server for this tray thing: https://github.com/ivarref/tray-server

🧡 1
Ivar Refsdal08:04:32

I added more stuff, namely that the icon gets a soft color if the server has not received any updates (requests) for 5 minutes (i.e. is whatever is pushing to the server running?)

pesterhazy10:04:36

Are you using it for test feedback, too?

Ivar Refsdal10:04:39

right now I'm just using it for gitlab pipeline tailing, not for tests

👍 1
Ivar Refsdal10:04:05

(that includes tests run in the pipeline though)

Ivar Refsdal10:04:52

((not sure it's a good idea with the soft colors -- at the same time I'd like to have a visual notification if no data has arrived, i.e. the producer of notifications is stopped/has crashed...))

henrik09:04:30

Specter is cheat mode

(multi-transform [(srange 4 12) (filterer odd?) (term reverse)]
  [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15])

;; => [1 2 3 4 11 6 9 8 7 10 5 12 13 14 15]

1
J10:04:10

Since rama, I often use specter.

tomd11:04:43

Genuinely interested, as I haven't used specter much, other than playing. Is it commonly something you find yourself needing, and worth introducing a whole new DSL for? I know your example is just illustrative, but I can't recall ever needing to do something so strange to a collection. And if I did, it would be rare enough that I'd spell it out more procedurally so others (and myself) could understand it in the future without having to recall the specter DSL. This is all assuming that specter isn't needed enough to make remembering it worthwhile. fwiw, the procedural equivalent I had in mind would looking something like this, maybe bringing in rrb vectors if at a perf bottleneck:

(let [coll [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
      subrange (subvec coll 4 12)
      odds     (filterv odd? subrange)
      evens    (filterv even? subrange)]
  (reduce into [] [(subvec coll 0 4) (interleave (rseq odds) evens) (subvec coll 12)]))
;; => [1 2 3 4 11 6 9 8 7 10 5 12 13 14 15]
which, admittedly is more verbose, but considering how rarely I need to do something like this, feels worth the verbosity..?

1
Omar12:04:22

TIL rseq exists. Procrastinating catching up on off-topic is pretty useful sometimes.

😄 4
henrik12:04:27

It is illustrative as you say. The main points illustrated are 1) it’s possible to tersely express complex transformations/queries on data, 2) in a way that’s composable, 3) with performance that will be close to optimal, or at least better than iteration 1 and 2 of a handwritten equivalent. (Admittedly 3 requires a REPL to assert) Worth noting is that Specter preserves the data structures that you feed it. If you were to give the Specter version a list, you will get a list back. If you give it a vector, you’ll get a vector back. As to flexibility/composability, we could replace odd? with any predicate, and the numbers with any other data. None of the basic behavior relies on the values being interleaved etc. We can also throw other Specter path operations in there, and they will compose with srange, filterer etc. You can hand write anything that you can do with Specter, but it will most likely be more bespoke, less flexible, and not as fast (to write or run). On the other hand, you’ll need to learn an extended vocabulary of functions, which is a downside for most of us.

tomd14:04:09

That's a good answer, thank you. I think either I'll need to see specter used in a complex codebase (I can never seem to be able to extrapolate these illustrative examples well) or just try it in one. I guess I tend to work in fields where performance isn't so critical, so bringing in a new DSL to pre-optimize code doesn't feel worth bringing in the new cognitive overhead. I can certainly imagine a level of complexity where the hand-rolled solution is just too brittle and slow, but maybe these problems crop up more in some fields than others.

henrik14:04:27

That’s 💯 fair. The example given is just meant to be something that’s flexes its muscles. Most of our use cases are not quite that bad. Here’s a more down-to-earth example that’s roughly equivalent to something we actually have in our codebase. This would be one of the simpler cases where we still use Specter. The main advantages here is that expressing the operations done on test-db is somewhat more elegant, and we don’t have to think about accidentally converting vectors to lists etc.

👀 1
tomd14:04:30

Yeah, very declarative. I guess you'd need to be mixing assoc-in and update-in and then being mindful to iterate in a way that returns a vector, if you went the non-specter route. Good stuff!

👍 1
henrik14:04:20

Another less contrived example. Find a value in a sequence and move it to a particular index. Could be modified to move the value to wherever another given value is (by looking at the val part instead of the idx part).

henrik14:04:04

This is the common case, at least in our codebase btw. Specter rarely “escapes” function boundaries, and whoever uses the function doesn’t really need to care that the implementation uses Specter.

🆒 1