turses¶
A Twitter client for the console.
Features¶
- Multiple timelines (buffers)
- Multi-column
- Tweet, Reply, Retweet, Delete tweet
- Follow/Unfollow
- Favorite/Unfavorite
- Direct Messages
- Open URLs in browser
- Thread view
- Unread count
- Search
- View user’s tweets
- Fully customizable
- Multiple accounts
- View user profile
User Guide¶
This part of the documentation will help you using turses
.
Installation¶
From source¶
turses
is evolving fast, you can find the latest version on GitHub.
You can either clone the public repository:
$ git clone git://github.com/alejandrogomez/turses.git
Download the tarball:
$ curl -OL https://github.com/alejandrogomez/turses/tarball/master
Or, download the zipball:
$ curl -OL https://github.com/alejandrogomez/turses/zipball/master
Once you have a copy of the source, you can embed it in your Python package, or install it into your site-packages easily:
$ python setup.py install
Distribute & pip¶
Installing is simple with pip:
$ pip install turses
or (but you should consider using pip):
$ easy_install turses
Configuration¶
The configuration files are located on $HOME/.turses
directory.
There is one mayor configuration file in turses:
config
- contains user preferences: colors, bindings, etc.
An one default token file:
token
- contains authentication token for the default user account
Each user account that is no the default one needs to be aliased and has its
own token file alias.token
.
To create an aliased account:
$ turses -a work
And, after authorizing turses
to use that account, a token file named
work.token
will be created. Optionally you can create a work.config
file for a configuration specific to that account.
Now, when you execute again:
$ turses -a work
you will be logged in with the previously stored credentials.
Here is an example with two accounts apart from the default one, aliased
to alice
and bob
.
~
|+.turses/
| |-config
| |-alice.config
| |-token
| |-alice.token
| `-bob.token
|+...
|-...
`
If you want to generate a configuration file, you can do so executing:
$ turses -g /path/to/file
The configuration file is divided into sections, each of which is described below these lines.
Warning
The timelines
section of the configuration has been
deprecated, use sessions instead.
Sessions¶
The file with the session declarations is located on
$HOME/.turses/sessions
.
sessions
is a ini-style configuration file in which each section represents
the layout of a session. The defaults
session is loaded when no other
section is present.
Each section has only two options:
visible
- contains the timelines that will be visible stacked in columns
buffers
- contains the timelines that won’t be visible but will be loaded
Warning
The visible
option must be present for any session but
buffers
is optional.
For each option, you will define the timelines as a comma-separated list of their names. Here is a list with the valid names:
home
for the home timelinementions
for the mentions timelinefavorites
for the favorites timelinemessages
for the direct message timelineown_tweets
for the timeline with your tweetssearch:<query>
for searching timelineshashtag:<query>
for searching a hashtaguser:<screen_name>
for a user’s timelineretweets_of_me
for the timeline with your retweeted tweets
Declaring a custom session is as easy as defining a section on the
sessions
file. As an example, let’s define a session called
interactions
, in which we would only like to view our mentions, messages
and what people are saying about turses
; and load the home timeline in
background:
[interactions]
visible = mentions, messages, search:turses, hashtag:turses
buffer = home
If you would like to load a session when starting turses
, you must provide
the name of the session as a command-line argument. You can start the session
named interactions
by executing:
$ turses -s interactions
# or, alternatively
$ turses --session interactions
Twitter¶
This section allows you to configure the settings related to the Twitter API.
turses
communicates with Twitter over HTTPS by default but you can switch
it off if you set it to false:
[twitter]
use_https = false
However, we recommend you to use HTTPS, especially in open WiFi networks where anybody could be sniffing packages and reading your personal information and communications.
The other available option is update_frequency
which controls how often (in
seconds) the timelines should be automatically updated.
An example configuration that updates the timelines every minute:
[twitter]
update_frequency = 60
Bindings¶
Almost every action within turses
is configurable. The defaults resemble
some of the bindings from the vi
editor. To see an up-to-date description
of all the available actions open the help buffer pressing ?
.
An example configuration with the motion keys assigned to the arrow keys:
[bindings]
up = up
down = down
left = left
right = right
turses
uses the representation of keystrokes provided by urwid to
map the bindings to actions.
Colors¶
You can change the colors of different elements of the UI in turses
. The
legal values for colors are listed in the urwid wiki.
An example configuration that sets a magenta background and white foreground in the editor:
[colors]
editor = white
editor_bg = dark magenta
Styles¶
This section allows you to onfigure the styles for some of the UI elements in
turses
. Below is a description of all the configuration options in the
section.
Templates¶
The templates allow you to configure how certain text is rendered in turses
.
The following templates are available:
header_template
: The header of a tweet.dm_template
: The header of a direct message.tab_template
: The text in a tab.
This templates contain variables enclosed between braces that are replaced by their corresponding value. Let’s look at the defaults to see all the available variables within the templates:
[styles]
reply_indicator = ✉
retweet_indicator = ♻
header_template = {username}{retweeted}{retweeter} - {time}{reply} {retweet_count}
username
: The author of the tweet.retweeted
: The value ofretweet_indicator
if the status is a retweet.retweeter
: The name of the retweeter (if any).time
: Relative time of the tweet.reply
: The value ofreply_indicator
if the status is a reply.retweet_count
: The number of retweets.
Warning
The reply_indicator
and retweet_indicator
values will be
surrounded with spaces.
[styles]
dm_template = {sender_screen_name} => {recipient_screen_name} - {time}
sender_screen_name
: The sender of the message.recipient_screen_name
: The recipient of the message.time
: Relative time of the message.
[styles]
tab_template = {unread} {timeline_name}
unread
: Unread tweet count.timeline_name
: The name of the timeline.
Tweets¶
You can configure how tweets are rendered. By default the statuses are enclosed in a box, but you can use a divider instead.
Here’s how the default configuration for status styles looks like:
[styles]
box_around_status = true
If box_around_status
is set to true
, the tweets will be rendered as
follows:
When setting box_around_status
to false
you can specify a divider
character that will be printed below the statuses.
Warning
The box_around_status
option has precedence over
status_divider
[styles]
box_around_status = false
status_divider = false
status_divider_char = ─
This is how it looks like using ─
as a status divider:
Editor¶
You can also configure the position of the editor in the screen modifyng the
editor_horizontal_align
and editor_vertical_align
options. The accepted
values for this options are the following:
editor_horizontal_align
:left
,center
orright
editor_vertical_align
:top
,middle
orbottom
An example configuration with the editor positioned in the center of the screen:
[styles]
editor_horizontal_align = center
editor_vertical_align = middle
Here’s how it looks like:
Url format¶
You can choose how URLs are rendered tweaking the url_format
option in the
styles
section. The following formats are available:
shortened
: URL shortened by Twitter (e.g.t.co/foo
)original
: Full original URL (e.g.http://example.com/
)display
: Original URL with an ellipsis if it’s too long and trimming the- protocol prefix (e.g.
example.com/a-very-long-⋯
)
The default option is display
. Here’s an example of a configuration option
to display the full original URLs:
[styles]
url_format = original
User info window¶
When you are focusing a status and press i
, turses
will show a popup
with information about the author of the status. At the bottom of the
information widget the last statuses posted by the user are shown.
The number of statuses to display is configurable via the
statuses_in_user_info
parameter. By default, it shows three statuses but we
can easily change that to show the last five:
[styles]
statuses_in_user_info = 5
Debug¶
The last section of the configuration is debug
, which is intended for
developers.
[debug]
logging_level = 3
Dev Guide¶
If you want to contribute to the project, this part of the documentation is for you.
Set up the development environment¶
You’re free to setup up the environment in any way you like. Here is a way using virtualenv and virtualenvwrapper. If you don’t have them, you can install them using:
$ pip install virtualenvwrapper
Virtual environments allow you to work on an installation of python which is not the one installed on your system. Especially, it will install the different projects under a different location.
To create the virtualenv environment, you have to do:
$ mkvirtualenv turses
Then you would have to install all the dependencies:
$ pip install -r requirements/dev.txt
$ make install
Running the test suite¶
Each time you add a feature, there are two things to do regarding tests: checking that the tests run in a right way, and be sure that you add tests for the feature you are working on or the bug you’re fixing.
The tests leaves under /tests
and you can run them using py.test
:
$ make test
Internals¶
Overview¶
Here is an overview of the multiple files that compound turses, each of them with a comment explaining their goal.
turses
├── requirements
│ ├── base.txt
│ └── dev.txt
├── setup.py
└── turses
├── api
│ ├── base.py # definition of an interface to the Twitter API
│ ├── backends.py # Twitter API implementations
│ ├── debug.py # mock API implementation for debugging
│ └── __init__.py
├── cli.py # logic for launching `turses`
├── config.py # configuration management
├── core.py # core logic: controller and event handling
├── __init__.py
├── meta.py # decorators and abstract base classes
├── models.py # data structures
├── ui.py # UI widgets
└── utils.py # misc funcions that don't fit elsewhere
turses.cli
¶
Handle the invocation of turses
from the command line.
-
turses.cli.
main
()¶ Launch
turses
.
turses.config
¶
-
class
turses.config.
Configuration
¶ Generate and parse configuration files. When instantiated, it loads the defaults.
Calling
Configuration.parse_args()
with anargparse.ArgumentParser
instance will modify the instance to match the options provided by the command line arguments.Calling
turses.config.Configuration.load()
on this class’ instances reads the preferences from the user configuration files. If no configuration or token files are found, this class will take care of creating them.Offers backwards compatibility with the Tyrs configuration.
turses.core
¶
This module contains the controller and key handling logic of turses.
-
class
turses.core.
InputHandler
(controller)¶ Maps user input to calls to
Controller
functions.
-
class
turses.core.
Controller
(ui, api, timelines)¶ The
Controller
.
turses.meta
¶
This module contains abstract classes and decorators.
Decorators¶
-
turses.meta.
wrap_exceptions
(func)¶ Augments the function arguments with the on_error and on_success keyword arguments.
Executes the decorated function in a try except block and calls on_success (if given) if no exception was raised, otherwise calls on_error (if given).
-
turses.meta.
async
(func)¶ Decorator for executing a function in a separate
threading.Thread
.
-
turses.meta.
filter_result
(func, filter_func=None)¶ Decorator for filtering the output of
func
withfilter_func
.
Abstract base classes¶
The abstract base classes can be understood as interfaces; they define a set of methods and properties that their subclasses must implement. They provide very general pieces of functionality.
-
class
turses.meta.
ActiveList
¶ A list that contains an active element.
This abstract class implements some functions but the subclasses must define the
turses.meta.ActiveList.active
property, as well asturses.meta.ActiveList.is_valid_index()
andturses.meta.ActiveList.activate_last()
. methods.
-
class
turses.meta.
UnsortedActiveList
¶ A
ActiveList
in which the active element position can be shifted either to the beginning or to the end.All the methods contained in this class are abstract.
-
class
turses.meta.
Observable
¶ An implementation of the observer pattern.
Zero or more observers can subscribe to the changes in the instances of this class. When the instance changes, it will call its notify method, which loops through the observers and calls update() on them.
-
class
turses.meta.
Updatable
(update_function=None, update_function_args=None, update_function_kwargs=None)¶ An abstract class for making a class updatable.
The constructor takes an update function and arguments used to update the subclasses of
Updatable
.When
update()
is executed,update_callback()
is called, passing it the result.
-
class
turses.meta.
Observable
An implementation of the observer pattern.
Zero or more observers can subscribe to the changes in the instances of this class. When the instance changes, it will call its notify method, which loops through the observers and calls update() on them.
-
class
turses.meta.
Observer
¶ An abstract class that can subscribe to updates from
Observable
instances.
-
turses.meta.
notify
(func)¶ Wrap an instance method func, calling the instance’s notify method after executing func.
turses.models
¶
This module contains the data structures that power turses
and
the Twitter entities represented into it.
Base model¶
The model on which turses
is based is TimelineList
,
a list of Timeline
objects. This model is mapped into
the list of buffers that appear on the user interface.
-
class
turses.models.
TimelineList
¶ A list of
Timeline
instances that implements theUnsortedActiveList
interface, thus having an active element and a group of adjacent visible timelines.
Twitter models¶
The Twitter entities represented on turses
are the following:
-
class
turses.models.
Timeline
(name='', statuses=None, **kwargs)¶ List of Twitter statuses ordered reversely by date, optionally with a name and a function that updates the current timeline and its arguments.
Its
Updatable
and implements theActiveList
interface.
-
class
turses.models.
User
(id, name, screen_name, description, url, created_at, friends_count, followers_count, favorites_count, status=None)¶ A Twitter user.
-
class
turses.models.
Status
(id, created_at, user, text, author='', entities=None, is_reply=False, in_reply_to_user='', in_reply_to_status_id=None, is_retweet=False, retweeted_status=None, retweet_count=0, is_favorite=False)¶ A Twitter status.
-
class
turses.models.
DirectMessage
(id, created_at, sender_screen_name, recipient_screen_name, text, entities=None)¶ A Twitter direct message.
-
class
turses.models.
List
(id, owner, created_at, name, slug, description, member_count, subscriber_count, private=False)¶ A Twitter list.
turses.ui
¶
This module contains the curses UI widgets.
-
class
turses.ui.
CursesInterface
¶ Creates a curses interface for the program, providing functions to draw all the components of the UI.
Provides a facade API to draw the representation of the
TimelineList
, helpHelpBuffer
and introBanner
screens.
Note
The list of widgets presented here is not complete.
Widget wrappers¶
turses
make heavy usage of the urwid.WidgetWrap
class to compose custom
widgets.
ScrollableWidgetWrap
helps to make widgets that
implement the Scrollable
interface, thus are navigable with
the motion commands up
, down
, scroll_to_top
and
scroll_to_bottom
.
-
class
turses.ui.
ScrollableWidgetWrap
(contents=None)¶ A
urwid.WidgetWrap
forScrollable
, list-like widgets.
Twitter Widgets¶
Here’s a list with some of the widgets that represent Twitter entities:
-
class
turses.ui.
TimelinesBuffer
(timelines=None, **kwargs)¶ A widget that displays one or more Timeline objects.
Another widget can be placed on top of it.
-
class
turses.ui.
StatusWidget
(status)¶ Widget containing a Twitter status.
-
class
turses.ui.
UserInfo
(user, last_statuses)¶ A widget for displaying a Twitter user info.
turses.utils
¶
This module contains functions used across different modules.
Authors¶
Code contributors¶
- Nicolas Paris <http://github.com/Nic0>
- Alejandro Gómez <http://github.com/alejandrogomez>
- Sascha Kruse <http://github.com/knopwob>
- Poapfel <http://github.com/poapfel>
- Giannis Damigos <http://github.com/xekarfwtos>
- Joe di Castro <http://github.com/joedicastro>
- Paul Ivanov <http://github.com/ivanov>
- replicant <http://github.com/replicant0wnz>
- Wes Turner <http://github.com/westurner>
- Johannes Holmberg <http://github.com/Jolmberg>
- Marco Milanesi <http://github.com/kpanic>
- Douglas La Rocca <http://github.com/douglas-larocca>
Active participants¶
Here’s a list with the people that participate or have participated actively in making turses better:
- Diego Jose <http://github.com/diegoxter>
- Kismet <http://github.com/kismet010>
- Denise Tiersch <http://github.com/dtiersch>
Changelog¶
0.3.1¶
- Upgrade Tweepy dependency to 3.3
- Python 3 port by Douglas Larocca
0.3.0¶
- Upgrade Tweepy dependency to 3.1
- Drop oauthlib dependency
0.2.23¶
- Upgrade Tweepy dependency to 2.3
0.2.22¶
- Upgrade Tweepy dependency to 2.2
0.2.21¶
- Bugfix: Turses no longer crashes when clicking on the window
0.2.20¶
- Mouse scrolling support (thanks to Wes Turner)
- Bugfix: Escape HTML entities without borking tweet text (thanks to Denise Tiersch)
0.2.19¶
- Bugfix: Restore Python 2.6 compatibility
0.2.18¶
- Bugfix: use ASCII characters for reply and retweet indicators
0.2.17¶
- Make Ctrl-C act as escape
- Hashtag searches in sessions
0.2.16¶
- Update to tweepy 2.1, fix search functionality
0.2.15¶
- Configurable retweet and reply indicators
0.2.14¶
- Daemonize threads so they finish when quitting turses
- Fix a bug regarding SIGCONT handling
0.2.13¶
- Y as shortcut for retweeting and favoriting a tweet
0.2.12¶
- Upgrade to Tweepy 2.0 (hence Twitter API v1.1)
0.2.11¶
- Include
in_reply_to_status_id
parameter in replies
0.2.10¶
- Use HTTPS by default (thanks to Joe Di Castro)
0.2.9¶
- Configurable number of statuses in user info widget
- Sessions support
- Better information for SSL errors
0.2.8¶
- Python 2.6 support
0.2.7¶
- center focus when receiving tweets after scrolling down the bottom
- get your tweets that have been retweeted
0.2.6¶
- configurable URL format
- better browser integration (by Paul Ivanov)
0.2.5¶
- search commands also available with no timelines
- clear the status bar in every mode
- asynchronous search timeline addition
- keep columns when deleting a buffer within them
- bugfix: crashed when deleting all buffers
0.2.4¶
- bugfix: unable to focus the topmost status when having multiple columns
0.2.3¶
- per-account configuration
- bugfix: crashed when navigating to empty buffers
0.2.2¶
- fix regression: timelines not updating periodically
0.2.1¶
- bugfix: the Twitter entities were not processed every time
0.2.0¶
- logging
0.1.18¶
- bugfix: crash when rendering direct messages
0.1.17¶
- developer docs
- border around editor
- bugfix: help and version were removed by stdout replacement
- debug mode
- offline debugging
0.1.16¶
- show a popup with user info when pressing i
0.1.15¶
- configurable editor alignment
- make turses play nicely with terminal multiplexers (Joe Di Castro)
- follow and unfollow users typing their nick in an editor (Giannis Damigos)
- bugfix: pressing <Esc> in search user editor made turses crash
- bugfix: avoid duplicate usernames in replies
0.1.14¶
- bugfix: crash when shifting buffers to the beginning or end
0.1.13¶
- bugfix: could not remove own retweets
- bugfix: inconsistencies with help
0.1.12¶
- bugfix: missing key binding in help (Giannis Damigos)
- bugfix: status messages cleared the editor
- configurable status bar visibility
- changes to manual retweet template
- set console title to turses
- docs on readthedocs
0.1.11¶
- bugfix: exception when marking tweet as favorite
0.1.10¶
- expanded URLs for search results
- bugfix: crashed when expanded URLs were missing
0.1.9¶
- open focused status in a browser
- show expanded URLs
0.1.8¶
- bugfix: packaging error
0.1.7¶
- bugfix: inconsistencies when navigating tweets with arrow keys
- configurable status wrappers: box, divider or none
0.1.6¶
- colored urls
- colored favorites
- bugfix: non-ascii characters on templates made turses crash
- visual indicators for status types (retweet, reply, favorite)
0.1.5¶
- configurable tab text
- colored hashtags and usernames
0.1.4¶
- update all timelines periodically
- configurable default timelines
- bugfix: don’t crash with empty timelines
- bugfix: manual retweet crashed
- bugfix: don’t capture all input
0.1.3¶
- bugfix: packaging error
0.1.2¶
- bugfix: error with packaging
0.1.1¶
- bindings to update all timelines
- bugfix: generate_token_file instead of create_token_file
0.1.0¶
- binding to open focused status authors’ tweets
- reload configuration
- configuration default location and format changed
0.0.15¶
- bugfix: DM recipient was not correctly resolved
- fetch newer tweets when scrolling up from the top and viceversa
- show retweets by default
0.0.14¶
- bugfix: logging
0.0.13¶
- thread view
0.0.12¶
- multiple visible timelines in columns
- fix bug with unicode input
- open URLs in browser
0.0.11¶
- include retweets in home timeline
- fix bug with non-existent method
0.0.10¶
- unread count
- mark all tweets in active timeline as read
- fix (again) a bug with mouse events
0.0.9¶
- compose tweet with same hashtags as the focused status
- create search timeline with hashtags from focused status
0.0.8¶
- fix bug: self follow/unfollow
- fix bug: editor signals
- direct messages :)
- persistent timeline cursor
0.0.7¶
- fix critical bug, missing dependency urwid
0.0.6¶
- fix bug with mouse events
- relative imports to avoid ImportError exceptions
0.0.5¶
- more colorful defaults
- see your own tweets
- search for a user’s tweets
0.0.4¶
- follow and unfollow
- pluggable UI and API
- associate callbacks to API calls
0.0.3¶
- bug with non-ascii characters in search solved
- asynchronous API calls
- favorite/unfavorite tweets
- Favorites timeline
0.0.2¶
- tests with coverage check
- fixed bug with missing dependency in setup.py
- decoration for tabs