Releasing 0.4

This commit is contained in:
Lionel Dricot 2022-02-20 23:22:25 +01:00
parent aa8e0cdb3e
commit 3b809c4146
4 changed files with 37 additions and 18 deletions

View File

@ -1,6 +1,6 @@
# Offpunk History # Offpunk History
## 0.4 - Unreleased ## 0.4 - Feb 21st 2022
UPGRADE: Users who subscribed to pages before 0.4 should run once the command "list subscribe subscribed". Without that, the subscribed list will be seen as a normal list by sync. UPGRADE: Users who subscribed to pages before 0.4 should run once the command "list subscribe subscribed". Without that, the subscribed list will be seen as a normal list by sync.
- New list command : "list freeze" and "list suscribe" - New list command : "list freeze" and "list suscribe"
- Pictures are now displayed directely in terminal (suggested by kelbot) - Pictures are now displayed directely in terminal (suggested by kelbot)
@ -13,6 +13,7 @@ UPGRADE: Users who subscribed to pages before 0.4 should run once the command "l
- "version" will now display info about your system installation - "version" will now display info about your system installation
- "info" command will display technical information about current page - "info" command will display technical information about current page
- "sync" allows you to do the sync from within Offpunk - "sync" allows you to do the sync from within Offpunk
=> gemini://rawtext.club/~ploum/2022-02-21-offpunk04.gmi
## 0.3 - Feb 11th 2022 ## 0.3 - Feb 11th 2022
New Features: New Features:

View File

@ -1,6 +1,6 @@
# OFFPUNK # OFFPUNK
A command-line, text-based and offline-first Gemini, Gopher and Web browser by [Ploum](https://ploum.net). A command-line and offline-first smolnet browser/feed reader for Gemini, Gopher and Web by [Ploum](https://ploum.net).
The goal of Offpunk is to be able to synchronise your content once (a day, a week, a month) and then browse/organise it while staying disconnected. The goal of Offpunk is to be able to synchronise your content once (a day, a week, a month) and then browse/organise it while staying disconnected.
@ -46,11 +46,8 @@ Known issues in the code:
I would happily mentor anyone willing to implement those: I would happily mentor anyone willing to implement those:
* TODO0: Hard - Make a manual within the git repository and have it automatically deployed as a website. * TODO0: Hard - Make a manual within the git repository and have it automatically deployed as a website.
* TODO1: Easy - Update blackbox to reflect cache hits. * TODO1: Easy - Update blackbox to reflect cache hits.
* TODO2: Hard - "pdf" - Implement retrieving PDF version of pages * TODO2: Medium - Rendering themes to allow customizing of colors ? (if any interest in the feature)
* TODO3: Medium - Transparent privacy redirects (twitter->nitter, etc) * TODO3: Hard - "search" - Offline search engine to search in the cache (hard, no idea on how to do that)
* TODO4: Medium - Rendering themes to allow customizing of colors ? (if any interest in the feature)
* TODO6: Hard - "search" - Offline search engine to search in the cache (hard, no idea on how to do that)
* TODO7: Easy - "share" - send a page by email
## More ## More
@ -61,16 +58,17 @@ Announces about Offpunk will be made on Ploums Gemlog => gemini://rawtext.cl
## Dependencies ## Dependencies
Offpunk has no "strict dependencies", i.e. it will run and work without anything Offpunk has no "strict dependencies", i.e. it should run and work without anything
else beyond the Python standard library and the "less" pager. However, it will "opportunistically else beyond the Python standard library and the "less" pager. However, it will "opportunistically
import" a few other libraries if they are available to offer an improved import" a few other libraries if they are available to offer an improved
experience or some other features. Python libraries requests, bs4 and readabliity are required for http/html support. experience or some other features. Python libraries requests, bs4 and readabliity are required for http/html support.
To avoid using unstable or too recent libraries, the rule of thumb is that a library should be packaged in Debian/Ubuntu. To avoid using unstable or too recent libraries, the rule of thumb is that a library should be packaged in Debian/Ubuntu. Keep in mind that Offpunk is mainly tested will all libraries installed. If you encounter a crash without one optional dependencies, please report it.
Run command `version` in offpunk to see if you are missing some dependencies. Run command `version` in offpunk to see if you are missing some dependencies.
* [Python-xdg](https://www.freedesktop.org/wiki/Software/pyxdg) will place your data, config and cache in place recommended by the XDG specs (usually its .local/share/offpunk, .config/offpunk and .cache/offpunk). Without it, look for ~/.offpunk or ~/.config/offpunk while the cache will be in ~/.cache/offpunk/. If installation is done later, some config files may need to be migrated by hand. * [Python-xdg](https://www.freedesktop.org/wiki/Software/pyxdg) will place your data, config and cache in place recommended by the XDG specs (usually its .local/share/offpunk, .config/offpunk and .cache/offpunk). Without it, look for ~/.offpunk or ~/.config/offpunk while the cache will be in ~/.cache/offpunk/. If installation is done later, some config files may need to be migrated by hand.
* [xdg-utils](https://www.freedesktop.org/wiki/Software/xdg-utils/) provides xdg-open which is highly recommended to open files without a renderer or a handler. It is also used for mailto: command.
* [Python-requests](http://python-requests.org) is needed to handle http/https requests natively (apt-get install python3-requests). Without it, http links will be opened in an external browser * [Python-requests](http://python-requests.org) is needed to handle http/https requests natively (apt-get install python3-requests). Without it, http links will be opened in an external browser
* [BeautifulSoup4](https://www.crummy.com/software/BeautifulSoup) and [Readability](https://github.com/buriy/python-readability) are both needed to render HTML. Without them, HTML will not be rendered or be sent to an external parser like Lynx. (apt-get install python3-bs4 python3-readability or pip3 install readability-lxml) * [BeautifulSoup4](https://www.crummy.com/software/BeautifulSoup) and [Readability](https://github.com/buriy/python-readability) are both needed to render HTML. Without them, HTML will not be rendered or be sent to an external parser like Lynx. (apt-get install python3-bs4 python3-readability or pip3 install readability-lxml)
* [Python-feedparser](https://github.com/kurtmckee/feedparser) will allow parsing of RSS/Atom feeds and thus subscriptions to them. (apt-get install python3-feedparser) * [Python-feedparser](https://github.com/kurtmckee/feedparser) will allow parsing of RSS/Atom feeds and thus subscriptions to them. (apt-get install python3-feedparser)
@ -92,8 +90,9 @@ Run command `version` in offpunk to see if you are missing some dependencies.
* Built-in documentation: type `help` to get the list of command or a specific help about a command. * Built-in documentation: type `help` to get the list of command or a specific help about a command.
* Offline mode to browse cached content without a connection. Requested elements are automatically fetched during the next synchronization and are added to your tour. * Offline mode to browse cached content without a connection. Requested elements are automatically fetched during the next synchronization and are added to your tour.
* HTML pages are prettified to focus on content. Read without being disturbed. * HTML pages are prettified to focus on content. Read without being disturbed.
* RSS/Atom feeds are automatically discovered by `subscribe` and rendered as gemlogs.
* Support "subscriptions" to a page. New content seen in subscribed pages are automatically added to your next tour. * Support "subscriptions" to a page. New content seen in subscribed pages are automatically added to your next tour.
* Complex bookmarks management through multiple lists, built-in edition and archiving. * Complex bookmarks management through multiple lists, built-in edition, subscribing/freezing and archiving.
* Advanced navigation tools like `tour` and `mark` (as per VF-1). Unlike AV-98, tour is saved on disk accross sessions. * Advanced navigation tools like `tour` and `mark` (as per VF-1). Unlike AV-98, tour is saved on disk accross sessions.
* Ability to specify external handler programs for different MIME types (use `handler`) * Ability to specify external handler programs for different MIME types (use `handler`)
* Non-interactive cache-building with configurable depth through the --sync command. The cache can easily be used by other software. * Non-interactive cache-building with configurable depth through the --sync command. The cache can easily be used by other software.

View File

@ -68,6 +68,7 @@ except ModuleNotFoundError:
_HAS_CHAFA = shutil.which('chafa') _HAS_CHAFA = shutil.which('chafa')
_HAS_XSEL = shutil.which('xsel') _HAS_XSEL = shutil.which('xsel')
_HAS_XDGOPEN = shutil.which('xdg-open')
try: try:
from PIL import Image from PIL import Image
_HAS_PIL = True _HAS_PIL = True
@ -300,7 +301,9 @@ class AbstractRenderer():
return self.validity return self.validity
def get_links(self): def get_links(self):
if self.links == None : if self.links == None :
rendered_text, self.links = self.render(self.body,mode="links_only") results = self.render(self.body,mode="links_only")
if results:
self.links = results[1]
return self.links return self.links
def get_title(self): def get_title(self):
return "Abstract title" return "Abstract title"
@ -318,7 +321,10 @@ class AbstractRenderer():
else : else :
mode = "full" mode = "full"
prepared_body = self.prepare(self.body,mode=mode) prepared_body = self.prepare(self.body,mode=mode)
self.rendered_text, self.links = self.render(prepared_body,width=width,mode=mode) result = self.render(prepared_body,width=width,mode=mode)
if result:
self.rendered_text = result[0]
self.links = result[1]
return self.rendered_text return self.rendered_text
# An instance of AbstractRenderer should have a self.render(body,width,mode) method. # An instance of AbstractRenderer should have a self.render(body,width,mode) method.
# 3 modes are used :readable (by default), full and links_only (the fastest, when # 3 modes are used :readable (by default), full and links_only (the fastest, when
@ -651,6 +657,10 @@ class ImageRenderer(AbstractRenderer):
class HtmlRenderer(AbstractRenderer): class HtmlRenderer(AbstractRenderer):
def get_mime(self): def get_mime(self):
return "text/html" return "text/html"
def is_valid(self):
if not _DO_HTML:
print("HTML document detected. Please install python-bs4 and python-readability.")
return _DO_HTML and self.validity
def get_subscribe_links(self): def get_subscribe_links(self):
subs = [[self.url,self.get_mime(),self.get_title()]] subs = [[self.url,self.get_mime(),self.get_title()]]
soup = BeautifulSoup(self.body, 'html.parser') soup = BeautifulSoup(self.body, 'html.parser')
@ -1165,7 +1175,7 @@ class GeminiItem():
def get_rendered_body(self,readable=True): def get_rendered_body(self,readable=True):
if not self.renderer: if not self.renderer:
self._set_renderer() self._set_renderer()
if self.renderer: if self.renderer and self.renderer.is_valid():
body = self.renderer.get_body(readable=readable) body = self.renderer.get_body(readable=readable)
self.__make_links(self.renderer.get_links()) self.__make_links(self.renderer.get_links())
to_return = self._make_terminal_title() + body to_return = self._make_terminal_title() + body
@ -1472,8 +1482,12 @@ class GeminiClient(cmd.Cmd):
resp = input("Send an email to %s Y/N? " %gi.path) resp = input("Send an email to %s Y/N? " %gi.path)
self.gi = gi self.gi = gi
if resp.strip().lower() in ("y", "yes"): if resp.strip().lower() in ("y", "yes"):
cmd = "xdg-open mailto:%s" %gi.path if _HAS_XDGOPEN :
subprocess.call(shlex.split(cmd)) cmd = "xdg-open mailto:%s" %gi.path
subprocess.call(shlex.split(cmd))
else:
print("Cannot find a mail client to send mail to %s" %gi.path)
print("Please install xdg-open (usually from xdg-util package)")
return return
elif gi.scheme not in ("file","gemini", "gopher", "http", "https") and not self.sync_only: elif gi.scheme not in ("file","gemini", "gopher", "http", "https") and not self.sync_only:
print("Sorry, no support for {} links.".format(gi.scheme)) print("Sorry, no support for {} links.".format(gi.scheme))
@ -2103,7 +2117,11 @@ class GeminiClient(cmd.Cmd):
break break
else: else:
# Use "xdg-open" as a last resort. # Use "xdg-open" as a last resort.
cmd_str = "xdg-open %s" if _HAS_XDGOPEN:
cmd_str = "xdg-open %s"
else:
cmd_str = "echo ""Cant find how to open %s"""
print("Please install xdg-open (usually from xdg-util package)")
self._debug("Using handler: %s" % cmd_str) self._debug("Using handler: %s" % cmd_str)
return cmd_str return cmd_str
@ -2661,6 +2679,7 @@ Think of it like marks in vi: 'mark a'='ma' and 'go a'=''a'."""
output += " - python-readability : " + has(_HAS_READABILITY) output += " - python-readability : " + has(_HAS_READABILITY)
output += " - python-xdg : " + has(_HAS_XDG) output += " - python-xdg : " + has(_HAS_XDG)
output += " - python-setproctitle : " + has(_HAS_SETPROCTITLE) output += " - python-setproctitle : " + has(_HAS_SETPROCTITLE)
output += " - xdg-open : " + has(_HAS_XDGOPEN)
output += " - chafa : " + has(_HAS_CHAFA) output += " - chafa : " + has(_HAS_CHAFA)
output += " - xsel : " + has(_HAS_XSEL) output += " - xsel : " + has(_HAS_XSEL)
@ -2674,7 +2693,7 @@ Think of it like marks in vi: 'mark a'='ma' and 'go a'=''a'."""
output += "\n" output += "\n"
output += "Config directory : " + _CONFIG_DIR + "\n" output += "Config directory : " + _CONFIG_DIR + "\n"
output += "User Data directory : " + _DATA_DIR + "\n" output += "User Data directory : " + _DATA_DIR + "\n"
output += "CACHE : " + _CACHE_PATH output += "Cache directoy : " + _CACHE_PATH
print(output) print(output)

View File

@ -2,7 +2,7 @@ from setuptools import setup
setup( setup(
name='offpunk', name='offpunk',
version='0.3', version='0.4',
description="Offline Command line Gemini client forked from AV-98.", description="Offline Command line Gemini client forked from AV-98.",
author="Ploum", author="Ploum",
author_email="offpunk@ploum.eu", author_email="offpunk@ploum.eu",