termsaver-0.2/0000775000175000017500000000000012120627176013665 5ustar brunobruno00000000000000termsaver-0.2/setup.py0000775000175000017500000000636011751457401015410 0ustar brunobruno00000000000000#!/usr/bin/env python ############################################################################### # # file: setup.py # # Purpose: installs the termsaver application # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ The installation script of termsaver application. sudo python setup.py install # For debian based installation style sudo ./setup.py install --install-lib=/usr/local/share/termsaver --install-scripts=/usr/local/share/termsaver --install-data=/usr/local sudo ln -s /usr/local/share/termsaver/termsaver /usr/local/bin/termsaver You may also refer to: sudo pip install termsaver """ import os import platform from distutils.core import setup from termsaverlib import constants if platform.system() == 'FreeBSD': man_dir = 'man' else: man_dir = 'share/man' data_files = [(os.path.join('share', 'locale', lang, 'LC_MESSAGES'), [os.path.join('locale', lang, 'LC_MESSAGES', 'termsaver.mo')]) for lang in os.listdir('locale')] data_files.append((os.path.join(man_dir, 'man1'), ['doc/termsaver.1'])) setup(name='termsaver', version=constants.App.VERSION, description='Simple text-based terminal screensaver.', author='Bruno Braga', author_email='bruno.braga@gmail.com', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', 'Intended Audience :: Developers', 'Intended Audience :: Information Technology', 'Intended Audience :: System Administrators', 'License :: OSI Approved :: Apache Software License', 'Natural Language :: English', 'Operating System :: MacOS', 'Operating System :: POSIX', 'Programming Language :: Python', 'Topic :: Terminals', 'Topic :: Utilities', ], url='http://termsaver.info', keywords=['command-line', 'terminal', 'screensaver'], packages=[ 'termsaverlib', 'termsaverlib.plugins', 'termsaverlib.screen', 'termsaverlib.screen.base', 'termsaverlib.screen.helper', ], license='Apache License v2', scripts=['termsaver'], data_files=data_files, ) if __name__ == '__main__': # # The entry point of this application, as this should not be accessible as # a python module to be imported by another application. # print """ Thank you for trying termsaver. """ termsaver-0.2/termsaverlib/0000775000175000017500000000000012120627176016364 5ustar brunobruno00000000000000termsaver-0.2/termsaverlib/constants.py0000664000175000017500000000640212120350701020737 0ustar brunobruno00000000000000############################################################################### # # file: constants.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ Holds constant values used throughout termsaver application. """ class PropertyClass: """ A base class that defines a class as a holder for properties only, not to be instantiated in any circumstances. """ def __init__(self): """ This class (and sub-classes) should not be instantiated. """ raise NotImplementedError("This class cannot be instantiated!") class App(PropertyClass): """ Holds application related properties used by termsaver screens. Refer to each of the available properties for detailed documentation. """ VERSION = "0.2" """ Defines the version of termsaver application. This is accessed during install process, and to any help and usage messages informed by it. Refer to CHANGELOG file for a complete history about this project. """ NAME = 'termsaver' """ Defines the termsaver application, as it is executed from command-line. """ TITLE = 'TermSaver' """ Defines the termsaver application's official name as it should appear in documentation. """ DESCRIPTION = 'A simple text-based terminal screensaver' """ Defines the main description of the termsaver application. """ URL = 'http://termsaver.info' """ Defines the termsaver official website address. """ SOURCE_URL = 'http://github.com/brunobraga/termsaver' """ Defines the termsaver official source-code control site, hosted on GitHub. """ AUTHORS = ['Bruno Braga '] """ Defines a list of all authors contributing to the termsaver application. """ class Settings(PropertyClass): """ Holds configuration settings used by termsaver application. Refer to each of the available properties for detailed documentation. """ CHAR_DELAY_SECONDS = 0.003 """ Defines basically the speed in which the text will be displayed, character by character, giving a cool impression of an automated type writing machine Default value is 0.003 seconds (3 milliseconds). It is advised to use values between 0.01 and 0.001. """ FETCH_INTERVAL_SECONDS = 3600 """ Defines the interval between each fetching of data over the Internet. Default value is 1 hour. """ termsaver-0.2/termsaverlib/exception.py0000664000175000017500000001264312120351727020736 0ustar brunobruno00000000000000############################################################################### # # file: exceptions.py # # Purpose: holds termsaver special exceptions # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module holds special exceptions triggered by termsaver (and handled internally as well, but with more human-readable treatment). The classes available here are: * `TermSaverException` A generic exception that implements read-only functionality for its inheriting classes. * `ScreenNotFoundException` An exception that happens when termsaver is dealing with non existing screens. * `PathNotFoundException` An exception that happens when termsaver is dealing with non existing files. * `UrlException` An exception that happens when termsaver is dealing with URL connectvitiy issues. """ class TermSaverException(Exception): """ A base exception class providing additional read-only feature to its inheriting classes. You must fill the `readonly` list to enable a property as read-only. """ readonly = [] """ Defines a list to place names of properties that should be read-only. """ help_msg = '' """ An extra string of information to help guide users on exception issues. """ def __init__(self, *args, **kwargs): """ Instantiate a new exception object. You may use the extra property `help` when instantiating this. """ Exception.__init__(self, *args) # get the help argument dynamically from kwargs, if applicable if "help" in kwargs: self.help_msg = kwargs['help'] # mark this property as read-only self.readonly.append("help") def __setattr__(self, name, val): """ Override of original to check for read-only properties, throwing exception if tempered with. """ if name not in self.readonly: self.__dict__[name] = val else: raise Exception("%s.%s is read only!" % (self.__class__.__name__, name)) class PathNotFoundException(TermSaverException): """ Exception to handle special cases when a path required to run could not be found in the file system. """ path = '' """ The name of the screen that could not be found by termsaver. """ def __init__(self, path, *args, **kwargs): """ Instantiates this exception class, with an additional parameter for the name of the screen not found by termsaver. This value is accessible by """ TermSaverException.__init__(self, *args, **kwargs) self.path = path # mark this property as read-only self.readonly.append('path') class UrlException(TermSaverException): """ Exception to handle special cases when connectivity to a specific URL was not successful. """ url = '' """ The name of the screen that could not be found by termsaver. """ def __init__(self, url, *args, **kwargs): """ Instantiates this exception class, with an additional parameter for the name of the screen not found by termsaver. This value is accessible by """ TermSaverException.__init__(self, *args, **kwargs) self.url = url # mark this property as read-only self.readonly.append('url') class InvalidOptionException(TermSaverException): """ Exception to handle special cases when user uses comman line options wrongfully. """ option_name = '' """ The name of the screen that could not be found by termsaver. """ def __init__(self, option_name, *args, **kwargs): """ Instantiates this exception class, with an additional parameter for the name of the screen not found by termsaver. This value is accessible by """ TermSaverException.__init__(self, *args, **kwargs) self.option_name = option_name # mark this property as read-only self.readonly.append('option_name') class XmlException(TermSaverException): """ Exception to handle XML issues. """ name = '' """ The name of the file path or URL that had issues with parsing """ def __init__(self, name, *args, **kwargs): """ Instantiates this exception class, with an additional parameter for the name of the screen not found by termsaver. This value is accessible by """ TermSaverException.__init__(self, *args, **kwargs) self.name = name # mark this property as read-only self.readonly.append('name') termsaver-0.2/termsaverlib/screen/0000775000175000017500000000000012120627176017643 5ustar brunobruno00000000000000termsaver-0.2/termsaverlib/screen/matrix.py0000664000175000017500000003330311744014541021520 0ustar brunobruno00000000000000# -*- coding: utf-8 -*- ############################################################################### # # file: matrix.py # # Purpose: refer to python doc for documentation details. # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module contains a fancy screen that displays falling text with Japanese characters similar to the Matrix movie. See additional information in the class itself. See more details of the movie in here: http://en.wikipedia.org/wiki/The_Matrix The screen class available here is: * `MatrixScreen` """ # # Python mobdules # import random import time # # Internal modules # from termsaverlib.screen.base import ScreenBase from termsaverlib.screen.helper.position import PositionHelperBase from termsaverlib import exception, constants from termsaverlib.i18n import _ class MatrixScreen(ScreenBase, PositionHelperBase): """ Fancy screen that displays falling Japanese and alpha - numeric characters simulating the Matrix movie. The Japanese characters are based on the Japanese Katakana phonetic letters. See more info in Wikipedia: http://en.wikipedia.org/wiki/Katakana From its base classes, the functionality provided here bases on the settings defined below: * clean up each cycle: False to give a sense of continuity, there will be no screen cleaning up """ line_delay = None """ Defines the line printing delay, to give a cool visual of a moving screen. This value is measured in seconds, and default marks are defined as 30 x `constants.Settings.LINE_DELAY_SECONDS`. """ granularity = 10 """ Defines an integer value that represents the granularity in which the characters will be displayed on screen, moving from very sparse (1) to very dirty (100). Default value should be 10, which gives a nice look with the algorithm executed in `get_char_list`. """ space_zenkaku = ' ' # WARNING: This is NOT a simple space char """ Represent a full-width space character, used to fill in the blanks on the screen and guarantee good positioning. See more information about full-width characters in: http://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms """ space_hangaku = ' ' """ Represent a half-width space character, used to fill in the blanks on the screen and guarantee good positioning. See more information about full-width characters in: http://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms """ digmap_alpha_num_zenkaku = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ] """ Holds the list of alpha-numeric characters, formatted with full-width formatting, to ensure char positioning on the screen during display. See more information about this at: http://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms """ digmap_alpha_num_hangaku = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'W', 'Y', 'Z', ] """ Holds the list of alpha-numeric characters, formatted with half-width formatting, to ensure char positioning on the screen during display. See more information about this at: http://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms """ digmap_kana_hangaku = [ 'ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ', 'サ', 'シ', 'ス', 'セ', 'ソ', 'タ', 'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', 'マ', 'ミ', 'ム', 'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'ワ', 'ン', 'ヲ', 'ー', ] """ Holds the list of Japanese Katakana used to display the screensaver. Based on information available on Wikipedia: http://en.wikipedia.org/wiki/Katakana All characters here are formatted with half-width formatting, to ensure char positioning on the screen during display. See more information about this at: http://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms """ digmap_kana_zenkaku = [ 'ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ', 'サ', 'シ', 'ス', 'セ', 'ソ', 'タ', 'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', 'マ', 'ミ', 'ム', 'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'ワ', 'ヰ', 'ヱ', 'ヲ', 'ン', 'ー', ] """ Holds the list of Japanese Katakana used to display the screensaver. Based on information available on Wikipedia: http://en.wikipedia.org/wiki/Katakana All characters here are formatted with full-width formatting, to ensure char positioning on the screen during display. See more information about this at: http://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms """ space = "" """ The actual space property used for blank printing. This will be based on `space_hangaku`, unless specified otherwise. """ digmap = [] """ The actual property used for character picking. This will be based on both `digmap_alpha_num_*` and `digmap_kana_*` value, unless specified otherwise. """ screen_map = [] """ The mapping of xy position and length of each line. This will hold the randomized values that are show on screen line by line. """ use_zenkaku = False """ Defines if all characters and size calculations should be done for full-width or half-width. """ proportion = 1 """ Defines the granulation proportion for displaying characters in full-width of half-width size. """ def __init__(self): """ The constructor of this class. """ ScreenBase.__init__(self, "matrix", _("displays a matrix movie alike screensaver"), {'opts': 'hkzd:g:', 'long_opts': ['kana', 'zenkaku', 'help', 'granularity=', 'delay=']}, ) self.cleanup_per_cycle = False # set defaults if self.line_delay is None: self.line_delay = 30 * constants.Settings.CHAR_DELAY_SECONDS def _run_cycle(self): """ Executes a cycle of this screen. """ # Identify terminal geometry self.get_terminal_size() if len(self.screen_map) == 0 or self.changed_geometry: # build it for the first time or whenever the geometry changes self.__build_screen_map() print self.print_line() time.sleep(self.line_delay) def _usage_options_example(self): """ Describe here the options and examples of this screen. The method `_parse_args` will be handling the parsing of the options documented here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ print _(""" Options: -g, --granularity an integer value to define how dirt should the screen be. Default value is [%(granularity)s]. Use something like [1] for clean style, or a [100] for total dirt. -d, --delay Defines the speed (in seconds) of the character movement Default value is [%(line_delay)s] (in seconds). -k, --kana-only Displays only Japanese characters (excludes alpha numeric). -z, --zenkaku Displays full-width (fattish) Japanese characters. By default it displays half-width characters. -h, --help Displays this help message Examples: $ %(app_name)s %(screen)s -g 100 This will print out random characters in maximum dirt (using almost the entire screen space). Try [1] for very clean results. $ %(app_name)s %(screen)s -g 5 -d 0.001 -k This will give a cleaner print than the default, much faster with only Japanese characters. """) % { 'screen': self.name, 'app_name': constants.App.NAME, 'granularity': self.granularity, 'line_delay': self.line_delay, } def _parse_args(self, prepared_args): """ Handles the special command-line arguments available for this screen. Although this is a base screen, having these options prepared here can save coding for screens that will not change the default options. See `_usage_options_example` method for documentation on each of the options being parsed here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ use_kana_only = False for o, a in prepared_args[0]: # optlist, args if o in ("-h", "--help"): self.usage() self.screen_exit() elif o in ("-k", "--kana"): use_kana_only = True elif o in ("-z", "--zenkaku"): self.use_zenkaku = True elif o in ("-g", "--granularity"): try: # make sure argument is a valid value (int) self.granularity = int(a) except: raise exception.InvalidOptionException("granularity") if self.granularity <= 0: raise exception.InvalidOptionException("granularity", "Must be higher than zero") elif o in ("-d", "--delay"): try: # make sure argument is a valid value (float) self.line_delay = float(a) except: raise exception.InvalidOptionException("delay") if self.line_delay <= 0: raise exception.InvalidOptionException("delay", "Must be higher than zero") else: # this should never happen! raise Exception(_("Unhandled option. See --help for details.")) # fill in other important properties if self.use_zenkaku: digmap_kana = self.digmap_kana_zenkaku digmap_alpha_num = self.digmap_alpha_num_zenkaku self.space = self.space_zenkaku self.proportion = 2 else: digmap_kana = self.digmap_kana_hangaku digmap_alpha_num = self.digmap_alpha_num_hangaku self.space = self.space_hangaku self.proportion = 1 self.digmap.extend(digmap_kana) if not use_kana_only: self.digmap.extend(digmap_alpha_num) def __build_screen_map(self): """ Defines the `screen_map` size and structure, considering the terminal geometry and the fact that full-width characters occupy the double of the space of a usual char. Additionally, it will start randomizing which x position should start with visible chars and which should be just empty space. """ # clean up previous self.screen_map = [] for __ in range(0, self.geometry['x'] / self.proportion): if random.random() > 0.5: char_list = self.get_char_list() else: char_list = [self.space for __ in \ range(0, random.randint(0, self.geometry['y']))] self.screen_map.append(char_list) def get_char_list(self): """ creates a randomized list of characters to be used in the `screen_map`. """ result = [] while(len(result) == 0): bt = [self.space for __ in range(0, min((self.geometry['y'], random.randint(0, self.geometry['y'] * 20 / (self.granularity * \ self.proportion)))))] cl = [self.digmap[random.randint(0, len(self.digmap)) - 1] \ for __ in range(0, random.randint(0, self.geometry['y'] - len(bt)))] result = bt result.extend(cl) return result def print_line(self): """ Prints the line picking up the first available char of each list within the `screen_map`, and creating (renewing) them if empty. """ result = "" for i in range(0, len(self.screen_map)): if len(self.screen_map[i]) == 0: self.screen_map[i] = self.get_char_list() try: result += self.screen_map[i].pop(0) except: # ignore errors in here pass return result termsaver-0.2/termsaverlib/screen/urlfetcher.py0000664000175000017500000000420511741736000022354 0ustar brunobruno00000000000000############################################################################### # # file: urlfetcher.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ Simple screensaver that displays data from a URL. See additional information in the class itself. The screen class available here is: * `UrlFetcherScreen` """ # # Internal modules # from termsaverlib.screen.base.urlfetcher import UrlFetcherBase from termsaverlib import constants from termsaverlib.i18n import _ class UrlFetcherScreen(UrlFetcherBase): """ Simple screensaver that displays data from a URL. """ def __init__(self): """ Creates a new instance of this class. """ UrlFetcherBase.__init__(self, "urlfetcher", _("displays url contents with typing animation")) def _message_no_url(self): """ """ return _(""" You just need to provide the URL from where %(app_title)s will read and display on screen. If you do not have any idea which URL to use, check out some examples here: RFC RFC-1034 - http://tools.ietf.org/rfc/rfc1034.txt See a RFC list from Wikipedia: http://en.wikipedia.org/wiki/List_of_RFCs (remember to use the txt version) """) % { 'app_title': constants.App.TITLE, } termsaver-0.2/termsaverlib/screen/rssfeed.py0000664000175000017500000000670311741736000021651 0ustar brunobruno00000000000000############################################################################### # # file: rssfeed.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ Simple screensaver that displays data from a RSS feed. See additional information in the class itself. The screen class available here is: * `RSSFeedScreen` """ # # Internal modules # from termsaverlib.screen.base.rssfeed import RSSFeedScreenBase from termsaverlib import constants from termsaverlib.i18n import _ class RSSFeedScreen(RSSFeedScreenBase): """ Simple screensaver that displays data from a RSS feed. RSS Feed Screen configuration: * sleep between items: 3 seconds * clean up each cycle: True this will force the screen to be cleaned (cleared) before each joke is displayed * character display delay: 0.015 a bit faster than traditional speeds, because users are not interested in the char print animation as much. * clean up each item: False * display format: '%(title)s (%(pubDate)s)\n%(description)s\n%(link)s\n.\n' """ def __init__(self): """ Creates a new instance of this class. """ RSSFeedScreenBase.__init__(self, "rssfeed", _("displays rss feed information"), None, ["pubDate", "title", "link", "description"], '%(title)s (%(pubDate)s)\n%(description)s\n%(link)s\n.\n', ) # set defaults for this screen self.cleanup_per_cycle = True self.cleanup_per_item = False self.sleep_between_items = 3 self.delay = 0.015 def _message_no_url(self): """ Defines a method to be overriden by inheriting classes, with the purpose to display extra help information for specific errors. """ return _(""" You just need to provide the URL of the RSS feed from where %(app_title)s will read and display on screen. If you do not have any idea which RSS to use, check out some examples here: CNN Top Stories - http://rss.cnn.com/rss/edition.rss World - http://rss.cnn.com/rss/edition_world.rss Technology - http://rss.cnn.com/rss/edition_technology.rss See CNN's complete list of RSS syndication here: http://edition.cnn.com/services/rss/ Lifehacker - http://www.lifehacker.com/index.xml Note: Lifehacker uses HTML to deliver "description" contents in the RSS, so you might need to change the format to something like: --format "%%(title)s (%%(pubDate)s)\\n" """) % { 'app_title': constants.App.TITLE, } termsaver-0.2/termsaverlib/screen/programmer.py0000664000175000017500000000620611741736000022367 0ustar brunobruno00000000000000############################################################################### # # file: programmer.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ A screen to read source code files (or any other) in a typing writer animation See additional information in the class itself. The helper class available here is: * `ProgrammerScreen` """ from termsaverlib.screen.base.filereader import FileReaderBase from termsaverlib import constants from termsaverlib.i18n import _ class ProgrammerScreen(FileReaderBase): """ A simple screen that will display any text (hei programmer, source code!), on screen in a typing writer animation. From options available in `FileReaderBase`, this will use: * `FileReaderBase.cleanup_per_cycle` as True * `FileReaderBase.cleanup_per_file` as True """ def __init__(self): """ Creates a new instance of this class (used by termsaver script) From its base classes, the functionality provided here bases on the settings defined below: * clean up each cycle: True this will force the screen to be cleaned (cleared) before each new cycle is displayed * clean up each file: True this will force the screen to be cleaned (cleared) before each new file is displayed """ FileReaderBase.__init__(self, "programmer", _("displays source code in typing animation")) self.cleanup_per_cycle = True self.cleanup_per_file = True def _message_no_path(self): """ The specific helper message in case there is no path informed in the command-line arguments. """ return _(""" You just need to provide the path to the location from where %(app_title)s will read and display on screen. If you do not have any code in your local machine, just get some interesting project from the Internet, such as Django (http://www.djangoproject.com): If you have access to subversion, you may download it at: svn co https://code.djangoproject.com/svn/django/trunk/ django-trunk Or, just download the zipped source and unpack it on your local machine: https://www.djangoproject.com/download/ """) % { 'app_title': constants.App.TITLE, } termsaver-0.2/termsaverlib/screen/quotes4all.py0000664000175000017500000000610411741736000022306 0ustar brunobruno00000000000000############################################################################### # # file: quotes4all.py # # Purpose: holds base classes used by screens in termsaver # refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ Simple screensaver that displays recent jokes from http://jokes4all.net website, from its hourly updated RSS feed. See additional information in the class itself. The screen class available here is: * `Quotes4AllRSSFeedScreen` """ # # Internal modules # from termsaverlib.screen.base.rssfeed import SimpleRSSFeedScreenBase from termsaverlib.i18n import _ class Quotes4AllRSSFeedScreen(SimpleRSSFeedScreenBase): """ Simple screensaver that displays recent jokes from http://jokes4all.net website, from its hourly updated RSS feed. RSS Feed Screen configuration: * sleep between items: 10 seconds this is to allow people enough time for them to read the quote * clean up each cycle: True this will force the screen to be cleaned (cleared) before each joke is displayed * character display delay: 0.015 a bit faster than traditional speeds, because users are not interested in the char print animation as much. * clean up each item: True this will force the screen to be cleaned (cleared) before each image is displayed * display format: '\n"%(description)s" -- %(title)s\n' * center in vertical * center in horizontal * clean dirt: new lines """ def __init__(self): """ Creates a new instance of this class (used by termsaver script) """ SimpleRSSFeedScreenBase.__init__(self, "quotes4all", _("displays recent quotes from quotes4all.net"), "http://quotes4all.net/rss/360010110/quotes.xml", ["title", "description"], '"%(description)s" -- %(title)s', 0.015 ) # set defaults for this screen self.sleep_between_items = 10 self.line_delay = 0 self.cleanup_per_cycle = True self.cleanup_per_item = True self.center_vertically = True self.center_horizontally = True self.clean_dirt = ["\n", " "] termsaver-0.2/termsaverlib/screen/base/0000775000175000017500000000000012120627176020555 5ustar brunobruno00000000000000termsaver-0.2/termsaverlib/screen/base/urlfetcher.py0000664000175000017500000002041011741736000023262 0ustar brunobruno00000000000000############################################################################### # # file: urlfetcher.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module contains a screen base class that handles URL fetched contents. See additional information in the class itself. The helper classes available here are: * `UrlFetcherBase` * `SimpleUrlFetcherBase` """ # # Internal modules # from termsaverlib.screen.base import ScreenBase from termsaverlib import exception, constants from termsaverlib.screen.helper.urlfetcher import URLFetcherHelperBase from termsaverlib.screen.helper.typing import TypingHelperBase from termsaverlib.i18n import _ class UrlFetcherBase(ScreenBase, TypingHelperBase, URLFetcherHelperBase): """ A base class used to handle URL fetched contents, and display them accordingly. This also includes the `TypingHelperBase` to add functionality of typing writer display. The instantiation of this class takes two additional arguments, compared with its base class: * url: the URL address to fetch data from * `delay`: defines the delay for printing out characters of a string """ url = "" """ the URL address to fetch data from """ def __init__(self, name, description, url=None, delay=None, cli_opts=None): """ Creates a new instance of this class. This constructor has two additional arguments, compared with its base class: * url: the URL address to fetch data from * `delay`: defines the delay for printing out characters of a string """ ScreenBase.__init__(self, name, description, cli_opts) if not cli_opts: self.cli_opts = { 'opts': 'hd:u:', 'long_opts': ['help', 'delay=', 'url='], } self.delay = delay self.url = url def _run_cycle(self): """ Executes a cycle of this screen. The actions taken here, for each cycle, are as follows: * retrieve data from `url` * print using `typing_print` """ data = self.fetch(self.url) self.clear_screen() self.typing_print(data) def _message_no_url(self): """ Defines a method to be overriden by inheriting classes, with the purpose to display extra help information for specific errors. """ return "" def _usage_options_example(self): """ Describe here the options and examples of this screen. The method `_parse_args` will be handling the parsing of the options documented here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ print _(""" Options: -u, --url Defines the URL location from where the information should be fetched, then displayed. This option is MANDATORY. -d, --delay Sets the speed of the displaying characters default is 0.003 of a second (advised to keep between 0.01 and 0.001). -h, --help Displays this help message Examples: $ %(app_name)s %(screen)s -u www.google.com This will trigger the screensaver to fetch the HTML contents of this web site and display progressively. $ %(app_name)s %(screen)s -u www.google.com -d 0 This will trigger the screensaver to fetch the HTML contents of this web site with no delay (too fast for a screensaver, but it's your choice that matters!) """) % { 'screen': self.name, 'app_name': constants.App.NAME, } def _parse_args(self, prepared_args): """ Handles the special command-line arguments available for this screen. Although this is a base screen, having these options prepared here can save coding for screens that will not change the default options. See `_usage_options_example` method for documentation on each of the options being parsed here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ for o, a in prepared_args[0]: # optlist, args if o in ("-h", "--help"): self.usage() self.screen_exit() elif o in ("-d", "--delay"): try: # make sure argument is a valid value (float) self.delay = float(a) except: raise exception.InvalidOptionException("delay") elif o in ("-u", "--url"): try: # try to fix the url formatting self.url = self.fix_uri(a) except Exception, e: raise exception.InvalidOptionException("url", e.message) else: # this should never happen! raise Exception(_("Unhandled option. See --help for details.")) # last validations if self.url in (None, ''): raise exception.InvalidOptionException("url", _("It is mandatory option"), help=self._message_no_url()) class SimpleUrlFetcherBase(UrlFetcherBase): """ Inherits the `UrlFetcherBase` class to handle basic URL fetching. This will simplify the use of UrlFetcherBase by forcing a fixed URL, and simplify the code of screens inheriting from it. """ def __init__(self, name, description, url, delay=None): """ Creates a new instance of this class. This constructor has forced the url argument, compared with its base class, as it has no command line options to define its value manually """ UrlFetcherBase.__init__(self, name, description, url, delay, {'opts': 'h', 'long_opts': ['help']}) def _usage_options_example(self): """ Describe here the options and examples of this screen. The method `_parse_args` will be handling the parsing of the options documented here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ print """ Options: -h, --help Displays this help message """ def _parse_args(self, prepared_args): """ Handles the special command-line arguments available for this screen. Although this is a base screen, having these options prepared here can save coding for screens that will not change the default options. See `_usage_options_example` method for documentation on each of the options being parsed here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ for o, __ in prepared_args[0]: # optlist, args if o in ("-h", "--help"): self.usage() self.screen_exit() else: # this should never happen! raise Exception(_("Unhandled option. See --help for details.")) termsaver-0.2/termsaverlib/screen/base/rssfeed.py0000664000175000017500000002716111744013132022561 0ustar brunobruno00000000000000############################################################################### # # file: rssfeed.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module contains a screen base class that handles RSS feeds display. See additional information in the class itself. The helper classes available here are: * `RSSFeedScreenBase` * `SimpleRSSFeedScreenBase` """ # # Python built-in modules # import time # # Internal modules # from termsaverlib.screen.base.urlfetcher import UrlFetcherBase from termsaverlib.screen.helper.xmlreader import XMLReaderHelperBase from termsaverlib.screen.helper.typing import TypingHelperBase from termsaverlib.screen.helper.position import PositionHelperBase from termsaverlib import common, exception, constants from termsaverlib.i18n import _ class RSSFeedScreenBase(UrlFetcherBase, TypingHelperBase, PositionHelperBase, XMLReaderHelperBase): """ A base class used to handle RSS feeds, and display them accordingly. This also includes the `TypingHelperBase` and `PositionHelperBase` to add functionality of typing writer display, and certain positioning features. The instantiation of this class takes two additional arguments, compared with its base class: * tags: defines the list of string tags of the RSS that you are interest in. Accepted values are: * pubDate * title * link * description * print_format: defines the formating to be printed out, based on the tags available (use python string format with dictionary. eg. '%(title)s (%(pubDate)s)\n\n') When inheriting from this screen, you can also take advantage of the following properties and functionalities: * `sleep_between_items`: Sleeping time, in seconds, between each RSS item displayed. * `cleanup_per_item`: Defines if termsaver should clean the screen for each item being read * `center_vertically`: Defines if the information displayed should be vertically centered on screen. * `center_horizontally`: Defines if the information displayed should be horizontally centered on screen. """ sleep_between_items = 1 """ Sleeping time, in seconds, between each RSS item displayed. """ cleanup_per_item = False """ Defines if termsaver should clean the screen for each item being read """ center_vertically = False """ Defines if the information displayed should be vertically centered on screen. """ center_horizontally = False """ Defines if the information displayed should be horizontally centered on screen. """ clean_html = True """ Defines that the output text must be cleaned from HTML tags. """ def __init__(self, name, description, url=None, tags=None, print_format=None, delay=None, cli_opts=None): """ Creates a new instance of this class. This constructor has two additional arguments, compared with its base class: * tags: defines the list of string tags of the RSS that you are interest in. Accepted values are: * pubDate * title * link * description * print_format: defines the formating to be printed out, based on the tags available (use python string format with dictionary. eg. '%(title)s (%(pubDate)s)\n\n') """ UrlFetcherBase.__init__(self, name, description, url, delay, cli_opts) XMLReaderHelperBase.__init__(self, "item", tags) self.print_format = print_format # build deafults if not cli_opts: self.cli_opts = { 'opts': 'hrd:u:f:', 'long_opts': ['raw', 'help', 'delay=', 'url=', 'format='] } if not print_format: self.print_format = '%(title)s (%(pubDate)s)\n\n' def _usage_options_example(self): """ Describe here the options and examples of this screen. The method `_parse_args` will be handling the parsing of the options documented here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ print _(""" Options: -h, --help Displays this help message -u, --url The URL path of the RSS feed (text) to be displayed -r, --raw Shows all text available (with HTML if any) -f, --format The printing format according to values available in RSS feed: * pubDate * title * link * description You must use python dictionary based formatting style (see examples for details) Example: $ %(app_name)s %(screen)s -u http://rss.cnn.com/rss/edition.rss This will trigger the screensaver to fetch the contents from the CNN feed and display it in default formatting: '%%(title)s (%%(pubDate)s)\\n' $ %(app_name)s %(screen)s -u http://rss.cnn.com/rss/edition.rss \\ -f '%%(title)s (%%(pubDate)s)\\n%%(description)s\\n%%(link)s' This will trigger the screensaver to fetch the contents from the CNN feed and display all contents as specified in the formatting. """) % { 'app_name': constants.App.NAME, 'screen': self.name, 'description': self.description, } def _parse_args(self, prepared_args): """ Handles the special command-line arguments available for this screen. Although this is a base screen, having these options prepared here can save coding for screens that will not change the default options. See `_usage_options_example` method for documentation on each of the options being parsed here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ for o, a in prepared_args[0]: # optlist, args if o in ("-h", "--help"): self.usage() self.screen_exit() elif o in ("-r", "--raw"): self.clean_html = False elif o in ("-f", "--format"): #remove escaping self.print_format = common.unescape_string(a) elif o in ("-u", "--url"): try: # try to fix the url formatting self.url = self.fix_uri(a) except Exception, e: raise exception.InvalidOptionException("url", e.message) else: # this should never happen! raise Exception(_("Unhandled option. See --help for details.")) # last validations if self.url in (None, ''): raise exception.InvalidOptionException("url", "It is mandatory option", help=self._message_no_url()) def _run_cycle(self): """ Executes a cycle of this screen. The actions taken here, for each cycle, are as follows: * retrieve data from `url` * parses the data into a XML dom document object * parses the document object into a list of dictionaries * print using `typing_print` """ self.doc_xml_string(self.fetch(self.url)) self.parse_data() self.clear_screen() for item in self.data: new_text = item try: new_text = common.unescape_string(self.print_format % new_text) # remove HTML tags is applicable if self.clean_html: new_text = common.strip_html(new_text) except: raise exception.InvalidOptionException("format", _("There was an error while using your format.")) if self.center_vertically or self.center_horizontally: self.get_terminal_size() if self.center_vertically: new_text = self.center_text_vertically(new_text) if self.center_horizontally: new_text = self.center_text_horizontally(new_text) self.typing_print(new_text) time.sleep(self.sleep_between_items) if self.cleanup_per_item: self.clear_screen() class SimpleRSSFeedScreenBase(RSSFeedScreenBase): """ Inherits the `RSSFeedScreenBase` class to handle basic RSS parsing. This will simplify the use of RSSFeedScreenBase by forcing a fixed URL feed, and simplify the code of screens inheriting from it. """ def __init__(self, name, description, url, tags=None, print_format=None, delay=None): """ Creates a new instance of this class. This constructor has forced the url argument, compared with its base class, as it has no command line options to define its value manually """ RSSFeedScreenBase.__init__(self, name, description, url, tags, print_format, delay, {'opts': 'h', 'long_opts': ['help']} ) def _usage_options_example(self): """ Describe here the options and examples of this screen. The method `_parse_args` will be handling the parsing of the options documented here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ print """ Options: -h, --help Displays this help message """ def _parse_args(self, prepared_args): """ Handles the special command-line arguments available for this screen. Although this is a base screen, having these options prepared here can save coding for screens that will not change the default options. See `_usage_options_example` method for documentation on each of the options being parsed here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ for o, __ in prepared_args[0]: # optlist, args if o in ("-h", "--help"): self.usage() self.screen_exit() else: # this should never happen! raise Exception(_("Unhandled option. See --help for details.")) termsaver-0.2/termsaverlib/screen/base/filereader.py0000664000175000017500000002471511741736000023235 0ustar brunobruno00000000000000############################################################################### # # file: filereader.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module contains a screen base class that handles screens that require recursive directory scanning for files to be printed out. See additional information in the class itself. The helper class available here is: * `FileReaderBase` """ # # Python built-in modules # import os # # Internal modules # from termsaverlib.screen.base import ScreenBase from termsaverlib import exception, constants from termsaverlib.screen.helper.typing import TypingHelperBase from termsaverlib.i18n import _ class FileReaderBase(ScreenBase, TypingHelperBase): """ A base class used to handle file reading, more specifically, multiple files retrieved from a `path` recursively. This also uses the `TypingHelperBase` helper class to add functionality of typing writer display. The instantiation of this class takes two additional arguments, compared with its base class: * `delay`: defines the speed of the typing writer. See more details of this in `TypingHelperBase` class documentation. Its value is defined by `TypingHelperBase`'s default, if none is informed. * `path`: defines the path from where this screen should scan for files When inheriting from this screen, you can also take advantage of the following properties and functionalities: * `cleanup_per_file`: forces to clean up the screen for each file in the looping. The alternative, available in `ScreenBase.cleanup_per_cycle`, only handles a cycle action. """ path = '' """ Defines the path to be recursively checked for text files to be displayed on terminal screen. """ cleanup_per_file = False """ Defines if termsaver should clean the screen for each file being read """ def __init__(self, name, description, path=None, delay=None, cli_opts=None): """ Creates a new instance of this class. This constructor has two additional arguments, compared with its base class: * delay: defines the speed of the typing writer. See more details of this in `TypingHelperBase` class documentation. * path: defines the path from where this screen should scan for files """ ScreenBase.__init__(self, name, description, cli_opts) # define default cli options, if none is informed if not cli_opts: self.cli_opts = { 'opts': 'hd:p:', 'long_opts': ['help', 'delay=', 'path='], } self.delay = delay self.path = path self.cleanup_per_cycle = False def _run_cycle(self): """ Executes a cycle of this screen. The actions taken here, for each cycle, are as follows: * loop all files retrieved from `path` * open each file, read its contents * print using `typing_print` """ # validate path if not os.path.exists(self.path): raise exception.PathNotFoundException(self.path) # get the list of available files file_list = self._recurse_to_list(self.path) if len(file_list) == 0: raise exception.PathNotFoundException(self.path) self.clear_screen() for path in file_list: f = open(path, 'r') # read the file with the typing feature self.typing_print(f.read()) f.close() if self.cleanup_per_file: self.clear_screen() def _usage_options_example(self): """ Describe here the options and examples of this screen. The method `_parse_args` will be handling the parsing of the options documented here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ print _(""" Options: -p, --path Sets the location to search for text-based source files. this option is mandatory. -d, --delay Sets the speed of the displaying characters default is%(default_delay)s of a second -h, --help Displays this help message Examples: $ %(app_name)s %(screen)s -p /path/to/my/code This will trigger the screensaver to read all files in the path selected $ %(app_name)s %(screen)s -p /path/to/my/code -d 0 This will trigger the screensaver to read all files in the path selected with no delay (too fast for a screensaver, but it's your choice that matters!) """) % { 'screen': self.name, 'app_name': constants.App.NAME, 'default_delay': constants.Settings.CHAR_DELAY_SECONDS, } def _parse_args(self, prepared_args): """ Handles the special command-line arguments available for this screen. Although this is a base screen, having these options prepared here can save coding for screens that will not change the default options. See `_usage_options_example` method for documentation on each of the options being parsed here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ for o, a in prepared_args[0]: # optlist, args if o in ("-h", "--help"): self.usage() self.screen_exit() elif o in ("-d", "--delay"): try: # make sure argument is a valid value (float) self.delay = float(a) except: raise exception.InvalidOptionException("delay") elif o in ("-p", "--path"): # make sure argument is a valid value (existing path) self.path = a if not os.path.exists(self.path): raise exception.PathNotFoundException(self.path, _("Make sure the file or directory exists.")) else: # this should never happen! raise Exception(_("Unhandled option. See --help for details.")) # last validations if self.path in (None, ''): raise exception.InvalidOptionException("path", _("It is mandatory option"), help=self._message_no_path()) def _recurse_to_exec(self, path, func, filetype=''): """ Executes a function for each file found recursively within the specified path. Arguments: * path: the path to be recursively checked (directory) * func: the function to be executed with the file(s) * filetype: to filter for a specific filetype """ try: if os.path.isdir(path): for item in os.listdir(path): f = os.path.join(path, item) self.log("checking %s..." % f) if os.path.isdir(f): if not item.startswith('.'): self._recurse_to_exec(f, func, filetype) elif f.endswith(filetype) and not self._is_path_binary(f): func(f) elif path.endswith(filetype) and not self._is_path_binary(path): func(path) except: # # In case of IOErrors, assume this is true for simplicity reasons # as the file should be ignored for screen saver operations. # return def _recurse_to_list(self, path, filetype=''): """ Returns a list of all files within directory in "path" Arguments: * path: the path to be recursively checked (directory) * filetype: to filter for a specific filetype """ result = [] self._recurse_to_exec(path, result.append, filetype) return result def _is_path_binary(self, path): """ Returns True if the given path corresponds to a binary, or, if by an reason, the file can not be accessed or opened. For the merit of being a binary file (i.e., termsaver will not be able to handle it), it is safe enough to consider the above True, as any files in this situation will be simply skipped, avoiding weird errors being thrown to the end-user. Arguments: path: the file location """ CHUNKSIZE = 1024 f = None try: f = open(path, 'rb') except: # # In case of IOErrors, assume this is true for simplicity reasons # as the file should be ignored for screen saver operations. # return True try: while True: chunk = f.read(CHUNKSIZE) if '\0' in chunk: # found null byte return True if len(chunk) < CHUNKSIZE: break # done except: # # In case of IOErrors, assume this is true for simplicity reasons # as the file should be ignored for screen saver operations. # return True finally: if f: f.close() return False def _message_no_path(self): """ Defines a method to be overriden by inheriting classes, with the purpose to display extra help information for specific errors. """ return "" termsaver-0.2/termsaverlib/screen/base/__init__.py0000664000175000017500000002777212111143523022672 0ustar brunobruno00000000000000############################################################################### # # file: __init__.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module holds base classes that are used by all screens within termsaver application. Each individual "screen" represents a unique screensaver that can be triggered by termsaver. The base classes available in this package are: * `ScreenBase`: the most basic screen class, which will handle simple interaction with the terminal. * `filereader.FileReaderBase`: handles screens that require recursive directory scanning for files to be printed out * `urlfetcher.UrlFetcherBase`: handles screens that require Internet connectivity. * `urlfetcher.SimpleUrlFetcherBase`: similar as `UrlFetcherBase`, with simpler options (to avoid overhead to build your own argument parsing, and usage documentation) * `rssfeed.RSSFeedScreenBase`: handles RSS parsing from Internet. * `rssfeed.SimpleRSSFeedScreenBase`: similar as `RSSFeedScreenBase`, with simpler options (to avoid overhead to build your own argument parsing, and usage documentation) Build your own screen ===================== It is very simple to inherit from these base classes and create your own screen. See some of the examples implemented here already. Basically, you will need to: * define a name and description for your screen (class instantiation) and keep them as short as possible (avoid too much typing) * if applicable, define your command-line usage guidelines and options (see `cli_opts`), if appropriate and override `_parse_args` method. Create your help/usage text by overriding the `_usage_options_example` method. * build your action by overriding the `_run_cycle` method, if applicable (the base class will be triggered by the `autorun` method that loops indefinitely or until there is a keyboard interruption (ctrl+C). Before you start, though, I strongly advise you to check out the code here thoroughly, to avoid reinventing the wheel in parts that are already covered. Additionally, consistency is important, so try to keep the same concept of how things are done here... Well, if you have better idea, I am very opened to adapt (but then instead of making a mess, we would change it all to be still consistent). """ # # Python built-in modules # import os import getopt import sys # # Internal modules # from termsaverlib import common, constants, exception from termsaverlib.screen.helper import ScreenHelperBase from termsaverlib.i18n import _ class ScreenBase(ScreenHelperBase): """ This is the main screen that all screens must inherit in order to be part of the screensaver list, accessible with termsaver command-line options. When inheriting this to your own screen, remember to override the following methods: * `_run_cycle`: define here the algorithm to display a text-based look-alike screensaver. See other classes for example on how to use this. * `_usage_options_example`: print out here the options and examples on how to use your screen. See other classes for examples on how to use this. * `_parse_args`: from a properly parsed (using getopt) argument list, customize the configuration of your screen accordingly That's all you need to do! Additionally, you can also call the following helper methods: * `screen_exit`: if by any reason you need to close the application (remember, in most cases, you can just rely on throwing exceptions that are understood by termsaver application, available in `termsaverlib.exception` module) * `log` : if you need to write anything on screen before or after a screen cycle, you can do it in style by calling this method, which will inform the screen as a prefix to the message being displayed on screen. You can also use the following optional property: * `cleanup_per_cycle`: Defines if the screen should be cleaned up for every rotation cycle (new file). IMPORTANT: All other methods are not to be tempered with! """ name = '' """ Defines the name of the screen. """ description = '' """ Defines the description (short) of the screen. """ cli_opts = {} """ Defines the getopt format command-line options of the screen. It should be an object in the following structure: cli_opts = { 'opts': 'h', 'long_opts': ['help',], } """ cleanup_per_cycle = False """ Defines if the screen should be cleaned up for every rotation cycle (new file). """ def __init__(self, name, description, cli_opts): """ The basic constructor of this class. You need to inform basic information about your screen: * `name`: describes the name of the screen (try to keep it short, and/or abbreviated, as much as possible) * `description`: a brief (very brief) description of what the screen does (if you need to write more documentation about it, you can rely on man docs for that) * `cli_opts`: the command line options that will be available for your screen (use getopt formatting) """ self.name = name self.description = description self.cli_opts = cli_opts def autorun(self, args, loop=True): """ The accessible method for dynamically running a screen. This method will basically parse the arguments, prepare them with the method `_parse_args` that is inherited in sub-classes, and with the property `cli_opts` that holds the formatting of the arguments. Once all is ready to go, this will call the `_run_cycle` method, which is filled in the sub-classes with the algorithms to display text on screen to behave as a screensaver. The arguments of this method are: * args: (MANDATORY) the arguments passed when termsaver is executed from command-line. See `termsaver` script for details. * loop: (OPTIONAL) defines if termsaver should be executing on an infinite looping (goes on until the keyboard interrupt (Ctrl+C) is pressed), or not. This is up to the screen action (or end-user through configuable setting) to decide. """ # prepare values and validate if not args: args = '' if not self.cli_opts \ or 'opts' not in self.cli_opts.keys() \ or not self.cli_opts['opts']: self.cli_opts['opts'] = '' if not self.cli_opts['long_opts']: self.cli_opts['long_opts'] = [] else: if not type(self.cli_opts['long_opts']) is list or \ [type(i) == str for i in self.cli_opts['long_opts']] \ != [True for __ in range(len(self.cli_opts['long_opts']))]: # # Don't worry too much about errors here. This is supposed to # help developers while programming screens for this app. # raise Exception("Value of 'long_opts' in cli_opts dict MUST "\ "be a list of strings.") try: self._parse_args(getopt.getopt(args, self.cli_opts['opts'], self.cli_opts['long_opts'])) except getopt.GetoptError, e: raise exception.InvalidOptionException("", str(e)) # execute the cycle self.clear_screen() while(loop): try: self._run_cycle() except KeyboardInterrupt, e: # # do some cleanup if applicable # self._on_keyboard_interrupt() raise e # Clear screen if appropriate if self.cleanup_per_cycle: self.clear_screen() def _run_cycle(self): """ Executes a cycle of this screen. This base class actually does not hold any special actions to begin with, but executing it from inheriting classes is also a good practice, to allow future implementations that must be taken from a base class. """ pass @staticmethod def usage_header(): """ Simply prints a header information, used with the `usage` method. See also `usage` method for details. """ print """%(app_title)s v.%(app_version)s - %(app_description)s. """ % { 'app_title': constants.App.TITLE, 'app_version': constants.App.VERSION, 'app_description': constants.App.DESCRIPTION, } @staticmethod def usage_footer(): """ Simply prints a footer information, used with the `usage` method. See also `usage` method for details. """ print """-- See more information about this project at: %(url)s Report bugs to authors at: %(source_url)s """ % { 'url': constants.App.URL, 'source_url': constants.App.SOURCE_URL, } def _usage_options_example(self): """ Describe here the options and examples of your screen. See some examples of already implemented base screens so you can write similar stuff on your own, and keep consistency. """ pass def usage(self): """ Defines the usage information that is presented when a user hits the help option.You should not directly override this method, instead, just override the protected method `_usage_options_example`, created for this purpose. All other stuff will be defined by the `usage_header` and `usage_footer` methods. """ # header self.usage_header() print _("""Screen: %(screen)s Description: %(description)s Usage: %(app_name)s %(screen)s [options]""") % { 'app_name': constants.App.NAME, 'screen': self.name, 'description': self.description, } # any additional info in between (see other classes for reference) self._usage_options_example() #footer self.usage_footer() def _parse_args(self, prepared_args): """ (protected) MUST be overriden in inheriting classes, to deal with special arguments that will customize values for them. """ pass def screen_exit(self, error=0): """ Exits the screen (and finishes the application) with a specific error. If none is informed, it exits as successful (error 0). """ sys.exit(error) def log(self, text): """ Prints a log message on screen in the format: %(app_name)s.%(screen)s: %(message)s """ print "%s.%s: %s" % (constants.App.NAME, self.name, text) def _on_keyboard_interrupt(self): """ Executes extra commands if the keyboard interrupt exception happened while running a cycle. """ passtermsaver-0.2/termsaverlib/screen/rfc.py0000664000175000017500000001016111741736000020761 0ustar brunobruno00000000000000############################################################################### # # file: rfc.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ A simple screen that fetches documents from RFC (Request for Comments). The screen class available here is: * `RFCScreen` """ # # Python built-in modules # import random # # Internal modules # from termsaverlib.screen.base.urlfetcher import SimpleUrlFetcherBase from termsaverlib.i18n import _ class RFCScreen(SimpleUrlFetcherBase): """ A simple screen that fetches documents from RFC (Request for Comments). Request for Comments (RFC) is a memorandum published by the Internet Engineering Task Force (IETF) describing methods, behaviors, research, or innovations applicable to the working of the Internet and Internet- connected systems. More information about RFC at Wikipedia: http://en.wikipedia.org/wiki/Request_for_Comments This screen basically does the same as its super class, `SimpleUrlFetcherBase`, with a simple difference that it must randomize the URL to be fetched in every screen cycle. This is done by overriding the `run` command. The list of valid RFCs, according to Wikipedia, are listed in `valid_rfc`. Although this may vary in time, small out-of-date information will still not affect the main purpose of this screen. """ valid_rfc = [ 768, 791, 792, 793, 826, 854, 855, 862, 863, 864, 868, 903, 1034, 1035, 1036, 1058, 1059, 1087, 1112, 1119, 1149, 1157, 1176, 1294, 1305, 1321, 1350, 1436, 1441, 1459, 1730, 1777, 1855, 1889, 1918, 1939, 1945, 1948, 1950, 1951, 1952, 1964, 1991, 2080, 2119, 2131, 2177, 2195, 2228, 2246, 2251, 2252, 2253, 2254, 2255, 2256, 2326, 2327, 2328, 2351, 2362, 2397, 2407, 2408, 2409, 2440, 2445, 2453, 2460, 2549, 2570, 2606, 2616, 2740, 2743, 2744, 2810, 2811, 2812, 2813, 2821, 2822, 2853, 2865, 2866, 2965, 2974, 3022, 3031, 3056, 3080, 3162, 3261, 3284, 3286, 3315, 3339, 3376, 3401, 3402, 3403, 3404, 3405, 3501, 3530, 3720, 3783, 3801, 3977, 4213, 4217, 4271, 4287, 4251, 4291, 4353, 4408, 4422, 4541, 4575, 4579, 4634, 4646, 4787, 4960, 5023, 5533, 5969, 6455, 937, 951, 959, ] """ Extracted from Wikipedia: http://en.wikipedia.org/wiki/List_of_RFCs on 2012-02-28, 02:11 AM """ url_format = "http://tools.ietf.org/rfc/rfc%d.txt" """ The URL format that can return a text version of a specific RFC number. """ def __init__(self): """ The constructor of this class, using most default values from its super class, `SimpleUrlFetcherBase`. """ SimpleUrlFetcherBase.__init__(self, "rfc", _("randomly displays RFC contents"), "localhost") # base class require a URL def _run_cycle(self): """ Executes a cycle of this screen. Overriden from its superclass because it needs to must randomize the URL to be fetched in every screen cycle. """ # Randomize next URL to fetch from one of the valid list self.url = self.url_format % self.valid_rfc[ random.randint(0, len(self.valid_rfc) - 1)] data = self.fetch(self.url) self.clear_screen() self.typing_print(data) termsaver-0.2/termsaverlib/screen/jokes4all.py0000664000175000017500000000573311741736000022110 0ustar brunobruno00000000000000############################################################################### # # file: jokes4all.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ Simple screensaver that displays recent jokes from http://jokes4all.net website, from its hourly updated RSS feed. See additional information in the class itself. The screen class available here is: * `Jokes4AllRSSFeedScreen` """ # # Internal modules # from termsaverlib.screen.base.rssfeed import SimpleRSSFeedScreenBase from termsaverlib.i18n import _ class Jokes4AllRSSFeedScreen(SimpleRSSFeedScreenBase): """ Simple screensaver that displays recent jokes from http://jokes4all.net website, from its hourly updated RSS feed. RSS Feed Screen configuration: * sleep between items: 30 seconds this is to allow people enough time for them to read the joke * clean up each cycle: True this will force the screen to be cleaned (cleared) before each joke is displayed * character display delay: 0.015 a bit faster than traditional speeds, because users are not interested in the char print animation as much. * clean up each item: True this will force the screen to be cleaned (cleared) before each image is displayed * display format: '\n%(description)s\n\n%(pubDate)s %(link)s\n' * center in vertical """ def __init__(self): """ The constructor of this class, using most default values from its super class, `SimpleRSSFeedScreenBase`. NOTE: Maybe NSFW (Not Safe For Work) """ SimpleRSSFeedScreenBase.__init__(self, "jokes4all", _("displays recent jokes from jokes4all.net (NSFW)"), "http://jokes4all.net/rss/360010113/jokes.xml", ["pubDate", "link", "description"], '\n%(description)s\n\n%(pubDate)s %(link)s\n', 0.015 ) # set defaults for this screen self.sleep_between_items = 30 self.line_delay = 0 self.cleanup_per_item = True self.cleanup_per_cycle = True self.center_vertically = True termsaver-0.2/termsaverlib/screen/randtxt.py0000664000175000017500000001431211743754673021717 0ustar brunobruno00000000000000############################################################################### # # file: randtxt.py # # Purpose: holds base classes used by screens in termsaver # refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ Simple screensaver that displays a text in random position on screen. See additional information in the class itself. The screen class available here is: * `RandTxtScreen` """ import time from termsaverlib.screen.base import ScreenBase from termsaverlib.screen.helper.typing import TypingHelperBase from termsaverlib.screen.helper.position import PositionHelperBase from termsaverlib import constants, exception from termsaverlib.i18n import _ class RandTxtScreen(ScreenBase, TypingHelperBase, PositionHelperBase): """ Simple screensaver that displays a text in random position on screen. This screen offers the additional options to customize its behavior: * `delay`: Defines the freezing time for a word to be displayed on screen, before a next randomization (cycle). If never changed by command-line options, it will assume the value of `FREEZE_WORD_DELAY` * `word`: defines the word to be displayed on screen for files """ word = '' """ Holds the word to be displayed on screen """ freeze_delay = 0 """ Defines the freezing time for a word to be displayed on screen, before a next randomization (cycle). If never changed by command-line options, it will assume the value of `FREEZE_WORD_DELAY`. """ FREEZE_WORD_DELAY = 3 """ A default freezing time for a word to be displayed on screen, before a next randomization (cycle). Its value is set to 3 seconds. """ def __init__(self): """ Creates a new instance of this class. """ ScreenBase.__init__(self, "randtxt", _("displays word in random places on screen"), {'opts': 'hw:d:', 'long_opts': ['help', 'word=', 'delay=']}, ) self.word = constants.App.TITLE self.delay = 0.01 self.line_delay = 0 self.cleanup_per_cycle = True self.freeze_delay = self.FREEZE_WORD_DELAY def _run_cycle(self): """ Executes a cycle of this screen. The actions taken here, for each cycle, are as follows: * randomize text position vertically and horizontally * print using `typing_print` """ # calculate random position based on screen size self.get_terminal_size() txt = self.randomize_text_vertically( self.randomize_text_horizontally(self.word)) self.typing_print(txt) time.sleep(self.freeze_delay) def _usage_options_example(self): """ Describe here the options and examples of this screen. The method `_parse_args` will be handling the parsing of the options documented here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ print _(""" Options: -w, --word Sets the word to be displayed default is the name of this application (if you need to use spaces, don't forget to place the word with quotes) -d, --delay Sets how long the word will be displayed before randomized again. Default is %(default_delay)s second(s) -h, --help Displays this help message Example: $ %(app_name)s %(screen)s This will trigger the screensaver to display the default word %(app_title)s in random locations of the screen $ %(app_name)s %(screen)s -w FooBar This will trigger the screensaver to display the default word FooBar in random locations of the screen """) % { 'app_name': constants.App.NAME, 'app_title': constants.App.TITLE, 'screen': self.name, 'default_delay': self.FREEZE_WORD_DELAY, } def _parse_args(self, prepared_args): """ Handles the special command-line arguments available for this screen. Although this is a base screen, having these options prepared here can save coding for screens that will not change the default options. See `_usage_options_example` method for documentation on each of the options being parsed here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ for o, a in prepared_args[0]: # optlist, args if o in ("-h", "--help"): self.usage() self.screen_exit() elif o in ("-d", "--delay"): try: # make sure argument is a valid value (float) self.freeze_delay = float(a) except: raise exception.InvalidOptionException("delay") elif o in ("-w", "--word"): # make sure argument is a valid value if a in (None, ''): raise exception.InvalidOptionException("word") self.word = a else: # this should never happen! raise Exception(_("Unhandled option. See --help for details.")) termsaver-0.2/termsaverlib/screen/clock.py0000664000175000017500000001756512111161173021314 0ustar brunobruno00000000000000############################################################################### # # file: clock.py # # Purpose: refer to python doc for documentation details. # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module contains a simple screen that displays current time on terminal. See additional information in the class itself. The screen class available here is: * `ClockScreen` """ # # Python mobdules # import datetime import time # # Internal modules # from termsaverlib.screen.base import ScreenBase from termsaverlib.screen.helper.position import PositionHelperBase from termsaverlib import common from termsaverlib.i18n import _ class ClockScreen(ScreenBase, PositionHelperBase): """ Simple screen that displays the time on the terminal window. The ascii font used was retrieved from Figlet application (http://www.figlet.org/). From its base classes, the functionality provided here bases on the settings defined below: * clean up each cycle: True this will force the screen to be cleaned (cleared) before each new cycle is displayed """ ampm = False """ Defines the format of the datetime to be displayed. """ cseparator = ":" """ Do not change this (if you do, change also its ASCII representation) """ show_separator = True """ Defines if the clock separator should be displayed """ digmap = { '0': ' ___ \n / _ \ \n| | | |\n| |_| |\n \___/ \n \n', '1': ' _ \n / | \n | | \n | | \n |_| \n \n', '2': ' ____ \n|___ \ \n __) |\n / __/ \n|_____|\n \n', '3': ' _____ \n|___ / \n |_ \ \n ___) |\n|____/ \n \n', '4': ' _ _ \n| || | \n| || | \n|__ | \n |_| \n \n', '5': ' ____ \n| ___| \n|___ \ \n ___) |\n|____/ \n \n', '6': ' __ \n / /_ \n| \'_ \ \n| (_) |\n \___/ \n \n', '7': ' _____ \n|___ |\n / / \n / / \n /_/ \n \n', '8': ' ___ \n ( _ ) \n / _ \ \n| (_) |\n \___/ \n \n', '9': ' ___ \n / _ \ \n| (_) |\n \__, |\n /_/ \n \n', ':': ' \n _ \n (_) \n _ \n (_) \n \n', 'm': ' \n _ _ _ \n| |\n| | | |\n|_|_|_|\n \n', 'p': ' \n _ __ \n| `_ \ \n| |_) |\n| .__/ \n|_| \n', 'a': ' \n __ _ \n / _` |\n| (_| |\n \__,_|\n \n', ' ': ' \n \n \n \n \n \n', } """ Holds the ascii characters to be used by this screen. It is the simplification of: ___ _ ____ _____ _ _ ____ __ _____ ___ ___ / _ \ / ||___ \ |___ / | || | | ___| / /_ |___ | ( _ ) / _ \ _ _ _ _ _ __ __ _ | | | || | __) | |_ \ | || |_ |___ \ | '_ \ / / / _ \ | (_) |(_) | | | `_ \ / _` | | |_| || | / __/ ___) |__ _| ___) || (_) | / / | (_) | \__, | _ | | | | | |_) | | (_| | \___/ |_||_____||____/ |_| |____/ \___/ /_/ \___/ /_/ (_) |_|_|_| | .__/ \__,_| |_| Extracted from standard font of Figlet (http://www.figlet.org/) """ def __init__(self): """ The constructor of this class. """ ScreenBase.__init__(self, "clock", _("displays a digital clock on screen"), {'opts': 'hm', 'long_opts': ['help', 'ampm']}, ) self.cleanup_per_cycle = True def _run_cycle(self): """ Executes a cycle of this screen. """ # calculate random position based on screen size self.get_terminal_size() date_time = datetime.datetime.now() text = """ %s %s """ % ( date_time.strftime('%A, %%d%%s %B %Y') % (date_time.day, common.get_day_suffix(date_time.day)), self.get_ascii_time(date_time), ) text = self.center_text_horizontally(text) text = self.center_text_vertically(text) print text sleep_time = 1 # usually one cycle per second if self.ampm: # special case to show blinking separator sleep_time = 0.7 time.sleep(sleep_time) def _usage_options_example(self): """ Describe here the options and examples of this screen. The method `_parse_args` will be handling the parsing of the options documented here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ print _(""" Options: -h, --help Displays this help message -m, --ampm Shows the clock in am/pm 12-hour format, without seconds. """) def _parse_args(self, prepared_args): """ Handles the special command-line arguments available for this screen. Although this is a base screen, having these options prepared here can save coding for screens that will not change the default options. See `_usage_options_example` method for documentation on each of the options being parsed here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ for o, __ in prepared_args[0]: # optlist, args if o in ("-h", "--help"): self.usage() self.screen_exit() elif o in ("-m", "--ampm"): self.ampm = True else: # this should never happen! raise Exception(_("Unhandled option. See --help for details.")) def get_ascii_time(self, date_time): """ Returns the ASCII representation of a date. """ # define clock string based on options (12/24) if self.ampm: hour = int(date_time.strftime('%H')) suffix = "am" if hour >= 12: suffix = "pm" # fix the hour value into modulus of 12 hour = hour % 12 # fix the zero hour value if hour == 0: hour = 12 # shows/hides separator for a blinking effect separator = "" if self.show_separator: separator = self.cseparator self.show_separator = False else: separator = " " self.show_separator = True clock = "%s%s%s%s" % (hour, separator, date_time.strftime('%M'), suffix) else: # 24hs format includes seconds clock = date_time.strftime('%H' + self.cseparator + '%M' + self.cseparator + '%S') items = [] for c in clock: items.append(self.digmap[c]) output = '' for i in range(6): # loop lines of chars - Increased to six for extra font line temp = '' for item in items: temp += item.split('\n')[i] output += temp + '\n' return output termsaver-0.2/termsaverlib/screen/__init__.py0000664000175000017500000000732312120355760021756 0ustar brunobruno00000000000000############################################################################### # # file: __init__.py # # Purpose: refer to python doc for documentation details. # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module itself holds simple functions to better handle the screens available within this package. Available functions: * `get_available_screens`: Gets the available screens in this package for dynamic instantiation. * `build_screen_usage_list`: Builds a simple string with a list of all available screens, to be used in usage() methods. The modules available in this package are: * `asciiartfarts`: displays ascii images from asciiartfarts.com * `clock`: displays a digital clock * `sysmon`: displays a graphic for CPU/Mem usage * `jokes4all`: displays recent jokes from jokes4all.net * `programmer`: displays source code in typing animation * `quotes4all`: displays recent quotes from quotes4all.net * `randtxt`: displays word in random places on screen * `rfc`: randomly displays RFC contents * `rssfeed`: displays rss feed information * `urlfetcher`: displays url contents with typing animation * `matrix`: displays a matrix movie alike screensaver This also contains the following sub-packages: * `base`: holds base classes that are used by all screens within termsaver application * `helper`: holds all helper classes used by termsaver screens, to add reusable functionality to them """ # # Python built-in modules # import os import inspect # # Internal modules # from termsaverlib.screen import base from termsaverlib.plugins import get_available_plugin_screens def get_available_screens(): """ Gets the available screens in this package for dynamic instantiation. """ ignore_list = ['__init__.py'] screens = [] for module in os.listdir(os.path.join(os.path.dirname(__file__))): if module in ignore_list or module[-3:] != '.py': continue module_name = module[:-3] m = __import__(module_name, globals(), locals()) # loop module's classes in search for the ones inheriting Screenbase # and ignore name (no need) with underscore variable for name, obj in inspect.getmembers(m): if inspect.isclass(obj) and issubclass(obj, base.ScreenBase) \ and not name.endswith("Base"): screens.append(obj) # find plugins screens.extend(get_available_plugin_screens()) return screens def build_screen_usage_list(): """ Builds a simple string with a list of all available screens, to be used in usage() methods. """ screens = get_available_screens() screen_space = max([len(s().name) for s in screens]) return '\n '.join([''.join([s().name, ' ', ' ' * (screen_space - len(s().name) + 1), s().description]) for s in get_available_screens()]) termsaver-0.2/termsaverlib/screen/starwars.py0000664000175000017500000000402612111164424022055 0ustar brunobruno00000000000000############################################################################### # # file: rfc.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ A simple screen that fetches documents from RFC (Request for Comments). The screen class available here is: * `RFCScreen` """ # # Python built-in modules # import os # # Internal modules # from termsaverlib.screen.base import ScreenBase from termsaverlib.screen.helper.position import PositionHelperBase from termsaverlib.i18n import _ class StarWarsScreen(ScreenBase, PositionHelperBase): """ """ frame_size = 14 def __init__(self): """ The constructor of this class, using most default values from its super class, `SimpleUrlFetcherBase`. """ ScreenBase.__init__(self, "starwars", _("runs the asciimation Star Wars movie"), {'opts': 'h', 'long_opts': ['help',]}, ) self.cleanup_per_cycle = False def _run_cycle(self): """ """ # # confirm first that we are entering telnet (hard to close) # # FIXME os.system("telnet towel.blinkenlights.nl") termsaver-0.2/termsaverlib/screen/sysmon.py0000664000175000017500000003421412120614444021543 0ustar brunobruno00000000000000# -*- coding: utf-8 -*- ############################################################################### # # file: sysmon.py # # Purpose: refer to python doc for documentation details. # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module contains a simple screen that displays CPU/MEM charts. See additional information in the class itself. The screen class available here is: * `SysmonScreen` """ # # Python mobdules # import time import re import os # # Internal modules # from termsaverlib.screen.base import ScreenBase from termsaverlib.screen.helper.position import PositionHelperBase from termsaverlib import constants, exception from termsaverlib.i18n import _ class SysmonScreen(ScreenBase, PositionHelperBase): """ Simple screen that displays CPU/MEM usage charts on a terminal window. From its base classes, the functionality provided here bases on the settings defined below: * clean up each cycle: False The screen will be cleared manually after the CPU calculation is completed (it requires a sleep) """ path = None """ Defines the path of the file containing a monitoring value, from 0 to 100. """ info = { 'db': [ # # store data in format: # {'time': ??, 'cpu': ??, 'mem': ??, 'extra': ??} # ], 'total_mem': 0, 'max_cpu': 0, 'max_mem': 0, 'max_extra': 0, # for an external path } """ Registers the history of CPU/MEM usage, used to build the charts """ # # Graphical elements # pie_chart = ['○', '◔', '◑', '◕', '●'] """ Holds the unicode symbols for pie chart representation of percentage """ block = [' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█', '█'] """ Holds the block unicode symbolds used to draw the charts """ axis_corner = "└" """ Represents the unicode symbol for the axis corner in the xy chart """ axis_h = "─" """ Represents the unicode symbol for the horizontal axis in the xy chart """ axis_v = "│" """ Represents the unicode symbol for the vertical axis in the xy chart """ adjust = True """ Defines if the graphics should hold a 0-100 count or adjust to the highest value available """ def __init__(self): """ The constructor of this class. """ ScreenBase.__init__(self, "sysmon", _("displays a graphical system monitor"), {'opts': 'hd:np:', 'long_opts': ['help', 'delay=', 'no-adjust', 'path=']}, ) self.delay = 0.5 # # Due to a time delay to calculate CPU usage # we need to clear the screen manually # self.cleanup_per_cycle = False def _run_cycle(self): """ Executes a cycle of this screen. """ # calculate random position based on screen size self.get_terminal_size() # update info data if self.path: # # run the flow for external path # self.update_stats_extra() if self.geometry['x'] > 16: # just to avoid unexpected exceptions title = "%s: %s" % (_('Monitoring'), (self.path[:(self.geometry['x'] - 16)] + (self.path[(self.geometry['x'] - 16):] and '...'))) else: title = _("Monitoring file") txt = self.get_xy_chart(title, 'extra') txt += self.center_text_horizontally( "\n Load: %s%% %s " % ( ("%02d" % self.info['db'][-1]['extra']), self.get_chart(self.info['db'][-1]['extra']), ) ) else: # # run the flow for CPU/Mem as default # self.update_stats() txt = self.get_xy_chart("CPU Monitor", 'cpu') txt += "\n" txt += self.get_xy_chart("MEM Monitor", 'mem') txt += self.center_text_horizontally( "\n%s CPU: %s%% %s MEM: %s%% (total %sMB)" % ( self.get_chart(self.info['db'][-1]['cpu']), ('%.1f' % self.info['db'][-1]['cpu']), self.get_chart(self.info['db'][-1]['mem']), self.info['db'][-1]['mem'], int(self.info['total_mem']) )) # # Due to a time delay to calculate CPU usage # we need to clear the screen manually # self.clear_screen() # just print the whole text print txt # # The sleep happens here in the CPU calculation instead # #time.sleep(self.delay) def update_stats_extra(self): """ Updates the info property with latest information on an extra path, defined by --path argument option Note: This also takes care of sleep (defined by delay property) """ f = open(self.path, 'r') try: val = int(f.read()) except: raise exception.TermSaverException( _('The file does not contain an integer as expected.')) if val < 0 or val > 100: raise exception.TermSaverException( _('The file contains invalid data (must be between 0 and 100).')) f.close() # cut the data to keep only recent values self.info['db'] = self.info['db'][-(self.geometry['x'] - 5):] max_extra = 0 for item in self.info['db']: if item['extra'] > max_extra: max_extra = item['extra'] self.info['max_extra'] = max_extra self.info['db'].append( { 'time': time.time(), 'extra': val, } ) time.sleep(self.delay) def update_stats(self): """ Updates the info property with latest information on CPU and MEM usage. Note: This also takes care of sleep (defined by delay property) """ # TODO - Implement similar features for Windows/Mac OS # maybe consider psutil package if os.name != "posix": raise exception.TermSaverException(help_msg="OS is not supported!") # memory info re_parser = re.compile(r'^(?P\S*):\s*(?P\d*)\s*kB') mem_info = {} for line in open('/proc/meminfo'): match = re_parser.match(line) if not match: continue # skip lines that don't parse key, value = match.groups(['key', 'value']) if key not in ('MemTotal', 'MemFree'): continue mem_info[key] = int(value) # cpu info def getTimeList(): statFile = file("/proc/stat", "r") timeList = statFile.readline().split(" ")[2:6] statFile.close() for i in range(len(timeList)) : timeList[i] = int(timeList[i]) return timeList def deltaTime() : x = getTimeList() time.sleep(self.delay) y = getTimeList() for i in range(len(x)) : y[i] -= x[i] return y dt = deltaTime() cpu = 100 - (dt[len(dt) - 1] * 100.00 / sum(dt)) self.info['total_mem'] = mem_info['MemTotal'] / 1024 # insert into history data self.info['db'].append( { 'time': time.time(), 'cpu': cpu, 'mem': (mem_info['MemTotal'] - mem_info['MemFree']) * 100 / mem_info['MemTotal'] } ) # cut the data to keep only recent values self.info['db'] = self.info['db'][-(self.geometry['x'] - 5):] # recalculate the cpu ceiling value max_cpu, max_mem = 0, 0 for item in self.info['db']: if item['cpu'] > max_cpu: max_cpu = item['cpu'] if item['mem'] > max_mem: max_mem = item['mem'] self.info['max_cpu'] = max_cpu self.info['max_mem'] = max_mem def format_time(self, epoch): """ Formats a given epoch time into a very simplistic form compared to current time (eg. 1h meaning 1 hour ago). """ elapsed = time.time() - epoch if elapsed > 3600: return "%.1fh" % (elapsed/3600.0) elif elapsed > 60: return "%.1fm" % (elapsed/60.0) elif elapsed > 1: return "%.1fs" % elapsed else: return "" def get_chart(self, perc): """ returns a pie chart unicode depending on the percentage (eg. 100%) given. """ pos = int(perc * 5 / 100) if pos < len(self.pie_chart) and pos >= 0: return self.pie_chart[pos] else: return "" def get_xy_chart(self, title, key): ceiling = 100 if self.adjust: ceiling = self.info['max_' + key] ysize = int((self.geometry['y'] - 13)/2) # remove lines used current_position = 0 txt = self.align_text_right(title) + "\n" \ + ('%.0f' % ceiling) + "%\n" # create output (11 lines) for y in range(ysize - 1, -1, -1): current_position = 0 txt += " " + self.axis_v for x in range(self.geometry['x'] - 5): # padding if len(self.info['db']) - 1 < x: txt += " " else: current_position += 1 # to keep proportions ratio = 1 if ceiling > 0: ratio = int(self.info['db'][x][key] * ysize / ceiling) # based on number of blocks (10) if ratio >= y + 1: txt += self.block[-1] elif y > 0 and ratio > y: txt += self.block[ratio - y] elif y > 0: txt += self.block[0] else: txt += self.block[1] txt += "\n" txt += " " + self.axis_corner + self.axis_h * (self.geometry['x'] - 5) + "\n" txt += "%s%s%s\n" % (self.format_time(self.info['db'][0]['time']), " " * (current_position - 5), _("now")) return txt def _usage_options_example(self): """ Describe here the options and examples of this screen. The method `_parse_args` will be handling the parsing of the options documented here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ print _(""" Options: -d, --delay Sets the speed of the displaying characters default is 0.5 seconds (advised to keep at least above 0.1). -n, --no-adjust Forces the charts to displays 0 ~ 100%% values, instead of dynamically adjusted values based on current maximum. -p, --path Sets the location of a file to be monitored. The file must only contain a number from 0 to 100, or the screen will not start. This option is optional. -h, --help Displays this help message Example: $ %(app_name)s %(screen)s This will trigger the screensaver to display a dot on screen, with random size increase. $ %(app_name)s %(screen)s -d 5 Overrides the default delay to 5 seconds """) % { 'app_name': constants.App.NAME, 'screen': self.name, } def _parse_args(self, prepared_args): """ Handles the special command-line arguments available for this screen. Although this is a base screen, having these options prepared here can save coding for screens that will not change the default options. See `_usage_options_example` method for documentation on each of the options being parsed here. Additionally, this is dependent on the values exposed in `cli_opts`, passed to this class during its instantiation. Only values properly configured there will be accepted here. """ for o, a in prepared_args[0]: # optlist, args if o in ("-h", "--help"): self.usage() self.screen_exit() elif o in ("-n", "--no-adjust"): self.adjust = False elif o in ("-p", "--path"): # make sure argument is a valid value (existing path) self.path = a if not os.path.exists(self.path): raise exception.PathNotFoundException(self.path, _("Make sure the file exists.")) if not os.path.isfile(self.path): raise exception.InvalidOptionException("--path", _("Make sure it is a file")) elif o in ("-d", "--delay"): try: # make sure argument is a valid value (float) self.delay = float(a) except: raise exception.InvalidOptionException("delay") else: # this should never happen! raise Exception(_("Unhandled option. See --help for details.")) termsaver-0.2/termsaverlib/screen/helper/0000775000175000017500000000000012120627176021122 5ustar brunobruno00000000000000termsaver-0.2/termsaverlib/screen/helper/urlfetcher.py0000664000175000017500000001503011741736000023631 0ustar brunobruno00000000000000############################################################################### # # file: urlfetcher.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ A helper class used for screens that require Internet connectivity. See additional information in the class itself. The helper class available here is: * `URLFetcherHelperBase` """ # # Python built-in modules # from urllib2 import Request, urlopen, URLError, HTTPError import urlparse import time # # Internal modules # from termsaverlib.screen.helper import ScreenHelperBase from termsaverlib import exception, constants from termsaverlib.i18n import _ class URLFetcherHelperBase(ScreenHelperBase): """ A helper class that provides Internet connectivity for termsaver screens. The functionalities available are: * fetch data over the Internet (only text-base) * avoid too many requests at a time (configured at `constants.Settings.FETCH_INTERVAL_SECONDS` For these functionalities, the following methods are publicly available: * `fetch`: for a specified URI, it returns its string contents additionally, this will also set a `raw` property with the data last fetched. * `fix_uri`: uses an algorithm to fix and validate a string as URL format. This should be used to prepare the URL before calling `fetch` method. """ __last_fetched = None """ A flag that defines the EPOCH time when the last fetch occurred, to ensure termsaver application does not keep connecting to the Internet without need See also: `constants.Settings.FETCH_INTERVAL_SECONDS` """ raw = "" """ The raw text data that is fetched using urllib. This can be later manipulated as needed (xml parsing, etc). """ def fix_uri(self, text): """ Validates a text as URL format, also adjusting necessary stuff for a clearer URL that will be fetched here. Code based on Django source: https://code.djangoproject.com/browser/django/trunk/django/forms/ fields.py?rev=17430#L610 Arguments: * text: the URL string that is to be validated and fixed """ if not text: raise exception.UrlException(text, _("URL can not be blank")) try: url_fields = list(urlparse.urlsplit(text)) except ValueError: raise exception.UrlException(text, _("URL does not seem valid")) if not url_fields[0]: # If no URL scheme given, assume http:// url_fields[0] = 'http' if not url_fields[1]: # Assume that if no domain is provided, that the path segment # contains the domain. url_fields[1] = url_fields[2] url_fields[2] = '' # Rebuild the url_fields list, since the domain segment may now # contain the path too. try: url_fields = list(urlparse.urlsplit( urlparse.urlunsplit(url_fields))) except ValueError: raise exception.UrlException(text, _("URL does not seem valid")) if not url_fields[2]: # the path portion may need to be added before query params url_fields[2] = '/' return urlparse.urlunsplit(url_fields) def fetch(self, uri): """ Executes the fetch action toward a specified URI. This will also try to avoid unnecessary calls to the Internet by setting the flag `__last_fetched`. If it can not fetch again, it will simply return the `raw` data that was previously created by a previous fetch. Arguments: * uri: the path to be fetched """ # check if we can fetch again if self.__last_fetched and not self.raw and \ time.time() - self.__last_fetched < \ constants.Settings.FETCH_INTERVAL_SECONDS: return self.raw headers = {'User-Agent': "%s/%s" % (constants.App.NAME, constants.App.VERSION)} # separate possible querystring data from plain URL temp = uri.split('?') url = temp[0] if len(temp) > 1: # old style condition for old python compatibility data = temp[1] else: data = None self.log(_("Connecting to %s ... (this could take a while)") % uri) # execute URL fetch req = Request(url, data, headers) resp = None try: resp = urlopen(req) except HTTPError, e: raise exception.UrlException(uri, _("Fetched URL returned error %d.") % e.code) except URLError, e: raise exception.UrlException(uri, _("Could not fetch URL, because %s") % e.reason) else: self.__last_fetched = time.time() self.raw = resp.read() # make sure the content is not binary (eg. image) if self.__is_response_binary(self.raw): raise exception.UrlException(uri, _("Fetched data is binary.")) finally: if resp: resp.close() return self.raw def __is_response_binary(self, raw): """ Returns True if the given data is binary in nature, and False otherwise For the merit of being a binary file (i.e., termsaver will not be able to handle it), it is safe enough to consider the above True, as any files in this situation will be simply skipped, avoiding weird errors being thrown to the end-user. Arguments: raw: the response data that must be tested for binary values """ return raw.find("\0") > -1 termsaver-0.2/termsaverlib/screen/helper/typing.py0000664000175000017500000000750611741736000023011 0ustar brunobruno00000000000000############################################################################### # # file: typing.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ A helper class used for screens that require more dynamic output to users. See additional information in the class itself. The helper class available here is: * `TypingHelperBase` """ # # Python built-in modules # import sys import time # # Internal modules # from termsaverlib.screen.helper import ScreenHelperBase from termsaverlib import constants class TypingHelperBase(ScreenHelperBase): """ This helper class gives functionality to screens to print out information in a more interactive way, simulating a typing writer machine, based on two main speed control properties: * `delay`: defines the delay for printing out characters of a string * `line_delay`: defines the delay for printing out new lines within a string (sometimes, setting different proportions make a lot of a difference) If no values are defined by the screen itself, default values should be used. The `delay` is set in `constants.Settings.CHAR_DELAY_SECONDS`, and the `line_delay` is 10 times the value of delay. To use this screen helper is pretty straightforward, just call the method: * `typing_print`: this will print the specified text string using the speed controls `delay` and `line_delay`. """ delay = None """ Defines the character printing delay, to give a cool visual of a typing machine. This value is measured in seconds, and default marks are defined in `constants.Settings.CHAR_DELAY_SECONDS`. """ line_delay = None """ Defines the delay imposed to every new line prior to char printing. By default, its value is 10x the `delay`. """ def typing_print(self, text): """ Prints text with standard output to allow side-by-side printing, and give the impression of a typing writer machine. The speed is controlled by properties of this class: `delay` and `line_delay`. Arguments: * text: the text to be printed in typing style Notes: * This also supports new lines (\n) * blank spaces, due to its lack of meaning, are ignored for speed limiting, so they will be flushed all at once. """ # set defaults if self.delay is None: self.delay = constants.Settings.CHAR_DELAY_SECONDS if self.line_delay is None: self.line_delay = 10 * self.delay for line in text.split('\n'): for char in line: sys.stdout.write(char) # only pause if it is not a blank space if char != ' ': time.sleep(self.delay) sys.stdout.flush() # need to re-print the line removed from the split sys.stdout.write('\n') time.sleep(self.line_delay) # specific pause for new lines termsaver-0.2/termsaverlib/screen/helper/xmlreader.py0000664000175000017500000001547711741736000023470 0ustar brunobruno00000000000000############################################################################### # # file: xmlreader.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ A helper class used for screens that require XML handling. See additional information in the class itself. The helper class available here is: * `XMLReaderHelperBase` """ # # Python built-in modules # import os from xml.dom.minidom import parse, Node, parseString # # Internal modules # from termsaverlib.screen.helper import ScreenHelperBase from termsaverlib import exception class XMLReaderHelperBase(ScreenHelperBase): """ This helper class will handle basic XML parsing, not trying to solve all mysteries of the universe here. What we are looking for are main nodes that contain repetitive data, commonly found on a dataset, or RSS feed. More complex handling is not treated at this point, but it might be implemented if the need surfaces. The basic instantiation of this class require you to inform 2 arguments: * `base_node`: Defines the primary node where the data must be retrieved from. * `tags`: Defines which tags within the XML must be parsed to build a list of dictionaries. Those two arguments will give the hint about where is the data and which piece of it you are looking for. For actually getting the data, you will need to: * prepare a raw data (file content, Internet data, etc) into a XML object, named `__doc`; and * parse the XML object into a more convenient list of dictionaries that will be populated in `data` property. To prepare the data, you have 2 options: * `doc_xml_string`: a method that will create a dom xml document from a text string (obviously it must be a XML) * `doc_xml_file`: a method that will create a dom xml document from a file content (obviously it must be a XML) Once you have the XML properly prepared, and stored in `__doc`, you can call the parsing method: * `parse_data`: this will actually execute the action to extract the information you are looking for based on the arguments passed in the instantiation. """ __doc = None """ Holds the xml.dom.minidom document object """ clean_dirt = [] """ Holds a list of strings that will be cleaned up from each result in the XML data, when placing them into the `data` property. This can be pretty handy to remove trailing spaces, new lines, or unwanted HTML tags from the data. """ base_node = None """ Defines the primary node where the data must be retrieved from. """ tags = [] """ Defines which tags within the XML must be parsed to build a list of dictionaries. """ data = None """ Holds a list, created from properly parsing the dom document object in `__doc`, as specified with `base_node` and `tags` filtering. """ def __init__(self, base_node, tags): """ Creates a new instance of this class. Arguments: * `base_node`: Defines the primary node where the data must be retrieved from. * `tags`: Defines which tags within the XML must be parsed to build a list of dictionaries. """ self.base_node = base_node self.tags = tags def parse_data(self): """ Only call this once you have already created the dom document object, by calling either `doc_xml_file` or `doc_xml_string` methods. This will parse the document into a list, much simpler to deal with. On the logic here is done, the list is available in the property `data` """ def get_note_value(node, node_type): result = '' for node2 in node: for node3 in node2.childNodes: if node3.nodeType == node_type: result += node3.data # clean possible dirt for t in self.clean_dirt: # execute a loop here for dealing with multiple occurrences # (such as multiple spaces) while result.find(t) > -1: result = result.replace(t, "") return result if self.__doc is None: raise Exception("""You must parse the raw data, by calling a \ doc_xml_* method to populate the dom document object.""") result = [] for node in self.__doc.getElementsByTagName(self.base_node): temp = {} for tag in self.tags: temp[tag] = get_note_value(node.getElementsByTagName(tag), Node.TEXT_NODE) if not temp[tag]: temp[tag] = get_note_value(node.getElementsByTagName(tag), Node.CDATA_SECTION_NODE) result.append(temp) self.data = result def doc_xml_file(self, path): """ Parses a specified file into a xml.dom.minidom document object, to be used by `parse_data` method later on. This method here will store the result in the private `__doc` property. Arguments: * path: the XML file path that will be parsed into a dom document object. """ if not os.path.exists(path): raise exception.PathNotFoundException(path) try: self.__doc = parse(path) except: raise exception.XmlException(path) def doc_xml_string(self, text): """ Parses a specified string into a xml.dom.minidom document object, to be used by `parse_data` method later on. This method here will store the result in the private `__doc` property. Arguments: * text: the XML string value that will be parsed into a dom document object. """ try: self.__doc = parseString(text) except: raise exception.XmlException(text) termsaver-0.2/termsaverlib/screen/helper/position.py0000664000175000017500000002633412111156203023334 0ustar brunobruno00000000000000############################################################################### # # file: position.py # # Purpose: refer to module documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ A helper class that provides positioning functionality to screens, such as defining a terminal size, and centering information (horizontally or vertically). See additional information in the class itself. The helper class available here is: * `PositionHelperBase` """ # # Python built-in modules # import sys import time import platform import math import random import textwrap # # Internal modules # from termsaverlib.screen.helper import ScreenHelperBase class PositionHelperBase(ScreenHelperBase): """ This helper class provides positioning functionality to the screens, by dealing with the current dimensions of the terminal. There are main methods available here: * `get_terminal_size`: retrieves the current terminal dimensions, width and height, to be stored in local propertiy `geometry`. * `center_text_vertically`: centers a specified text in vertical * `center_text_horizontally`: centers a specified text in horizontal * `randomize_text_vertically`: randomizes a specified text in vertical * `randomize_text_horizontally`: randomizes a specified text in horizontal If the method `get_terminal_size` is never called, all other functionality, relying on terminal dimensions, will just based on a default size, set as 80x25. The main properties available are: * `geometry`: defines the size of the terminal (populated by the `get_terminal_size` method, whenever called. * `position`: defines the current position of the text to be printed, based on usage of other methods that temper with text positioning (eg. `randomize_text_horizontally`) * `changed_geometry`: for every call to `get_terminal_size` method, holds the information if the terminal has changed size or not. """ geometry = { 'x' : 0, 'y' : 0, } """ Defines the current terminal width and height. Its default value is set as 80x25. """ __old_geometry = { 'x' : 0, 'y' : 0, } """ Private property to track changes in the geometry. Refer to `changed_geometry` to identify any terminal size changes. """ changed_geometry = False """ A simple boolean that identifies if the terminal has changed size since the last check with `get_terminal_size`. This is handy to decide what to do with a particular screen (eg: clear and redraw again?). """ position = { 'x' : 0, 'y' : 0, } """ Stores the latest position X-Y axis (width and height) position value after calling the randomizing methods of this class (useful to allow you to know the previous location of the text in the window) """ def fix_text_wrap(self, text): """ Wraps the text to the geometry size, maintaining existing new lines. """ # fail safe if the screen does not properly set geometry if self.geometry['x'] == 0: return text temp = text.split("\n") longest_line = max([len(x) for x in temp]) new_text = [] for l in temp: t = "\n".join(textwrap.wrap(l, width=self.geometry['x'])) # fill in trailing blanks t += " " * (min(longest_line, self.geometry['x']) - min(len(t), self.geometry['x'])) new_text.append(t) return "\n".join(new_text) def center_text_vertically(self, text): """ Returns the text argument with additional new lines, calculated to display the text in the vertical center of the screen. Arguments: * text: the text to be vertically centered """ temp = self.fix_text_wrap(text).split("\n") self.position['y'] = int(math.floor( (self.geometry['y'] - len(temp)) / 2)) return "\n" * self.position['y'] + text def center_text_horizontally(self, text): """ Returns the text argument with additional blank spaces, calculated to display the text in the horizontal center of the screen. Arguments: * text: the text to be horizontally centered """ temp = self.fix_text_wrap(text).split("\n") new_text = "" for t in temp: self.position['x'] = int(math.ceil( (self.geometry['x'] - len(t)) / 2)) new_text += " " * self.position['x'] + t if len(temp) > 1: new_text += "\n" return new_text def align_text_right(self, text): """ Returns the text argument with additional blank spaces, calculated to display the text in the right. Arguments: * text: the text to be aligned """ return " " * (self.geometry['x'] - len(text)) + text def randomize_text_horizontally(self, text): """ Returns the text argument with additional blank spaces, calculated to display the text in a random position of the screen. Arguments: * text: the text to be horizontally randomized """ # find longest line temp = self.fix_text_wrap(text).split("\n") longest_line = max([len(x) for x in temp]) self.position['x'] = random.randint(0, self.geometry['x'] - longest_line) new_text = "" for t in temp: new_text += " " * self.position['x'] + t if len(temp) > 0: new_text += "\n" return new_text def randomize_text_vertically(self, text): """ Returns the text argument with additional new lines, calculated to display the text in a random position of the screen. Arguments: * text: the text to be vertically randomized """ total_lines = len(self.fix_text_wrap(text).split("\n")) self.position['y'] = random.randint(0, max(0, self.geometry['y'] - total_lines)) return "\n" * self.position['y'] + text def get_terminal_size(self): """ Retrieves the screen terminal dimensions, returning a tuple (width, height), and will also store them in internal property `geometry`. Copyright note: This code has been adapted from: http://stackoverflow.com/questions/566746/\ how-to-get-console-window-width-in-python posted by Harco Kuppens, at Jul 1 '11 at 16:23. """ # This is required if you are programming from non-windows platforms # more on this at: http://pydev.org/manual_adv_assistants.html #@PydevCodeAnalysisIgnore def _get_terminal_size_windows(): res = None try: from ctypes import windll, create_string_buffer # stdin handle is -10 # stdout handle is -11 # stderr handle is -12 h = windll.kernel32.GetStdHandle(-12) csbi = create_string_buffer(22) res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) except: return None if res: import struct (_, _, _, _, _, left, top, right, bottom, _, _) = struct.unpack("hhhhHhhhhhh", csbi.raw) sizex = right - left + 1 sizey = bottom - top + 1 return sizex, sizey else: return None def _get_terminal_size_tput(): try: import subprocess proc = subprocess.Popen(["tput", "cols"], stdin = subprocess.PIPE, stdout = subprocess.PIPE) output = proc.communicate(input = None) cols = int(output[0]) proc = subprocess.Popen(["tput", "lines"], stdin = subprocess.PIPE, stdout = subprocess.PIPE) output = proc.communicate(input = None) rows = int(output[0]) return (cols, rows) except: return None def _get_terminal_size_linux(): def ioctl_GWINSZ(fd): try: import fcntl, termios, struct cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) except: return None return cr cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) if not cr: try: fd = os.open(os.ctermid(), os.O_RDONLY) cr = ioctl_GWINSZ(fd) os.close(fd) except: pass if not cr: try: cr = (os.environ['LINES'], os.environ['COLUMNS']) except: return None return int(cr[1]), int(cr[0]) current_os = platform.system() tuple_xy = None if current_os == 'Windows': tuple_xy = _get_terminal_size_windows() if tuple_xy is None: tuple_xy = _get_terminal_size_tput() # needed for window's python in cygwin's xterm! if current_os == 'Linux' or current_os == 'Darwin' or \ current_os.startswith('CYGWIN'): tuple_xy = _get_terminal_size_linux() if tuple_xy is None: tuple_xy = (80, 25) # default value self.geometry['x'], self.geometry['y'] = tuple_xy # store geometry changes if self.__old_geometry == {'x': 0, 'y': 0}: # first time checking geometry self.__old_geometry = self.geometry.copy() self.changed_geometry = False elif self.__old_geometry != self.geometry: self.__old_geometry = self.geometry.copy() self.changed_geometry = True else: self.changed_geometry = False termsaver-0.2/termsaverlib/screen/helper/__init__.py0000664000175000017500000000472611741736000023237 0ustar brunobruno00000000000000############################################################################### # # file: __init__.py # # Purpose: refer to package documentation for details # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This package holds all helper classes used by termsaver screens, to add reusable functionality to them, and help maintain consistency throughout all of them. All helper screens should inherit from the base screen helper `ScreenHelperBase`, documented below. The available classes in this package are: * `ScreenHelperBase`: the main helper class from which all helper classes will inherit from. * `typing.TypingHelperBase`: helper functionality to display typing writer effects for screens. * `urlfetcher.URLFetcherHelperBase`: helper functionalities to give Internet connectivity to screens. * `xmlreader.XMLReaderHelperBase`: helper functionalities to assist on XML parsing. """ # # Python built-in modules # from os import system # # Internal modules # from termsaverlib.common import is_windows class ScreenHelperBase(object): """ This is the main helper class from which all should inherit from. This will also hold most rudimentary functionalities that can be reused by all screens. """ @staticmethod def clear_screen(): """ A simple method that clears the screen. This supports both Windows and Unix base systems. """ if is_windows(): # Execute command for Windows Platform, DOS console __ = system('cls') # Windows prints the output of this call else: # Execute command for Unix based Platform system('clear') termsaver-0.2/termsaverlib/screen/asciiartfarts.py0000664000175000017500000000575411741736000023062 0ustar brunobruno00000000000000############################################################################### # # file: asciiartfarts.py # # Purpose: refer to python doc for documentation details. # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module contains a simple screen that connects to asciiartfarts.com RSS feeds to display ascii arts on screen. See additional information in the class itself. The screen class available here is: * `AsciArtFartsScreen` """ # # Internal modules # from termsaverlib.screen.base.rssfeed import SimpleRSSFeedScreenBase from termsaverlib.i18n import _ class AsciArtFartsScreen(SimpleRSSFeedScreenBase): """ A simple screen that connects to asciiartfarts.com RSS feeds to display ascii arts on screen. From its base classes, the functionality provided here bases on the settings defined below: * sleep between items: 5 seconds not so much time between images * clean up each cycle: True this will force the screen to be cleaned (cleared) before each new cycle is displayed * center in vertical * center in horizontal * clean dirt: HTML
 tags

        * clean up each item: True
          this will force the screen to be cleaned (cleared) before each image
          is displayed
    """

    def __init__(self):
        """
        The constructor of this class, using most default values from its super
        class, `SimpleRSSFeedScreenBase`.

        The display of the ascii arts here are basically based on getting the
        description tag of the RSS feed, that constains a dirty HTML ascii art.

        NOTE: Maybe NSFW (Not Safe For Work)
        """
        super(AsciArtFartsScreen, self).__init__(
            "asciiartfarts",
            _("displays ascii images from asciiartfarts.com (NSFW)"),
            'http://www.asciiartfarts.com/farts.rss',
            ["description"],
            "%(description)s",
        )

        # set defaults for this screen
        self.cleanup_per_cycle = True
        self.sleep_between_items = 5
        self.center_vertically = True
        self.center_horizontally = True
        self.clean_dirt = ['
', '
'] self.cleanup_per_item = True termsaver-0.2/termsaverlib/plugins/0000775000175000017500000000000012120627176020045 5ustar brunobruno00000000000000termsaver-0.2/termsaverlib/plugins/__init__.py0000664000175000017500000001023111744023311022143 0ustar brunobruno00000000000000############################################################################### # # file: __init__.py # # Purpose: refer to python doc for documentation details. # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module itself holds simple functions to better handle the screens available within any plugins installed. Available functions: * `get_available_plugin_screens`: Gets the available screens in sub-directories {plugin}/screen/ for dynamic instantiation. The modules available in this package are installed on-demand, so they are not documented here. How to create plugins ===================== The main script termsaver will execute a dynamic search for all screens that inherit from the `ScreenBase` class. For plugins, however, screens are not placed in the same directory of the built-in screens, but instead into their own location. The directory structure of a plugin should be like: plugins/ | |---- __init__.py | |---- my_plugin/ | | | |---- __init__.py | | | |---- screen | | | | | |---- __init__.py | | | | | |---- my_screen.py | | | | | |---- ... | | | Additional rules before you begin: (1) Naming Conventions The application name must be in the format: termsaver-{plugin-name}, and the directory to be created inside the plugins will be {plugin-name}. Python does not like dashes for module names, so be careful with names you pick. (2) Screens Each screen you design (inside the plugins/{plugin-name}/screen directory) must inherit from the `ScreenBase` class, as this is the base for the application to find the screen, and handle input/output accordingly. This sctructure is designed to immitate termsaver's main structure, so once you get familiar with it, it should be piece of cake to manage your own "space". """ # # Python built-in modules # import os import inspect # # Internal modules # from termsaverlib.screen import base def get_available_plugin_screens(): """ Gets the available screens in this package for dynamic instantiation. """ ignore_list = ['__init__.py'] screens = [] for plugin in os.listdir(os.path.join(os.path.dirname(__file__))): if (os.path.isdir(os.path.join(os.path.dirname(__file__), plugin))): # we are inside the plugin directory, get screens available in # screens directory for module in os.listdir(os.path.join(os.path.dirname(__file__), plugin, "screen")): if module in ignore_list or module[-3:] != '.py': continue module_name = plugin + ".screen." + module[:-3] m = __import__(module_name, globals(), locals(), [module_name.rsplit(".", 1)[-1]]) # loop module's classes in search for the ones inheriting # Screenbase and ignore name (no need) with underscore variable for name, obj in inspect.getmembers(m): if inspect.isclass(obj) and issubclass(obj, base.ScreenBase) and not name.endswith("Base"): screens.append(obj) return screens termsaver-0.2/termsaverlib/i18n.py0000664000175000017500000000355611743306342017525 0ustar brunobruno00000000000000############################################################################### # # file: i18n.py # # Purpose: refer to python doc for documentation details. # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ Handles all internationalization (i18n) functionality for termsaver application """ # # Python build-in modules # import gettext # # Internal modules # from termsaverlib import constants _ = None """ The unicode text dealer for i18n stuff, renamed as an underscore to keep same standards used by gettext. """ def set_app(application_name): """ Defines the application name for the binding text files. """ result = None try: gettext.textdomain(application_name) result = gettext.gettext except: # # If we can not handle i18n, just deal with text as it is # result = lambda x: x # For debugging #raise return result # # Call the default (termsaver app name) # _ = set_app(constants.App.NAME) # # This should be overriden by plugins, as they can have their own i18n files #termsaver-0.2/termsaverlib/__init__.py0000664000175000017500000000314611741736000020474 0ustar brunobruno00000000000000############################################################################### # # file: __init__.py # # Purpose: refer to python doc for documentation details. # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ This module holds all stuff required for termsaver application to work properly The modules available in this package are: * `common`: helper functions used by termsaver code * `constants`: series of configuration constants used by termsaver code * `exceptions`: various exceptions classes to handle termsaver errors * `i18n`: handles internationalization for termsaver application This also contains the following sub-packages: * `screen`: holds all screens accessible by termsaver application. Also holds base and helper classes to ease the implementation of new screens. """ termsaver-0.2/termsaverlib/common.py0000664000175000017500000001101511755123173020225 0ustar brunobruno00000000000000############################################################################### # # file: common.py # # Purpose: holds common helper functions used by termsaver code. # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ Holds common functionality used by termsaver screens. """ # # Python build-in modules # import os import sys import traceback import HTMLParser import subprocess import re def is_windows(): """ Returns True if the environment is Microsoft Windows. """ return sys.platform == "win32" def prettify_exception(ex): """ Outputs the exception with its stack trace within separator lines. """ print """ =================================== Exception: (%s) %s %s =================================== """ % (ex.__class__.__name__, ex.message, traceback.format_exc()) def get_app_dir(): """ Retrieves the termsaver main directory based on current operating system. For Windows machines, this should be something like: \Documents and Settings\\Application Data\termsaver For Unix machines, it will be: /home//.termsaver/ """ if is_windows(): path = os.path.join(os.environ['APPDATA'], "termsaver") else: path = os.path.join(os.environ['HOME'], ".termsaver") # create if applicable if not os.path.exists(path): # permission errors here will just propagate error os.mkdir(path) return path def get_temp_dir(): """ Retrieves the temporary based on current operating system. For Windows machines, this should be something like: \Documents and Settings\\Local Settings\Temp For Unix machines, it will be: /tmp/ """ if is_windows(): path = os.environ['TMP'] else: path = "/tmp" return path def unescape_string(escaped_text): """ Unescape strings. This is useful for cases when data that needs to be displayed on screen is escaped for HTML or database stuff. Additional replacing is taken here, such as some HTML tags: *
, replaced to \n """ unescaped = escaped_text try: unescaped = HTMLParser.HTMLParser().unescape(escaped_text) # replace most common HTML data unescaped = unescaped.replace('
', '\n') unescaped = unescaped.replace('
', '\n') unescaped = unescaped.replace('
', '\n') unescaped = unescaped.decode('string_escape') except: # # If there were errors here, just ignore them and try to give back # the string the best it could do # pass return unescaped def get_day_suffix(day): """ Returns the suffix of the day, such as in 1st, 2nd, ... """ if day in (1, 11, 21, 31): return 'st' elif day in (2, 12, 22): return 'nd' elif day in (3, 13, 23): return 'rd' else: return 'th' def execute_shell(cmd, ignore_errors=False): """ Simple routine to execute shell commands. If `ignore_errors` is false (default) errors here will be thrown, and must be treated individually, to ensure proper message to end-user. The `cmd` argument must be an array, formatted for subprocess.Popen. If you are not sure on how to do that, just use: shlex.split(string). """ try: p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True) out, __ = p.communicate() except Exception, e: if not ignore_errors: raise e return out.rstrip() def strip_html(text): """ Simple regex that cleans a string of any HTML tags (for terminal output, there isn't much sense to have them printed anyway). """ return re.sub('<[^<]+?>', '', text) termsaver-0.2/termsaver0000775000175000017500000001751012120606670015623 0ustar brunobruno00000000000000#!/usr/bin/env python ############################################################################### # # file: termsaver # # Purpose: refer to python doc for documentation details. # # Note: This file is part of Termsaver application, and should not be used # or executed separately. # ############################################################################### # # Copyright 2012 Termsaver # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # ############################################################################### """ The entry point script for termsaver application. Usage: simplest form, just hit "termsaver" and go through the available options. This script will basically handle simple parsing of arguments, also transferring some of the arguments to a selected screen for additional and customizable options. See more details of this documentation in: * `usage` function * `parse_args` function """ # # Python built-in modules # import sys import errno # # Internal modules # from termsaverlib.screen import build_screen_usage_list, get_available_screens from termsaverlib.screen.base import ScreenBase from termsaverlib.screen.helper import ScreenHelperBase from termsaverlib import common, exception, constants from termsaverlib.i18n import _ verbose = False """ Defines if the error output should contain more debuging information. The verbose mode here does not actually refer to printing logs on screen (because this makes no sense for a screensaver), so any exceptions thrown that kills the application will be just completely printed out for troubleshooting purposes only. """ def usage(): """ Prints a simple description of termsaver, with a complete list of all available screens (installed in termsaverlib.screen package). """ # Print the main termsaver header ScreenBase.usage_header() print _("""Usage: %(app_name)s [screen] [options] Screens: %(screens)s Options: -h, --help Displays this help message -v, --verbose Displays python exception errors (for debugging) Refer also to each screen's help by typing: %(app_name)s [screen] -h """) % { 'app_name': constants.App.NAME, 'screens': build_screen_usage_list() } # Print the main termsaver footer ScreenBase.usage_footer() def parse_args(args): """ Simple routine to parse and handle arguments passed to termsaver. Here, a manual parsing is required because we need to transfer the arguments to the corresponding screen being called, if applicable. Some arguments are universal, though: * -v, --verbose: can only be used by the main termsaver script it will be removed from the arguments list before being transferred to the corresnponding screen. It basically prints out python exception details that can be useful for troubleshooting. * -h, --help: reused by screens, to display each screen's usage information. If no screens have been informed in the arguments, the main usage information will be then displayed. """ # # We have to parse them the hard-way to allow getopt to act within each # screen class instead. # # force parsing verbose mode from any screen global verbose for arg in args: if arg in ('-v', '--verbose'): verbose = True args.remove(arg) if len(args) < 1: usage() sys.exit(0) elif args[0] in ('-h', '--help'): usage() sys.exit(0) elif args[0] in [s().name for s in get_available_screens()]: # a proper screen was chosen, so send the args to be parsed # by the screen class for screen in \ [s for s in get_available_screens() if args[0] == s().name]: screen().autorun(args[1:]) else: txt = 'screen' if str(args[0]).startswith('-'): txt = 'option' raise exception.InvalidOptionException('', _('It seems you chose an invalid %s.') % txt) if __name__ == '__main__': # # The entry point of this application, as this should not be accessible as # a python module to be imported by another application. # try: # parse arguments and execute them accordingly parse_args(sys.argv[1:]) except KeyboardInterrupt, e: # # Handles keyboard interrupt to exit this application # by cleaning up the screen for "left-overs" ScreenHelperBase.clear_screen() if verbose: common.prettify_exception(e) # Just finish gracefully sys.exit(0) except exception.TermSaverException, e: error_number = errno.EPERM # 1 if isinstance(e, exception.PathNotFoundException): # # Handles issues with file or directory reading errors # error_number = errno.ENOENT print _('Oops! Could not find path for %(path)s. %(msg)s') % \ {'path': e.path, 'msg': e.message} elif isinstance(e, exception.InvalidOptionException): # # Handles issues with invalid options # error_number = errno.EINVAL suf = '' if e.option_name not in (None, ''): suf = " '%s'" % e.option_name print _('Oops! Invalid use of option%(suf)s. %(msg)s.%(help)s') % \ {'suf': suf, 'msg': e.message, 'help': _(' See --help for details.')} elif isinstance(e, exception.UrlException): # # Handles issues with invalid URLs # error_number = errno.ENETUNREACH print _('Oops! Error while trying to fetch from %(url)s. %(msg)s')\ % {'url': e.url, 'msg': e.message} elif isinstance(e, exception.XmlException): # # Handles issues with invalid URLs # error_number = errno.ENOEXEC suf = '' if e.name not in (None, ''): suf = " with '%s'" % e.name print _('Oops! There were parsing issues%(suf)s. %(msg)s') % \ {'suf': suf, 'msg': e.message} elif isinstance(e, exception.TermSaverException): # # Handles other termsaver errors # error_number = errno.ENOEXEC print _('Oops! There was an error: %(msg)s') % {'msg': e.message} if verbose: common.prettify_exception(e) if e.help_msg not in (None, ''): print e.help_msg sys.exit(error_number) except Exception, e: # # Handles keyboard interrupt to exit this application # by cleaning up the screen for "left-overs" # print _("""Oops! Something went terribly wrong. Error details: %s""" % e.message) if verbose: common.prettify_exception(e) print _(""" You are more than welcome to report this at: %(url)s """) % {'url': constants.App.SOURCE_URL} if not verbose: print _(""" Just before you do so, please run termsaver again with the option --verbose and copy the output when you are filling the bug report, that will help track faster the problem. Thanks! """) sys.exit(errno.EPERM) termsaver-0.2/locale/0000775000175000017500000000000012120627176015124 5ustar brunobruno00000000000000termsaver-0.2/locale/pt/0000775000175000017500000000000012120627176015547 5ustar brunobruno00000000000000termsaver-0.2/locale/pt/LC_MESSAGES/0000775000175000017500000000000012120627176017334 5ustar brunobruno00000000000000termsaver-0.2/locale/pt/LC_MESSAGES/termsaver.mo0000664000175000017500000000057211753731260021706 0ustar brunobruno00000000000000$,8@9Project-Id-Version: TermSaver 0.1.2 Report-Msgid-Bugs-To: POT-Creation-Date: 2012-05-13 23:10+1000 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language-Team: LANGUAGE Language: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit termsaver-0.2/locale/en/0000775000175000017500000000000012120627176015526 5ustar brunobruno00000000000000termsaver-0.2/locale/en/LC_MESSAGES/0000775000175000017500000000000012120627176017313 5ustar brunobruno00000000000000termsaver-0.2/locale/en/LC_MESSAGES/termsaver.mo0000664000175000017500000003071311742053437021666 0ustar brunobruno00000000000000) zB S t f.v'Y;+)36/j*(+ (8a[ z #S&tU(),...///G/'^/Y/+/ 0!0)90c030/0*01(.1+W1(11    Options: -c, --char Sets the character to be showing up default is X -d, --delay Sets the speed of the displaying characters default is 0.05 of a second (advised to keep between 0.1 and 0.01). -h, --help Displays this help message Example: $ %(app_name)s %(screen)s This will trigger the screensaver to display a dot on screen, with random size increase. $ %(app_name)s %(screen)s -c + Overrides the default dot (.) character to be a plus sign (+) Options: -h, --help Displays this help message -u, --url The URL path of the RSS feed (text) to be displayed -f, --format The printing format according to values available in RSS feed: * pubDate * title * link * description You must use python dictionary based formatting style (see examples for details) Example: $ %(app_name)s %(screen)s -u http://rss.cnn.com/rss/edition.rss This will trigger the screensaver to fetch the contents from the CNN feed and display it in default formatting: '%%(title)s (%%(pubDate)s)\n' $ %(app_name)s %(screen)s -u http://rss.cnn.com/rss/edition.rss \ -f '%%(title)s (%%(pubDate)s)\n%%(description)s\n%%(link)s' This will trigger the screensaver to fetch the contents from the CNN feed and display all contents as specified in the formatting. Options: -p, --path Sets the location to search for text-based source files. this option is mandatory. -d, --delay Sets the speed of the displaying characters default is%(default_delay)s of a second -h, --help Displays this help message Examples: $ %(app_name)s %(screen)s -p /path/to/my/code This will trigger the screensaver to read all files in the path selected $ %(app_name)s %(screen)s -p /path/to/my/code -d 0 This will trigger the screensaver to read all files in the path selected with no delay (too fast for a screensaver, but it's your choice that matters!) Options: -u, --url Defines the URL location from where the information should be fetched, then displayed. This option is MANDATORY. -d, --delay Sets the speed of the displaying characters default is 0.003 of a second (advised to keep between 0.01 and 0.001). -h, --help Displays this help message Examples: $ %(app_name)s %(screen)s -u www.google.com This will trigger the screensaver to fetch the HTML contents of this web site and display progressively. $ %(app_name)s %(screen)s -u www.google.com -d 0 This will trigger the screensaver to fetch the HTML contents of this web site with no delay (too fast for a screensaver, but it's your choice that matters!) Options: -w, --word Sets the word to be displayed default is the name of this application -d, --delay Sets how long the word will be displayed before randomized again. Default is%(default_delay)s of a second -h, --help Displays this help message Example: $ %(app_name)s %(screen)s This will trigger the screensaver to display the default word %(app_title)s in random locations of the screen $ %(app_name)s %(screen)s -w FooBar This will trigger the screensaver to display the default word FooBar in random locations of the screen You just need to provide the URL from where %(app_title)s will read and display on screen. If you do not have any idea which URL to use, check out some examples here: RFC RFC-1034 - http://tools.ietf.org/rfc/rfc1034.txt See a RFC list from Wikipedia: http://en.wikipedia.org/wiki/List_of_RFCs (remember to use the txt version) You just need to provide the URL of the RSS feed from where %(app_title)s will read and display on screen. If you do not have any idea which RSS to use, check out some examples here: CNN Top Stories - http://rss.cnn.com/rss/edition.rss World - http://rss.cnn.com/rss/edition_world.rss Technology - http://rss.cnn.com/rss/edition_technology.rss See CNN's complete list of RSS syndication here: http://edition.cnn.com/services/rss/ Lifehacker - http://www.lifehacker.com/index.xml Note: Lifehacker uses HTML to deliver "description" contents in the RSS, so you might need to change the format to something like: --format "%%(title)s (%%(pubDate)s)\n" You just need to provide the path to the location from where %(app_title)s will read and display on screen. If you do not have any code in your local machine, just get some interesting project from the Internet, such as Django (http://www.djangoproject.com): If you have access to subversion, you may download it at: svn co https://code.djangoproject.com/svn/django/trunk/ django-trunk Or, just download the zipped source and unpack it on your local machine: https://www.djangoproject.com/download/ Connecting to %s ... (this could take a while)Could not fetch URL, because %sFetched URL returned error %d.Fetched data is binary.It is mandatory optionMake sure the file or directory exists.Screen: %(screen)s Description: %(description)s Usage: %(app_name)s %(screen)s [options]There was an error while using your format.URL can not be blankURL does not seem validUnhandled option. See --help for details.displays a random running dotdisplays ascii images from asciiartfarts.com (NSFW)displays recent jokes from jokes4all.net (NSFW)displays recent quotes from quotes4all.netdisplays rss feed informationdisplays source code in typing animationdisplays url contents with typing animationdisplays word in random places on screenrandomly displays RFC contentsProject-Id-Version: PACKAGE VERSION Report-Msgid-Bugs-To: POT-Creation-Date: 2012-03-01 22:35+1000 PO-Revision-Date: 2012-03-01 22:35+1000 Last-Translator: Automatically generated Language-Team: none Language: en MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); Options: -c, --char Sets the character to be showing up default is X -d, --delay Sets the speed of the displaying characters default is 0.05 of a second (advised to keep between 0.1 and 0.01). -h, --help Displays this help message Example: $ %(app_name)s %(screen)s This will trigger the screensaver to display a dot on screen, with random size increase. $ %(app_name)s %(screen)s -c + Overrides the default dot (.) character to be a plus sign (+) Options: -h, --help Displays this help message -u, --url The URL path of the RSS feed (text) to be displayed -f, --format The printing format according to values available in RSS feed: * pubDate * title * link * description You must use python dictionary based formatting style (see examples for details) Example: $ %(app_name)s %(screen)s -u http://rss.cnn.com/rss/edition.rss This will trigger the screensaver to fetch the contents from the CNN feed and display it in default formatting: '%%(title)s (%%(pubDate)s)\n' $ %(app_name)s %(screen)s -u http://rss.cnn.com/rss/edition.rss \ -f '%%(title)s (%%(pubDate)s)\n%%(description)s\n%%(link)s' This will trigger the screensaver to fetch the contents from the CNN feed and display all contents as specified in the formatting. Options: -p, --path Sets the location to search for text-based source files. this option is mandatory. -d, --delay Sets the speed of the displaying characters default is%(default_delay)s of a second -h, --help Displays this help message Examples: $ %(app_name)s %(screen)s -p /path/to/my/code This will trigger the screensaver to read all files in the path selected $ %(app_name)s %(screen)s -p /path/to/my/code -d 0 This will trigger the screensaver to read all files in the path selected with no delay (too fast for a screensaver, but it's your choice that matters!) Options: -u, --url Defines the URL location from where the information should be fetched, then displayed. This option is MANDATORY. -d, --delay Sets the speed of the displaying characters default is 0.003 of a second (advised to keep between 0.01 and 0.001). -h, --help Displays this help message Examples: $ %(app_name)s %(screen)s -u www.google.com This will trigger the screensaver to fetch the HTML contents of this web site and display progressively. $ %(app_name)s %(screen)s -u www.google.com -d 0 This will trigger the screensaver to fetch the HTML contents of this web site with no delay (too fast for a screensaver, but it's your choice that matters!) Options: -w, --word Sets the word to be displayed default is the name of this application -d, --delay Sets how long the word will be displayed before randomized again. Default is%(default_delay)s of a second -h, --help Displays this help message Example: $ %(app_name)s %(screen)s This will trigger the screensaver to display the default word %(app_title)s in random locations of the screen $ %(app_name)s %(screen)s -w FooBar This will trigger the screensaver to display the default word FooBar in random locations of the screen You just need to provide the URL from where %(app_title)s will read and display on screen. If you do not have any idea which URL to use, check out some examples here: RFC RFC-1034 - http://tools.ietf.org/rfc/rfc1034.txt See a RFC list from Wikipedia: http://en.wikipedia.org/wiki/List_of_RFCs (remember to use the txt version) You just need to provide the URL of the RSS feed from where %(app_title)s will read and display on screen. If you do not have any idea which RSS to use, check out some examples here: CNN Top Stories - http://rss.cnn.com/rss/edition.rss World - http://rss.cnn.com/rss/edition_world.rss Technology - http://rss.cnn.com/rss/edition_technology.rss See CNN's complete list of RSS syndication here: http://edition.cnn.com/services/rss/ Lifehacker - http://www.lifehacker.com/index.xml Note: Lifehacker uses HTML to deliver "description" contents in the RSS, so you might need to change the format to something like: --format "%%(title)s (%%(pubDate)s)\n" You just need to provide the path to the location from where %(app_title)s will read and display on screen. If you do not have any code in your local machine, just get some interesting project from the Internet, such as Django (http://www.djangoproject.com): If you have access to subversion, you may download it at: svn co https://code.djangoproject.com/svn/django/trunk/ django-trunk Or, just download the zipped source and unpack it on your local machine: https://www.djangoproject.com/download/ Connecting to %s ... (this could take a while)Could not fetch URL, because %sFetched URL returned error %d.Fetched data is binary.It is mandatory optionMake sure the file or directory exists.Screen: %(screen)s Description: %(description)s Usage: %(app_name)s %(screen)s [options]There was an error while using your format.URL can not be blankURL does not seem validUnhandled option. See --help for details.displays a random running dotdisplays ascii images from asciiartfarts.com (NSFW)displays recent jokes from jokes4all.net (NSFW)displays recent quotes from quotes4all.netdisplays rss feed informationdisplays source code in typing animationdisplays url contents with typing animationdisplays word in random places on screenrandomly displays RFC contentstermsaver-0.2/locale/ja/0000775000175000017500000000000012120627176015516 5ustar brunobruno00000000000000termsaver-0.2/locale/ja/LC_MESSAGES/0000775000175000017500000000000012120627176017303 5ustar brunobruno00000000000000termsaver-0.2/locale/ja/LC_MESSAGES/termsaver.mo0000664000175000017500000000102011742053437021643 0ustar brunobruno00000000000000,<P*QT|>displays recent quotes from quotes4all.netProject-Id-Version: PACKAGE VERSION Report-Msgid-Bugs-To: POT-Creation-Date: 2012-03-01 22:35+1000 PO-Revision-Date: 2012-03-01 22:35+1000 Last-Translator: Automatically generated Language-Team: none Language: ja MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; quotes4all.netから最近の引用符が表示されます。termsaver-0.2/PKG-INFO0000664000175000017500000000147512120627176014771 0ustar brunobruno00000000000000Metadata-Version: 1.1 Name: termsaver Version: 0.2 Summary: Simple text-based terminal screensaver. Home-page: http://termsaver.info Author: Bruno Braga Author-email: bruno.braga@gmail.com License: Apache License v2 Description: UNKNOWN Keywords: command-line,terminal,screensaver Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Natural Language :: English Classifier: Operating System :: MacOS Classifier: Operating System :: POSIX Classifier: Programming Language :: Python Classifier: Topic :: Terminals Classifier: Topic :: Utilities termsaver-0.2/README0000664000175000017500000001766412120627136014557 0ustar brunobruno00000000000000.. ############################################################################ .. # .. # file: README .. # .. # Purpose: holds basic information about termsaver application, .. # in markdown format for GitHub. .. # .. # Note: This file is part of Termsaver application, and should not be .. # used or executed separately. .. # .. ############################################################################ .. # .. # Copyright 2012 Termsaver .. # .. # Licensed under the Apache License, Version 2.0 (the "License"); you may .. # not use this file except in compliance with the License. You may obtain .. # a copy of the License at .. # .. # http://www.apache.org/licenses/LICENSE-2.0 .. # .. # Unless required by applicable law or agreed to in writing, software .. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT .. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the .. # License for the specific language governing permissions and limitations .. # under the License. .. # .. ############################################################################ ========= TermSaver ========= *A simple text-based screensaver for terminal windows.* You may also want to visit our website: http://termsaver.info .. image:: https://github.com/brunobraga/termsaver/raw/master/extras/termsaver-main_medium.jpeg ---------- Background ---------- The motivation behind this project is basically pure boredom (laughs). Seriously, it may look like nonsense to have a screensaver look-alike program running on a terminal window. Nonetheless, sometimes, we still want to see some kind of movement, or action on the screen... which invigorates one's state of mind and helps concentration back to the black screen (well, some people like it white, meh!). If you are: * looking for some extra display on your main terminal window, to keep the screen busy while you are up to something else; or * looking for some distractions that may entertain you after too many hours in front of the terminal; or * with plenty of screen space (so long 80x25 default terminal window! long live 1920px...), and use many terminals on screen; or * just wanting to pretend you are busy with something (this is terrible) then, TermSaver is the **right** application for you. ------------ Requirements ------------ * Linux, or Mac (or Windows too, but you are on your own) * Python 2.5+ (and < 3.x) ------------ Installation ------------ Apt (Advanced Packaging Tool) ----------------------------- For Ubuntu (12.10+) distro, you can use: :: sudo apt-get install termsaver Pip (Pip Installs Packages, for Python Package Index) ----------------------------------------------------- For those using others, and still want to do it the easy way, I recommend: :: sudo pip install termsaver From the Source --------------- 1. Download the Source here_: .. _here: http://pypi.python.org/pypi/termsaver/ 2. Unpack it :: tar -zxvf termsaver-{version}.tar.gz 3. Install it :: sudo python setup.py install PPA (Advanced Packaging Tool) ----------------------------- If you can't wait for Debian/Ubuntu releases, you can get the latest packages from: :: sudo add-apt-repository ppa:bruno-braga/termsaver sudo apt-get update sudo apt-get install termsaver -------- Features -------- The TermSaver is a very simple application, built with the idea to allow more screensavers to be added to its core. Developers, please read the section below. The current published screensavers are: Ascii Art Farts --------------- This is a screensaver that displays ascii art from asciiartfarts.com RSS feed in an animation format. Jokes For All ------------- This is a screensaver that displays recent jokes from http://jokes4all.net website, from its hourly updated RSS_ feed. .. _RSS : http://en.wikipedia.org/wiki/RSS Programmer ---------- This is a screensaver that displays source code from a specified path in visual animation. Quotes For All -------------- This is a screensaver that displays recent quotes from http://quotes4all.net website, from its hourly updated RSS_ feed. .. _RSS : http://en.wikipedia.org/wiki/RSS Random Text ----------- This is a screensaver that displays a text (your name, or whatever) on a randomized position of the screen, changing position every N seconds. Request for Change ------------------ This is a screensaver that fetches documents from RFC (Request for Comments) in visual animation, which are documents elaborated by the Internet Engineering Task Force, available at http://tools.ietf.org/rfc/. This screensaver randomizes documents to display, from a list of latest valid documents. See more information about this in Wikipedia_. .. _Wikipedia : http://en.wikipedia.org/wiki/Request_for_Comments RSS Feeds --------- This is a screensaver that displays any RSS_ feed you want to show in your terminal, with customizable settings and format. .. _RSS : http://en.wikipedia.org/wiki/RSS URL Fetcher ----------- This is a screensaver that displays content from a specified URL_ directly on screen, in visual animation. .. _URL : http://en.wikipedia.org/wiki/Uniform_resource_locator Clock ----- This is a screensaver that displays a digital clock using ascii letters. Matrix ------ This is a screensaver that displays falling (rising) Japanese characters simulating the screen from the movie The_Matrix_ .. _The_Matrix : http://en.wikipedia.org/wiki/The_Matrix Sysmon ------ (For Linux systems only) Displays the CPU/Memory usage over time in a graphic alike screensaver. ------ **Disclaimer Note**: termsaver holds no responsibility for the contents offered by third-parties, nor it has controls to filter them. Use it at your own risk. ---------- Developers ---------- A more detailed guideline for developers willing to jump in and create screensavers for termsaver is here: https://github.com/brunobraga/termsaver/wiki/Developers ------- Roadmap ------- There is no current roadmap defined, besides improvement tickets created in Issues_ tab in GitHub. Refer also to http://github.com/brunobraga/termsaver/wiki/Brainstorming for some insights of stuff we are thinking about. .. _Issues : https://github.com/brunobraga/termsaver/issues ---------- Contribute ---------- Translation ----------- The internationalization of this application follows same standards of most applications out there, by using *gettext* and MO/PO files. The translation is still being finished up, and when it is ready for contributor calls, we will post detailed information about the procedure. Let us know you want to help: support@termsaver.info Screensavers (plugin) --------------------- As of v0.2, full plugin support is available, find an example here: https://github.com/brunobraga/termsaver-figlet Submit a bug ------------ If you find any errors in this application, you are more than welcome to participate. You can: * report the bug: https://github.com/brunobraga/termsaver/issues * Fork this project: https://github.com/brunobraga/termsaver/fork --------- Uninstall --------- Using Apt (Advanced Packaging Tool) or PPA (Personal Package Archive) ---------------------------------------------------------------------- :: sudo apt-get remove termsaver Using Pip (Pip Install Packages, for Python Package Index) ---------------------------------------------------------- :: sudo pip uninstall termsaver Manual Uninstall ---------------- Just remove manually the following files: :: # For Linux boxes rm -rvf /usr/local/bin/termsaver rm -rvf /usr/local/lib/python2.7/dist-packages/termsaver* rm -rvf /usr/local/share/man/man1/termsaver.1 find /usr/local/share/locale/ -name "termsaver.mo" -exec rm -rfv {} \; If the actuall location differ from the above, it might be worth it to just run the find command and look for them yourself (should not be hard): :: find /usr/ -name "*termsaver*" termsaver-0.2/doc/0000775000175000017500000000000012120627176014432 5ustar brunobruno00000000000000termsaver-0.2/doc/termsaver.10000664000175000017500000000625212120363757016533 0ustar brunobruno00000000000000.TH "TERMSAVER" "1" "22 March 2012" "Termsaver" "" .SH "NAME" Termsaver \- A simple text-based terminal screensaver .SH "SYNTAX" .B termsaver .RI [ SCREEN ] .RI [ OPTIONS ] .br .SH "DESCRIPTION" .B Termsaver is a simple alternative for simulating command-line based screensavers right on the terminal, in text-based format. .P To start the screensaver, execute .B Termsaver command with proper options as described in detail below, and to close it, just use the standard .I Ctrl+C to interrupt it (or close the terminal window if you are on a desktop environment and no longer need it). .br .SH "SCREEN" The .B Termsaver application, to work properly, requires a .I screen as argument, which represents the name of the screensaver to be loaded. Each .I screen, in turn, will have its own set of optional arguments, documented in its .B help option. . .P Here follows a list of currently available screens (note that this information might become outdated if updates are not fully documented here, so always rely on the .B help option to display all .I screens available): .TP .B quotes4all displays recent quotes from quotes4all.net .TP .B asciiartfarts displays ascii images from asciiartfarts.com (NSFW) .TP .B rssfeed displays rss feed information .TP .B clock displays a digital clock on screen .TP .B randtxt displays word in random places on screen .TP .B rfc randomly displays RFC contents .TP .B programmer displays source code in typing animation .TP .B urlfetcher displays url contents with typing animation .TP .B jokes4all displays recent jokes from jokes4all.net (NSFW) .TP .B matrix displays a matrix movie alike screensaver .TP .B sysmon displays a graphic of CPU/MEM usage over time .P Refer to .B help option for additional information for each .I screen usage and example. .br .SH "OPTIONS" This program follow the usual GNU command line syntax, with long options starting with two dashes (`\-'). A summary of options is included below. .TP .B \-h, \-\-help Displays this help message .TP .B \-v, \-\-verbose Displays python exception errors (for debugging) .P .SH "EXAMPLES" .TP Check all available screens to use: .B termsaver --help .br .TP Run random text screensaver with extra arguments: .B termsaver .I randtxt .BR --word " HelloWorld " --delay " 1 " .SH "SEE ALSO" See more information about this project at: .br .I http://termsaver.info .br .SH "COPYRIGHT" Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at .P http://www.apache.org/licenses/LICENSE-2.0 .P Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. .br .SH "AUTHORS" Termsaver was written by Bruno Braga .RI < bruno.braga@gmail.com >, .br and contributors. .PP .SH "BUGS" Report bugs to authors at: .br .I http://github.com/brunobraga/termsaver