Bwahahaahaaahaaaaa, this is great! :-D
feh
, but since macros still need an additional keystroke, I quickly fell back to just o
or 1
or whatever the respective link number is. I read somewhere™ that some terminals might be able to render images, but I never tried it. Need to look into that some day.
* Ocdtrekkie's home and car automation
* Prologic wanted to try some Go Doom clone or something like that
* Fixing darch's
Bad Request
in the conversation view by removing superfluous csrf_token
cookies other than for /
, refactoring plans of CSRF handling in yarnd* How people getting scammed in all sorts of different ways
* Pronouncing Twtxt
* Following YouTube channels
* Subscribing to RSS and Atom feeds with Newsboat, Tiny Tiny RSS and yarnd
* And probably a lot more
All these hot temperatures for weeks made the 20°C today feel quite cold. After lunch I had to wear a jumper, cool air coming in was too much for only a t-shirt when sitting still at the desk. But walking this evening was very lovely. Absolutely perfect in a t-shirt. We thought we will encounter some more rain on our way, so we opted for long trousers. Yet, it remained dry, so we both regretted our choice quickly. The humidity of at least 100% was very tough. However, no comparison to temperatures of last week and the one before.

Noone else was outside, we had everything for us. Met exactly six people in total in those two and quarter hours. In general this was a very silent trip. No birds singing, no traffic on the one road for several minutes. Heard just a bunch of sheep and cows in the distance. Quite weird, but enjoyable for sure.
¹ Last time I checked: "We value your privacy, accept all cookies" No you do not, fuck off.
I reckon two
return
s can be saved in GetUser(…)
. Oh, on further inspection there are even two nested err != nil
checks.Generics were desperately needed. I'm glad they finally introduced them. I stumbled across them last week and gave them a shot. The syntax is probably not the very best, but I will get used to it eventually.

Comet is also not too shabby. ;-)
And now I nearly missed adding the screenshot to this twt! Good thing I proofread it three times.

Just before going to bed yesterday I went outside to take a quick last look at Ursa Major. I wasn't even even standing five seconds there and I saw a meteor for barly half a second. Truly amazing!
Just before going to bed yesterday I went outside to take a quick last look at Ursa Major. I wasn't even even standing five seconds there and I saw a meteor for barly half a second. Truly amazing!
KDE 3.5 had the very best KMail versions ever. Very stable, no bugs I encountered (although the bug tracker was full of bug reports, too). With 4 and 5 lots of little issues got introduced that haven't been there before and plenty are still unresolved today. I sent a couple of bug reports for KDE software, but never got any reactions. Once, six or seven years later a dude came back and asked whether a particular bug had been fixed in the meantime. By then I had long migrated off that program.
With KDE 5 I have to fake
XDG_CURRENT_DESKTOP=KDE
or else with an i3
value, icons are not found in KDE programs anymore. Yeah. Also KMail's message text pane does not have any borders around the header part when I start KMail (left). Opening the settings and closing the dialog with OK without changing anything fixes it. It then decorates the headers properly (right). No idea what's going on there.
Also gave Thunderbird a shot a couple of times, but it never worked out for me. One major issue was the broken rendering of quotes when composing I think. And also a bunch of other things I don't remember anymore.
@movq Absolutely, HTML mails are an invention straight from hell! I even only send plain text mails at work as the only guy.
QTWEBENGINE_CHROMIUM_FLAGS="--single-process" kmail
surpringly works… O_o WTF. This goes in the /usr/local/bin/kmail wrapper script then.
org.kde.pim.webengineviewer: WebEngine render process crashed
being printed to stdout.https://bugreports.qt.io/browse/QTBUG-73293 Closed as invalid.
https://bugs.archlinux.org/task/61534 suggests to
QTWEBENGINE_CHROMIUM_FLAGS="--enable-logging --v=3" kmail
, unfortunately, nothing useful shows up:
[32957:1:0813/153712.828577:VERBOSE1:sandbox_linux.cc(69)] Activated seccomp-bpf sandbox for process type: renderer.
[32491:32555:0813/153712.854714:VERBOSE1:gles2_cmd_decoder.cc(3850)] GL_EXT_packed_depth_stencil supported.
org.kde.pim.webengineviewer: WebEngine render process crashed
Why is there not a single decent e-mail program out there? Anybody using only mutt?
Unwrap()
, Is(…)
and As(…)
is sooooooo much work. Unnecessary work, there must be a better way. Sleeping on this twice, the main issue is probably not carefully thinking about the errors in my APIs. Which kind of errors should be distinguishable by the caller. Does it even make sense to differentiate between them? Can the caller react differently depending on what went wrong? This also depends on the caller, of course. In my combinedlog.parseLine(…)
example it's basically stupid. One generic error is enough.Logging only a single line is often very useful. But apart from access logs in web servers I can't remember seen this implemented anywhere in the wild.
The fundamental error was to enable people making tabs arbitrarily wide. :-)
%w
at the front of the message and not at the end and get exactly what I want: fmt.Errorf("%w '%s'", ErrInvalidSentBytes, sentBytes)
results in "invalid sent bytes '4385743057573509732574375098741128354092547569201274123'" and can be error.Is(err, ErrInvalidSentBytes
-asserted. No idea why I did not think of that. O_o Thanks mate! :-)
The technical details to only produce one log per request were sorted out fairly quickly with a customer logger, that just replaces the last message with the newly logged one and finally at response end actually logs it. When a Java component was completely rewritten in Go they tried it out and I was very surprised that it worked that well for the analysis. I basically never missed any other surrounding logs that would have been produced in the old log flooding style. Over time a few things such as structured context fields were added that turned out to be useful to have for error analysis. It's been a couple of years, but I think we rewrote that logger a bunch of times to optimize even further and try out new API ideas we had.
I remember it as a surprisingly successful experiment. In my current project I also once tried to tell my work mates about that, but – just like me when I heard about it in the first month – they weren't ready for it. :-) To be fair, we have a slightly different situation now than in the other project.
errors.As(…)
just doesn't feel natural. errors.Is(…)
only just. I mainly avoided it. Yesterday evening I actually researched a bit about that and found this article on errors with Go 1.13. It shed a little bit of light, but I still have a long way to go, I reckon.We tried several things but haven't found the holy grail. Currently, we have a mix of different styles, but nothing feels really right. And having plenty of different approaches also doesn't help, that's right. I agree, error messages often end up getting wrapped way too much with useless information. We haven't found a solution yet. We just noticed that it kind of depends on the exact circumstances, sometimes the caller should add more information, sometimes it's better if the callee already includes what it was supposed to do.
To experiment and get a feel for yesterday's research results I tried myself on the combined log parser and how to signal three different errors. I'm not happy with it. Any feedback is highly appreciated. The idea is to let the caller check (not implemented yet) whether a specific error occurred. That means I have to define some dedicated errors upfront (
ErrInvalidFormat
, ErrInvalidStatusCode
, ErrInvalidSentBytes
) that can be used in the err == ErrInvalidFormat
or probably more correct errors.Is(err, ErrInvalidFormat)
check at the caller.All three errors define separate error categories and are created using
errors.New(…)
. But for the invalid status code and invalid sent bytes cases I want to include more detail, the actual invalid number that is. Since these errors are already predefined, I cannot add this dynamic information to them. So I would need to wrap them à la fmt.Errorf("invalid sent bytes '%s': %w", sentBytes, ErrInvalidSentBytes")
. Yet, the ErrInvalidSentBytes
is wrapped and can be asserted later on using errors.Is(err, ErrInvalidSentBytes)
, but the big problem is that the message is repeated. I don't want that!Having a Python and Java background, exception hierarchies are a well understood concept I'm trying to use here. While typing this long message it occurs to me that this is probably the issue here. Anyways, I thought, I just create a
ParseError
type, that can hold a custom message and some causing error (one of the three ErrInvalid*
above). The custom message is then returned at `Error()` and the wrapped cause will be matched in `Is(…)`. I then just return a ParseError{fmt.Sprintf("invalid sent bytes '%s'", sentBytes), ErrInvalidSentBytes}
, but that looks super weird.I probably need to scrap the "parent error"
ParseError
and make all three "suberrors" three dedicated error types implementing Error() string
methods where I create a useful error messages. Then the caller probably could just errors.Is(err, InvalidSentBytesError{})
. But creating an instance of the InvalidSentBytesError
type only to check for such an error category just does feel wrong to me. However, it might be the way to do this. I don't know. To be tried. Opinions, anyone? Implementing a whole new type is some effort, that I want to avoid.Alternatively just one
ParseError
containing an error kind enumeration for InvalidFormat
and friends could be used. Also seen that pattern before. But that would then require the much more verbose var parseError ParseError; if errors.As(err, &parseError) && parseError.Kind == InvalidSentBytes { … }
or something like that. Far from elegant in my eyes.
Although there are a bunch of Ukrainian license plates around here, I never wondered why I actually could read all of them without issues. Nice trick to just limit the Cyrillic script to the ones that look like Latin letters.
Also the bad switch dropping a byte every now and then and this way producing Chinese characters was really fun. Good to know, it would have never occurred to me. Not in a hundred years.
I'm sure there are many more things I learned and already forgot again. :-)

We saw a super nice, large, orange moon raising over the horizon. But my camera couldn't pick it up.
time.RFC3339
or time.RFC3339Nano
constants and don't worry about it.Maybe the positive effect is that you're forced to always go to the docs to look everything up when writing the special time pattern, because there's no chance of remembering anything at all (maybe except the year 2006). With the letter system you might think you know what you do and then skip that check in the docs and finally fail because it was the other way around again. If the Go maintainers wanted to prevent that, then they actually succeeded.
It really depends on the ecosystem you're in. The lower date and upper time rule e.g. doesn't work for Java:
yyyy-MM-dd'T'HH:mm:ssSSSXXX
(not sure on the exact number of X
s though).
No doubt, writing good error messages is an art in itself and often takes a minute or two (or even more) to come up with something short and still precise. But in the end it will always pay off to provide some quality message. Same with logging in general, of course. But errors returned to somebody else are more important than internal logs.
In a previous commercial software project the customer wanted to have a complete catalog of all info log messages and above. An additional description with more context had to be provided what that log ID and message meant. I think with warning level and above both a solution and verification was required on how to fix it and then validate that it actually worked. Error and fatal included even more stuff I can't remember anymore.
For us developers that was incredibly annoying, but when we then finally also had to operate that software, this was absolutely awesome to have! Man, did I suddenly understand what all this effort was for. It immediately paid off. There was one guy inhouse just analyzing logs from our different systems all day long and trying to categorize and correlate things. Even with the log message catalog he often had some detail questions to use developers. Can't imagine what would have happend without that catalog.
That experience was truely an eye-opener for me. I can also see it with my current work mates. Only if you had been forced to analyze yourself with nothing else but the logs what was going on or went wrong, you will appreciate and also write good messages yourself. If you haven't been in that situation before, there's basically no way you'll be in a position to write decent logs. And even then you realize that important context is missing when you have to analyze something. :-)
I'm on the fence with testing log entries. In a previous project we quite often did. But there were also hard requirements to produce certain logs, so then it made sense. Usually I don't unless there are some weird circumstances. Can't think of any such situation off the top of my head right now, though.
Just a few weeks back I had basically the same idea with inventing a more generic mock implementation for our storage layer at work. Previously, we had tons of new test storage types each implementing another hardcoded behavior based on the exact input. For a start that works well and is incredibly easy, but over time it quickly becomes unmaintainable and also reading the tests is extremely hard. Why is that weird value used as an argument over here? Quite some time later one realizes: Oh, right, it will then trigger that and that.
So my approach basically boils down to the exact same thing Jessica does. To be able to set a mock function in the mocked object that will then do whatever is needed. Setting up more involved tests is now concise and readable. It's still not perfect, but a large improvement even so. My implementation goes a bit further than Jessica's and falls back to the real functionality, if not overridden explicitly. This has the advantage to just throw together a bunch of tests without mocking *everything*, since there are often a lot of steps needed to build the actual scenario.
In Kraftwerk v2 I extended the mock storage to be able to be initialized even more easily with this automatic
init()
. At work where this mock.Storage
type *inherits* (and not just contains a) memory.Storage
forces us to also explicitly create a memory storage for each and every mock.Storage{Storage: memory.NewStorage(…), …}
. One day, if I have some time, I'll refactor the day-job code and apply this simplification, too. Ideally, Go would allow me to write some constructor thingy where I could set up and propagate initial data to the backing memory implementation. Then there's no chance of forgetting a call to the s.init()
in a new function. But that's the best I've come up with so far. I just want to make it as easy as possible to write tests.So that was very cool for me to see her writing it down as well. It seems my idea the other day was not completely silly. :-) Haven't seen it anywhere else up until now.
This test subject fits perfectly. Just before quitting time two work mates and I discussed about tests. And one rule we made up now is to prefer table tests, when possible. This helps writing and maintaining better tests. I remember back in the Java days when there were different parameterized test frameworks, as they called it. They worked similarly, but in contrast to Go's flexibility of the builtin table tests, it doesn't really compare. Arguably, it's still heaps of code in Go, but creating parameterized tests in Java was always much more hassle in my opinion. Oh, I need this special runner now, which is the correct one? What was the annotation called again? Oh hang on, now these other tests won't work anymore with this new test runner, I have to move stuff to new test classes. That's why I only rarely used them. With Go, it's a real first-class citizen and not an afterthought and that positively shows. (Not sure if parameterized tests improved after Java 8.)
One thing that the article doesn't mention, or I already forgot after writing this wall of text. ;-) Thinking about edge cases. That's super important and often they're missed in my experience. Here TDD might be a good approach to the problem. Come up with possible cornor cases up front, write some tests and then implement the logic. At least for bug fixes this is a great way. There are limitations of course, if you don't know in advance how your going to design the API, TDD won't work in practice. We just had exactly this sitation this week at work. Even with only one fairly simple new function in the end. We threw away four (!) designs and did it quite differently for the final result. If we had strictly followed TDD here, we would have rewritten all our tests a couple of times. And that would have been super annoying and thus demotivating (well, we had to completely rework them once). Granted, that doesn't happen thiiiis often, but it still occurs every now and then.
One last final thing: I very much enjoy looking at code coverage reports and see a lot of green there. This motivates me writing more tests and thinking of ways I could test that last little thing here as well. And if that turns out to be impossible with reasonable effort, you know that you probably need to refactor things.
cbl
and friends. When I quickly counted by HTTP status code, I thought it would be nice to interactively drill down further. But I couldn't answer my question of what I actually want to see or look out for, so I stopped.
HELP
, because my quickly thrown together parser didn't expect this sort of crap. Any particular tools you use to analyze your logs with?
I'll go with two predefined exercise types, that's all that *I* need at the moment. Yeah, keeping extensability in mind is very important. Thank you very much for all your valuable input!
Our approaches differ in measurements, I don't care about calories, although, that is most likely by far the best meaningful number. It's just not something I'm interested in and I also don't have any way to measure it. In that regard I'm like a child and want to play with counting exercises. ;-)
<canvas>
or something like that, so JS was required, too. Unfortunately. For the "Enter Exercise" form JS helped to disable the free text input field when another exercise was selected. But it also worked flawlessly with JS disabled. Or was there some CSS trickery going on? Can't remember. Can't remember. Would need to look into the code.The key is to have everything working without JS. JS might only be used to add little UX benefits. But it must remain working without JS, too. That's my fundamental rule for over a decade now.
Yes, UI and REST API are two very different things. I started with the REST API to have something very simple and functional. It's much easier to test and I can simply have a shell script to interact with.
Content-Type
header and sometimes even omit it from the HTML altogether. But when I do, I also use the shorter and more reasonable looking HTML5 style <meta charset="UTF-8">
, just like @eaplmx showed. The advantage with the HTTP response header is that I just tell nginx to do it for me, so I cannot forget it in the HTML by accident. Well, in case I forgot, it's not an issue.But specifying it also in the HTML helps everybody who happens to download the page. Opening it locally then obviously cannot make use of the nonexisting HTTP response header. Not that I think there are a lot of people out there downloading it, but just in case. :-)
Do you happen to have all your browsers set to fall back to UTF-8 if they can't detect the encoding, @abucci?
As predicted, I did not saw the accident where you had to re-setup the camera. I tried to spot it, no chance. Very well done!
I'm also loving your new ideas. Go for it!

Besides this slow worm and a second, much shorter one later on, a larger frog jumped across the path in the dark. Later a mouse or something along those lines rapidly switched sides and ran over the path. Both just half a meter in front of us, quite cool. Also seen two deer.


We're using Badger at work and unfortunately it's the wrong database for us. Badger is well suited for high write workloads but we're mostly only reading. It's constantly reorganizing the database and wasting a lot of resources. Currently, we're trying to understand the details to reconfigure it, but we could not achieve a lot so far. Tomorrow, I have to continue research on that topic. :-( Also with all the other trouble it had caused us so far, I'll not use Badger in my hobby projects. We also noticed ristretto, the cache, somehow accesses /etc/passwd. No reaction from the developers. Development stalled and then lately continued in a new fork by the same guys but it's already discontinued for another fork and a lot of stuff they don't need anymore like vlogs, write transactions, etc. have been removed. A lot of stuff is changing at the moment.
Bolt is a candidate we even did a crude storage implementation with. The idle performance is great, basically zero, but when work has to happen, we obviously don't hit as good numbers as with Badger. Still good enough from what we've seen so far without spending time analyzing it in any detail. We would also have to bolt the data encryption to Bolt ourselves. That's where Badger really shines. But if you en-/decrypt data in the application, you're still be able to get some metadata from Bolt, like how many records are there, how big are they etc. From my understanding Badger encrypts the whole database and derives dedicated encryption keys from the master key which are then even rotated automatically.
So Bolt could be something to try. I'll probably also have a deeper look into Bitcask some day this week. However, with these more "esoteric" databases debugging probably gets harder. For well-hung, more traditional solutions like SQLite etc. there are lots of viewers and tools out there. Not sure if that is the case for the others, too.
Ok, I have to check out IndieAuth. Actually, I have no idea about it.
set_unread
actually marks it read but the name suggests the exact opposite, in particular to mark the buffer unread. So I thought the line is then moved up to some previous location or even removed completely. It's doing exactly what I want, still confused by the name. Thanks again! <3
I also thought a couple of times in my life to operate a small hobby weather station. In elementary school I actually started recording plenty of metrological data. But after a couple of days I lost interest. That happened a couple of times. Nowadays a lot of things could probably be automated with little maintenance. No idea.
Reminds me of a classic joke. Two planets meet: Oh, you look really bad, how're you going? – Well, I have Homo Sapiens. – Oh, I had them, too. They will pass off.
-o
flag and then saw there's the README-tools.md and finally noticed you even linked it.They claim the database is free of charge, but I would have to register an account and accept some terms. I try to avoid creating accounts in the first place if possible. Luckily, I don't need that DB. :-)
However, temperatures are supposed to rise, up to 36°C on Thursday. Örks.
