Home

Awesome

fern

                            
                            
   :##  Federated  
   #. Editor  and  
   # Reader  of  News                                                               
 #####   ###    #:##: #:##: 
   #       :#   ##  # #  :#   /.\
   #    #   #   #     #   #  // \\
   #    #####   #     #   #  \\///
   #    #       #     #   #   \//
   #        #   #     #   # -=//=-
   #     ###:   #     #   #-=//==-
                            
                            

fern: a curses-based mastodon client modeled off usenet news readers & pine, with an emphasis on getting to 'timeline zero'

Fern screenshot

Fern depends upon Mastodon.py, and is tested on python 2.7 (though it ought to work on python 3 as well).

It was forked from my misc repo, so if you want to see the history of older commits, view it here.

Installation

	pip install Mastodon.py
	sudo make install

When you start fern for the first time, it will prompt you for your instance URL, email, and password. (To reset this, delete ~/.fern)

If you would like to import your existing history of posts, mentions, and favorites, type :import_history. This may take a long time.

Philosophy

Fern comes out of some discussions on the fediverse about how user interface design influences behavior & how certain kinds of norms developed around reading whole threads in usenet because of the design of news clients. The UI of fern is an experiment in trying to encourage users to read entire threads, read their entire timeline, and treat the fediverse more like a medium for serious discussion (i.e., to de-twitterize the fediverse's culture with regard to sealioning).

It also tries to fill in a gap between command-line based clients like tootstream (wherein it's very easy to miss part of a thread or reply to the wrong post because the user manages IDs) and heavy, push-centered experiences like the mastodon web interface (wherein automatic loading can interrupt user input, and where the timeline can quickly get large enough to slow down your whole computer). This is a niche is shares with the likes of brutaldon.

To these ends, there are a couple general rules fern follows:

More specifically:

About the local cache

Fern caches all toots immediately after fetching them, and checks this local cache first for display. This aggressive caching is necessary because Mastodon.py lazily fetches items from the ActivityPub server as they're needed for view, which can be quite slow -- too slow for search, and sometimes too slow for rapid reading of the timeline.

This local cache is represented as a hash table keyed by message ID, and while it's a single table in memory, it's stored in 10 chunks (based on the last digit of the ID). This segmentation makes saving quicker in cases where only a few messages have been fetched.

Messages are fetched and added to the local cache if the user requests a fetch (F), expands a thread (t), requests a particular message by ID (:open_tid), or imports history (:import_history). A save occurs after each manual fetch (once per timeline) or after expanding each thread, and it also occurs upon exit.

Viewing images & long messages

Fern has a pager facility (accessed by pressing g). Setting a pager allows one to scroll through long messages, and setting a browser allows viewing messages as HTML. If the environment variable BROWSER is set to w3m -T text/html -o auto_image=TRUE and your copy of w3m was built with image support, then you can view images attached to a toot in your terminal by pressing g. The BROWSER environment variable, if it exists, overrides the value of PAGER.

Setting up auto-CW rules

Fern has a facility for automatically applying CWs to incoming toots based on regular expression matching. If the original post has a CW, then this adds the new categorizations to the end. These CWs are added at display time, so they aren't searchable.

The rules are stored as a TSV, in the file called cwrules.tsv in your fern config directory (usually ~/.fern).

The first column of the TSV is a regular expression, and the second column is the CW tag to be applied. For instance:

twitter|(bir(d|b)|hell)site	Twitter mention
sex|dick|baloney pony	lewd
sad|depressed	MH(-)
^(.+)@(noagenda\.social|sealion\.club)	troll instance

Missing features

Fern does not supply the ability to follow, mute, or block other users. It also doesn't allow you to mute threads, edit profile information, or change the visibility of your toots. It does not perform client-side size limit checks. It does not attempt to render HTML -- it turns both links and images into raw URLs, turns <p> and <br> tags into newlines, and strips all other tags entirely -- so users who want to see properly-rendered HTML must use an HTML pager.

Fern was planned to support nuanced (killfile-like) blocking and filtering, but this has not yet been implemented.

We have no account-switching support. The most convenient way to do this right now is keep a copy of .fern for every account and swap them out, but this means that (for instance) search is limited by account.

Flaws

Sometimes, the mastodon API doesn't give us as many messages as we ask for, or truncates the range. If you don't use fern for a couple days, you're liable to miss notifications. Using the page facility can get around this, & in the future fetch ought to use it.

Fern isn't heavily tested on python3, and switching between python 2 and python 3 with the same configuration and cache can cause problems. Specifically, it can corrupt your cache, because of some changes to how strings work that are too hairy for me to fully understand.

While fern now works on 80x24 terminals, it will probably still break if your terminal is much smaller. (If this happens, you'll get an error like "Something happened: ERR in addstr()".)

What do users say?

Drew DeVault says that I'm a "moron" for supporting python2, and that my code is bad.

Feoh says "VERY cool"

IceWolf says "700 lines of code? For an entire Mastodon client? Nice! (:"

tedu says "Good luck! (Earnestly.)"