Once again I glimpsed at my twtxt feed access log. Now Iām wondering: is there a twtxt client named xt out there? Does anyone know? I did not find anything for āxt/0.0.1ā.
We had a faint yellow-orange-redish sky this evening. Only subtle, but it was actually one of those rare 360° sunsets. Just when I thought, that was it, itās now over, the colors took off like crazy: https://lyse.isobeef.org/abendhimmel-2025-01-01/
A much nicer start into the year than all the hell yesterday. However, just as I type this, there come also the next round of explosions as darkness falls. Those bloody fuckers, please blow yourselves up!
@bender@twtxt.net @prologic@twtxt.net Reminds me of: https://img.ifunny.co/images/d07b9a2014e3b3901abe5f4ab22cc2b89a0308de8a21d868d2022dac7bb0280d_1.jpg :-D
Moin @arne@uplegger.eu, herzlich willkommen! Ich bin gerade auf https://uplegger.eu/blog/popelfinger gestoĆen und war sofort sehr begeistert. :-D Mal sehen, ob ich die anderen an einem der Feiertage davon überzeugt bekomme, das mal auszuprobieren. :-)
Yeah, @eapl.me@eapl.me, I kinda like file extensions in some situations. What do you think of twtxt.exe, @bender@twtxt.net? ]:->
Time to rotate three months into archive feeds again.
Righto, @eapl.me@eapl.me, ta for the writeup. Here we go. :-)
Metadata on individual twts are too much for me. I do like the simplicity of the current spec. But I understand where youāre coming from.
Numbering twts in a feed is basically the attempt of generating message IDs. Itās an interesting idea, but I reckon it is not even needed. Iād simply use location based addressing (feed URL + ā#ā + timestamp) instead of content addressing. If one really wanted to, one could hash the feed URL and timestamp, but the raw form would actually improve disoverability and would not even require a richer client. But the majority of twtxt users in the last poll wanted to stick with content addressing.
yarnd actually sends If-Modified-Since request headers. Not only can I observe heaps of 304 responses for yarnds in my access log, but in Cache.FetchFeeds(ā¦) we can actually see If-Modified-Since being deployed when the feed has been retrieved with a Last-Modified response header before: https://git.mills.io/yarnsocial/yarn/src/commit/98eee5124ae425deb825fb5f8788a0773ec5bdd0/internal/cache.go#L1278
Turns out etags with If-None-Match are only supported when yarnd serves avatars (https://git.mills.io/yarnsocial/yarn/src/commit/98eee5124ae425deb825fb5f8788a0773ec5bdd0/internal/handlers.go#L158) and media uploads (https://git.mills.io/yarnsocial/yarn/src/commit/98eee5124ae425deb825fb5f8788a0773ec5bdd0/internal/media_handlers.go#L71). However, it ignores possible etags when fetching feeds.
I donāt understand how the discovery URLs should work to replace the User-Agent header in HTTP(S) requests. Do you mind to elaborate?
Different protocols are basically just a client thing.
I reckon itās best to just avoid mixing several languages in one feed in the first place. Personally, I find it okay to occasionally write messages in other languages, but if that happens on a more regularly basis, Iād definitely create a different feed for other languages.
Isnāt the emoji thing ājustā a client feature? So, feed do not even have to state any emojis. As a user Iād configure my client to use a certain symbol for feed ABC. Currently, I can do a similar thing in tt where I assign colors to feeds. On the other hand, what if a user wants to control what symbol should be displayed, similar to the feedās nick? Hmm. But still, my terminal font doesnāt even render most of emojis. So, Unicode boxes everywhere. This makes me think it should actually be a only client feature.
Hey @eapl.me@eapl.me, your feed is broken. All U+2028 got transformed into newlines.
Went on a really cool walk today after the sun came out this arvo. Just 11°C and a fair bit of wind required a scarf and beanie. I love the autumn colors a lot and never tire of looking at them.
On the summit the view was absolutely terrible, because there were super low hanging clouds. But it still looked fairly spectacular. Very surreal, I could not make out the edge of the Swabian Alb. The haze just blended with the rest of the sky. Towards the sun it was just one giant white wall after half a kilometer or so. That doesnāt happen all that often here.
After dusk I saw five deer on a meadow. Well their outlines against the remaining backlit sky.
Oh boy, Iām looking for trapezoidal (like ACME thread) screws and nuts in left hand form. The rods are already expensive, but nuts feel like a total ripoff. A hex nut for Tr20x2 being 30mm long and 30mm in ādiameterā costs me 22 bucks! O_o Just a single one, made of regular steel. A meter of rod is 21ā¬. The more common Tr20x4 hex nut is just 7⬠and the rod 17ā¬, but 4mm pitch is a bit much for a leadscrew for semi-precision work I reckon.
Well, maybe I just use metric threads. I will sleep on this.
I heard a funny saying today: Democracy is when three foxes and a bunny decide what to have for dinner.
Good writeup, @anth@a.9srv.net! I agree to most of your points.
3.2 Timestamps: I feel no need to mandate UTC. Timezones are fine with me. But I could also live with this new restriction. I fail to see, though, how this change would make things any easier compared to the original format.
3.4 Multi-Line Twts: What exactly do you think are bad things with multi-lines?
4.1 Hash Generation: I do like the idea with with a new uuid metadata field! Any thoughts on two feeds selecting the same UUID for whatever reason? Well, the same could happen today with url.
5.1 Reply to last & 5.2 More work to backtrack: I do not understand anything youāre saying. Can you rephrase that?
8.1 Metadata should be collected up front: I generally agree, but if the uuid metadata field were a feed URL and no real UUID, there should be probably an exception to change the feed URL mid-file after relocation.
rsync(1) but, whenever I Tab for completion and get this:
@aelaraji@aelaraji.com @mckinley@twtxt.net rsync -avzr with an optional --progress is what I always use. Ah, I could use the shorter -P, thanks @movq@www.uninformativ.de.
@falsifian@www.falsifian.org Yeah, delete requests feel very odd.
Now WTF!? Suddenly, @falsifian@www.falsifian.orgās feed renders broken in my tt Python implementation. Exactly what I had with my Go rewrite. I havenāt touched the Python stuff in ages, though. Also, tt and tt2 do not share any data at all.
By any chance, did you remove the ; charset=utf-8 from your Content-Type: text/plain header, falsifian?
@movq@www.uninformativ.de Non-ASCII characters were broken. Like U+2028, degrees (°), etc.
Turns out I used a silly library to detect the encoding and transform to UTF-8 if needed. When there is no Content-Type header, like for local files, it looks at the first 1024 bytes. Since it only saw ASCII in that region, the damn thing assumed the data to be in Windows-1252 (which for web pages kinda makes sense):
// TODO: change default depending on user's locale?
return charmap.Windows1252, "windows-1252", false
https://cs.opensource.google/go/x/net/+/master:html/charset/charset.go;l=102
This default is hardcoded and cannot be changed.
Trying to be smart and adding automatic support for other encodings turned out to be a bad move on my end. At least I can reduce my dependency list again. :-)
I now just reject everything that explicitly specifies something different than text/plain and an optional charset other than utf-8 (ignoring casing). Otherwise I assume itās in UTF-8 (just like the twtxt file format specification mandates) and hope for the best.
Hmmmm, I somehow run into an encoding problem where my inserted data end up mangled in the database. But, both SQLite and Go use UTF-8. Whatās happening here? :-?
20° temperature drop in just a hand full of days. Ooof. We went on a stroll at 10°C today. I could have used a beanie, my ears were very cold. The sun was out, but hardly any people. Very nice. Also, no wind.
It was nice to finally hear a few birds singing again, although it was still fairly silent. The sun gave us a nice show. In hindsight, we should have stayed at the summit a bit longer. In the forest, we missed the very best, crazy red sky. We could only see parts shimmering through the tree lines.
@falsifian@www.falsifian.org In my opinion it was a mistake that we defined the first url field in the feed to define the URL for hashing. It should have been the last encountered one. Then, assuming append-style feeds, you could override the old URL with a new one from a certain point on:
# url = https://example.com/alias/txtxt.txt
# url = https://example.com/initial/twtxt.txt
<message 1 uses the initial URL>
<message 2 uses the initial URL, too>
# url = https://example.com/new/twtxt.txt
<message 3 uses the new URL>
# url = https://example.com/brand-new/twtxt.txt
<message 4 uses the brand new URL>
In theory, the same could be done for prepend-style feeds. They do exist, Iāve come around them. The parser would just have to calculate the hashes afterwards and not immediately.
When we passed a few horses in the forest, there was really strong soup odor in the air. It didnāt smell like horse at all, but soup. Maybe theyāve been soup horses, chickens were out of stock.
29°C, zero wind, extremely humid, luckily the sun was behind the clouds. Iām soaking wet, sweat ran down in streams and dripped in my eyes, it burned a bit. The sky is getting a little dark, I hope the thunderstorm and rain are really arriving here later. Rain had always been finally cancelled the couple last days.
Iām gotta go cool off my fingers now, theyāre swollen from the heat.
-R=false on the command line or leave it out entirely. When explicitly stating -R=false, there has to be an equal sign. With a space (-R false) it's somehow parsed as -R which is equivalent to -R=true. O_o Very weird. I'd really like to see an error instead.
Yeah, user error on my end, never mind. The persisted settings.yaml overrides the command line arguments. Thatās surprising to me. I expected the command line options to overrule the config file. Oh well.
@abucci@anthony.buc.ci You can also use -R=false on the command line or leave it out entirely. When explicitly stating -R=false, there has to be an equal sign. With a space (-R false) itās somehow parsed as -R which is equivalent to -R=true. O_o Very weird. Iād really like to see an error instead.
I still have to figure out the precedence of the settings.yaml or command line arguments. Iām probably holding it wrong, but it seems to give me different resultsā¦
vim cursor at the end of the first line on replies, and forks. I have tried adding to this to jenny's configuration:
@quark@ferengi.one @movq@www.uninformativ.de A general workaround in these cases is to wrap the command in a shell script and reference said script instead.
@mckinley@twtxt.net Wow, I was not aware, that there are different kinds of blackberries. But of course there are. Everything has all sorts of different species, why would it be different with these tasty guys? :-)
I just read up on them and ā surprise, surprise ā it turns out, the Himalayans are not native to most of Europe either. Doh! It gets even more interesting, their origin is unclear. Maybe Armenia and the Caucasus region. Fascinating!
@abucci@anthony.buc.ci Thank you for using Lyseās Unofficial Yarnd Help Desk: https://lyse.isobeef.org/tmp/yarnd-disable-registrations.png
vim cursor at the end of the first line on replies, and forks. I have tried adding to this to jenny's configuration:
Today, I learned about vim "+normal $", how cool! :-) Thanks @quark@ferengi.one!
So, by āevolveā you actually mean āremoveā, @prologic@twtxt.net? :-?
Correct, @bender@twtxt.net. Since the very beginning, my twtxt flow is very flawed. But it turns out to be an advantage for this sort of problem. :-) I still use the official (but patched) twtxt client by buckket to actually fetch and fill the cache. I think one of of the patches played around with the error reporting. This way, any problems with fetching or parsing feeds show up immediately. Once I think, Iāve seen enough errors, I unsubscribe.
tt is just a viewer into the cache. The read statuses are stored in a separate database file.
It also happened a few times, that I thought some feed was permanently dead and removed it from my list. But then, others mentioned it, so I resubscribed.
@falsifian@www.falsifian.org @bender@twtxt.net Iād certainly hate my client for automatic feed unsubscription, too.
@prologic@twtxt.net Yeah, Iāve noticed that as well when I hacked around. Thatās a very good addition, ta! :-)
Getting to this view felt suprisingly difficult, though. I always expected my feeds I follow in the āFeedsā tab. You wonāt believe how many times I clicked on āFeedsā yesterday evening. :-D Adding at least a link to my following list on the āFeedsā page would help my learning resistence. But thatās something different.
Also, turns out that āMy Feedsā is the list of feeds that I author myself, not the ones I have subscribed to. The naming is alright, I can see that it makes sense. It just was an initial surprise that came up.
159-196-9-199.9fc409.mel.nbn.aussiebb.net
Iām wrong! Both 404 and 410, among others, are considered dead feeds: https://git.mills.io/yarnsocial/yarn/src/branch/main/internal/cache.go#L1343 Whatever that actually means.
159-196-9-199.9fc409.mel.nbn.aussiebb.net
@bender@twtxt.net 404 could be indeed a temporary error if the file resides on a mounted remote filesystem and then the mount point fails for some reason. With a symlink from the web root to the file on the mount, the web server probably will not recognize the mount point failure as such. Thus, it might not reply with a 503 Service Unavailable (or something like that), but 404 Not Found instead. (I could be wrong on that, though.)
The right⢠way is to signal 410 Gone if the feed does not exist anymore and will not come back to life again. But thatās hard to come by in the wild. Somebody has to manually configure that in almost all situations.
But yes, as @falsifian@www.falsifian.org points out, exponential backoff looks like a good strategy. Probably even report a failure to users somehow, so they can check and potentially unsubscribe.
Transformed four kilograms of blackberries into a bit over three kilograms of blackberry jelly. https://lyse.isobeef.org/brombeergelee-2024-08-19/ The leftover jelly did not fit in prepared canning jars, so I dumped it in a regular drinking glass (which was a mustard glass in its former life):
The rest is cooling off on the bench outside.Let me suggest to use a more secure password, @bender@twtxt.net. One, that does not contain āpasswordā. Like hunter2!!
Oh, the lovely smell of rain. Wonderful! 33°C today, yikes! And I can already hear the thunder rolling in.
By the way, @xuu@txt.sour.is, it looks like youāre running an old, buggy version of yarnd, that duplicates twts in the feed on edit.
The 26°C humidity was through the roof and we just barely escaped the thunderstorm on our stroll. Only the adjacent rain hit us hard. Black clouds caught up on us and we decided to take cover at a barn. Not even a minute later it started to rain cats and dogs for ten minutes straight. Holy crap, that was cool to watch. :-) Also, the smell of rain was just beautiful.
We then decided to continue our return in the light drizzle. But it then got much heavier again and we got completely soaked. With the wet t-shirt and the wind it actually felt rather cold. I anticipated to get rained on, so I left my camera at home. Plenty of paths turned into brook landscapes, several centimeter deep creeks ran down the hilly trails. Quite fascinating. :-)
The sunset a few minutes ago wasnāt too bad:
Iāve been out a few hours again. I came across a dozen or so forest mice. I heard tons of squeaking and saw a lighting fast moving seething mass under leaves and groves. It was impossible to capture anything but I could watch it for two, three minutes. They even seemed to come as close as 20Ā centimeters judging by the rustle and moving plant leaves. Pretty cool.
But heaps of people had to fire up their noise machines today. That clouded my overall joy in nature. Once a commercial airliner was about to fade away in the distance, the next one already adumbrated itself. Lots of prop planes and even a helicopter. Obnoxious loud super cars and motorcycles with broken off mufflers or I donāt know what. My felt hat amplifies the sound I noted.
Luckily, the sun hid behind the clouds most of the time, so I survived the 25°C. Even hotter tomorrow, yikes!
Yeah, the lack of comments makes regular JSON not a good configuration format in my view. Also, putting all keys in quotes and the use of commas is annoying. The big upside is thatās in lots of standard libraries.
I think the appeal with YAML is that is has comments, is kind of easy to write and read and also provides unlimited nesting levels. But it has all its drawbacks, no question. Forbidding tabs, thousands of different string flavors, having so many boolean options (poor Norwegians) etc. I use it, but I donāt particularly enjoy it.
Among simple key value pairs, I like INI files, but with # for comments, not ;. I never used TOML, read up on it yesteray before writing this question, but it looks a bit weird and has some strange rules. I guess I have to give it a try one day.
And yes, as mentioned by several of you, it always depends on the complexity of the configuration at hand.
Iām developing something for the scouts at the moment with rather simple requirements on the config. Currently, there are just four settings. Even INI would be overkill with its section. I selected JSON for now, because thatās readily available with Goās std lib. But I do not like it.
Btw. whatās your own config format, @xuu@txt.sour.is?
Question of the day: What configuration file formats do you all like and use?
@xuu@txt.sour.is These are indeed iterators. Very weird syntax, though.
@xuu@txt.sour.is Despite that these AoC math text problems are rather silly in my opinion (reminds me of an exercise in our math book where somebody wanted to carry a railroad rail around an L-shaped corner in the house and the question was how long that rail could be so that it still fits ā sure, weāve all carried several meter long railroad rails in our houses by ourselves numerous timesā¦), these algorithms are really neat!
Holy moly, this is a fantastic 37C3 talk about security researchers getting attacked and they reverse-engineer and fully disclose the entire ā very advanced ā attack. Operation Triangulation: What You Get When Attack iPhones of Researchers Very impressive!
Question to all you Gophers out there: How do you deal with custom errors that include more information and different kinds of matching them?
I started with a simple var ErrPermissionNotAllowed = errors.New("permission not allowed"). In my function I then wrap that using fmt.Errorf("%w: %v", ErrPermissionNotAllowed, failedPermissions). I can match this error using errors.Is(err, ErrPermissionNotAllowed). So far so good.
Now for display purposes Iād also like to access the individual permissions that could not be assigned. Parsing the error message is obviously not an option. So I thought, I create a custom error type, e.g. type PermissionNotAllowedError []Permission and give it some func (e PermissionNotAllowedError) Error() string { return fmt.Sprintf("permission not allowed: %v", e) }. My function would then return this error instead: PermissionNotAllowedError{failedPermissions}
At some layers I donāt care about the exact permissions that failed, but at others I do, at least when accessing them. A custom func (e PermissionNotAllowedError) Is(target err) bool could match both the general ErrPermissionNotAllowed as well as the PermissionNotAllowedError. Same with As(ā¦). For testing purposes the PermissionNotAllowedError would then also try to match the included permissions, so assertions in tests would work nicely. But having two different errors for different matching seems not very elegant at all.
Did you ever encounter this scenario before? How did you address this? Is my thinking flawed?
I played around with parsers. This time I experimented with parser combinators for twt message text tokenization. Basically, extract mentions, subjects, URLs, media and regular text. Itās kinda nice, although my solution is not completely elegant, I have to say. Especially my communication protocol between different steps for intermediate results is really ugly. Not sure about performance, I reckon a hand-written state machine parser would be quite a bit faster. I need to write a second parser and then benchmark them.
lexer.go and newparser.go resemble the parser combinators: https://git.isobeef.org/lyse/tt2/-/commit/4d481acad0213771fe5804917576388f51c340c0 Itās far from finished yet.
The first attempt in parser.go doesnāt work as my backtracking is not accounted for, I noticed only later, that I have to do that. With twt message texts there is no real error in parsing. Just regular text as a āfallbackā. So it works a bit differently than parsing a real language. No error reporting required, except maybe for debugging. My goal was to port my Python code as closely as possible. But then the runes in the string gave me a bit of a headache, so I thought I just build myself a nice reader abstraction. When I noticed the missing backtracking, I then decided to give parser combinators a try instead of improving on my look ahead reader. It only later occurred to me, that I could have just used a rune slice instead of a string. With that, porting the Python code should have been straightforward.
Yeah, all this doesnāt probably make sense, unless you look at the code. And even then, you have to learn the ropes a bit. Sorry for the noise. :-)
Any good ideas on how to maintain ~/go/pkg/mod and to remove old garbage?
I started reading the proposal to introduce operator overloading in Go version 2 that I like to see: https://github.com/golang/go/issues/27605 Now a few hours later I ended up at this gem. Write a program that makes 2+2=5: https://codegolf.stackexchange.com/questions/28786/write-a-program-that-makes-2-2-5 There are some awesone solutions. :-)
$name$ and then dispatch the hashing or checking to its specific format.
@xuu@txt.sour.is Really sweet! Why did you pick MD5 as the example?
@prologic@twtxt.net Alright, thereās some erroneous markdown parsing going on, I reckon. In my original twt I have a code block surrounded by three backticks. The code block itself contains a single backtick. However, at least for rendering, yarnd shows three backticks instead (not sure if my markdown is invalid, though):
<author> from <entry>s to <feed>, Newsboat marked all old affected articles as unread. IDs were untouched, of course. Need to investigate that. Had something similar happen with another feed change I did some time ago. Can't remember what that was, though.
Great, last system update broke something, building from current master I get:
/usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6: unknown type [0x13] section `.relr.dyn'
What the heck!?
And it also appears that Iām not really able to reproduce this unread bug. It only kind of works a single time. And it has something to do with my config. Not sure what it is yet. I also noticed that the <updated> timestamps in the entries somehow shifted between the old and new feed. Da fuq!?
Hmmm, after fixing my feeds to move the <author> from <entry>s to <feed>, Newsboat marked all old affected articles as unread. IDs were untouched, of course. Need to investigate that. Had something similar happen with another feed change I did some time ago. Canāt remember what that was, though.
@mckinley@twtxt.net Thank you! I didnāt even know about signing and encrypting XML documents. Right, RSS is a little bit messy.
Unfortunately, the autodiscovery document in one of your linked resources does not exist anymore. What annoys me in Atom is the distinction between <id> and <link>. I always want my URL also to be my ID, so I have to duplicate that ā unnecessarily in my opinion.
Also, never found a good explanation why I should add <link rel="self" ⦠/> to my feeds. I just do, but I donāt understand why. The W3C Feed Validation Service says:
[ā¦] This value is important in a number of subscription scenarios where often times the feed aggregator only has access to the content of the feed and not the location from which the feed was fetched.
This just sounds like a very questionable bandaid to bad software architecture. Why would the feed parser need access to the feed URL at this stage? And if so, why not just pass down the input source? Just doesnāt make sense to me.
Also, I just noticed that I reference the http://purl.org/rss/1.0/modules/syndication/ namespace, but donāt use it in most of my feeds. Gotta fix that. Must have copied that from my yfav feed without paying attention what Iām doing.
Your article made me reread the Atom spec and I found out, that I can omit the <author> in the <entry> when I specify a global <author> at <feed> level. Awesome! Will do that as well and thus reduce the feed size.
We had a nice sunset a few minutes ago:
Welcome back, @quark@ferengi.one! Your web server doesnāt send back a Last-Modified header for your feed, so the official twtxt client complains not to cache it. I just fixed that, so that tt shows your feed (of course no progress has been made in the meantime). And the Date header of your server seems to be quite funny, too. ;-)
@mckinley@twtxt.net Haha, while composing I was wondering two or three times whether I should throw my thoughts in an HTML page instead. But out of utter laziness I discarded that idea. ĀÆ_(ć)_/ĀÆ
@prologic@twtxt.net Error handling especially in Go is very tricky I think. Even though the idea is simple, itās fairly hard to actually implement and use in a meaningful way in my opinion. All this error wrapping or the lack of it and checking whether some specific error occurred is a mess. 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.
Iām trying to switch from Konversation to irssi. Letās see how that goes. Any irssiers out there who can recommend specific settings or scripts? I already got myself trackbar.pl and nickcolor.pl as super-essentials. Also trying window_switcher.pl. Somehow my custom binds for Ctrl+1/2/3/etc. to switch to window 1/2/3/etc. doesnāt do anything: { key = "^1"; id = "change_window"; data = "1"; } (I cannot use the default with Alt as this is handled by my window manager). Currently, Iām just cycling with Ctrl+N/P. Other things to solve in the near future:
- better, more colorful and compact theme (just removed clock from statusbar so far)
- getting bell/urgency hints working on arriving messages
- nicer tabs in status bar, maybe even just channel names and no indexes
- decluster status bar with user and channel modes (I never cared about those in the last decade)
@movq@www.uninformativ.de I usually only use eggs for baking or fry them for potatoes and spinach. @prologic@twtxt.net Why donāt you have them anymore? Did the fox get them all when the door didnāt close in time? ]:->
Alright, check this out. I just kinda completed todayās project of converting a jeans into a saw bag. Itās not fully done, the side seams on the flap need some more hand sewing, thatās for sure. No, I donāt have a sewing machine. Yet?
At first I wanted to put in the saw on the short side, but that would have made for more sewing work and increased material consumption. As a Swabian my genes force me to be very thrifty. Slipping in on the long side had the benefit of using the bottom trouser leg without any modification at all. The leg tapers slightly and gets wider and wider the more up you go. At the bottom itās not as extreme as at the top.
The bag is made of two layers of cloth for extra durability. The double layers help to hide the inner two metal snap fastener counter parts, so the saw blade doesnāt get scratched. Not a big concern, but why not doing it, literally no added efforts were needed. Also I reckon it cuts off the metal on metal clinking sounds.
The only downside I noticed right after I pressed in the receiving ends of the snap fasteners is that the flap overhangs the bag by quite a lot. I fear thatās not really user-friendly. Oh well. Maybe I will fold it shorter and sew it on. Letās see. The main purpose is to keep the folding saw closed, it only locks in two open positions.
Two buttons would have done the trick, with three I went a bit overkill. In fact the one in the middle is nearly sufficient. Not quite, but very close. But overkill is a bit my motto. The sides making up the bag are sewed together with like five stitch rows. As said in the introduction, the flap on the hand needs some more love.
Oh, and if I had made it in a vertical orientation I would have had the bonus of adding a belt loop and carrying it right along me. In the horizontal layout thatās not possible at all. The jeans cloth is too flimsy, the saw will immediately fall out if I open the middle button. Itās not ridgid enough. Anyways, I call it a success in my books so far. Definitely had some fun.
My first attempt of guessing a German word was a close failure: