support for timg as an alternative to chafa
This commit is contained in:
parent
a651537052
commit
435ab36525
|
@ -1,14 +1,16 @@
|
|||
# Offpunk History
|
||||
|
||||
## 1.1 - Unreleased
|
||||
- Perfect rendering of pictures with chafa 1.8+ and compatible terminal
|
||||
- Perfect rendering of pictures with chafa 1.8+ and compatible terminal (Kitty)
|
||||
- timg is supported as an alternative to chafa (with a little glitch)
|
||||
- "cp cache" put the path of the cached content in clipboard
|
||||
- "cp url X" will copy the URL of link X (suggested by Eoin Carney)
|
||||
- HTML renderering of <pre> has been improved
|
||||
- "fold" has been removed as it doesn’t work well anyway with our width.
|
||||
- "fold" has been removed as it doesn’t work well and can be replaced with "!fold".
|
||||
- Improved clipboard URL detection an fixed crash when binary in clipboard
|
||||
- Fixed crash when chafa is not installed (Thanks Xavier Hinault for the report)
|
||||
- Fixed crash when python-readability not installed (Thanks Nic for the report)
|
||||
- Fixed some URL being wronlgy interpreted as IPv6
|
||||
|
||||
## 1.0 - March 14th 2022
|
||||
- Default width is now the standard 72
|
||||
|
|
|
@ -67,7 +67,7 @@ Announces about Offpunk will be made on Ploum’s Gemlog => gemini://rawtext.cl
|
|||
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
|
||||
import" a few other libraries if they are available to offer an improved
|
||||
experience or some other features. Python libraries requests, bs4 and readability are required for http/html support. Images are displayed if python-ansiwrap and chafa are presents (python-pil is needed for chafa version before 1.10).
|
||||
experience or some other features. Python libraries requests, bs4 and readability are required for http/html support. Images are displayed if python-ansiwrap and chafa or timg are presents (python-pil is needed for chafa version before 1.10). When displaying only a picture (not inline), rendering will be pixel perfect in compatible terminals (such as Kitty) if chafa is at least version 1.8 or if timg is used.
|
||||
|
||||
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.
|
||||
|
||||
|
@ -86,6 +86,7 @@ Run command `version` in offpunk to see if you are missing some dependencies.
|
|||
* [Python editor](https://github.com/fmoo/python-editor) is used to edit your lists with "list edit". (apt-get install python3-editor)
|
||||
* [Xsel](http://www.vergenet.net/~conrad/software/xsel/) allows to `go` to the URL copied in the clipboard without having to paste it (both X and traditional clipboards are supported). Also needed to use the `copy` command. (apt-get install xsel)
|
||||
* [Chafa](https://hpjansson.org/chafa/) allows to display pictures in your console. Install it and browse to an HTML page with picture to see the magic.
|
||||
* [Timg](https://github.com/hzeller/timg) is a slower alternative to chafa for inline images. But it has better rendering when displaying only the image. Install both to get the best of both world.
|
||||
* [Python-pil](http://python-pillow.github.io/) is required to only display the first frame of animated gif with chafa if chafa version is lower than 1.10.
|
||||
* [Python-setproctitle](https://github.com/dvarrazzo/py-setproctitle) will change the process name from "python" to "offpunk". Useful to kill it without killing every python service.
|
||||
|
||||
|
|
120
offpunk.py
120
offpunk.py
|
@ -109,50 +109,73 @@ def wraplines(*args,**kwargs):
|
|||
def wrapparagraph(*args,**kwargs):
|
||||
return "\n".join(wraplines(*args,**kwargs))
|
||||
|
||||
_HAS_PIL = False
|
||||
_RENDER_IMAGE = False
|
||||
_HAS_TIMG = False
|
||||
#_HAS_TIMG = shutil.which('timg')
|
||||
if _HAS_TIMG:
|
||||
chafa_inline = "timg --frames=1 -p q -g %sx1000"
|
||||
chafa_cmd = "timg --frames=1 -C"
|
||||
if _HAS_ANSIWRAP:
|
||||
_RENDER_IMAGE = True
|
||||
|
||||
|
||||
try:
|
||||
from PIL import Image
|
||||
_HAS_PIL = True
|
||||
except ModuleNotFoundError:
|
||||
_HAS_PIL = False
|
||||
_HAS_TIMG = shutil.which('timg')
|
||||
_HAS_CHAFA = shutil.which('chafa')
|
||||
if not _RENDER_IMAGE:
|
||||
if _HAS_CHAFA:
|
||||
# starting with 1.10, chafa can return only one frame
|
||||
# which allows us to drop dependancy for PIL
|
||||
return_code = subprocess.run("chafa --version",shell=True, capture_output=True)
|
||||
output = return_code.stdout.decode()
|
||||
# with chafa < 1.10, --version was returned to stderr instead of stdout.
|
||||
if output == '':
|
||||
_NEW_CHAFA = False
|
||||
chafa_inline = "chafa --bg white -s %s -w 1 -f symbols"
|
||||
chafa_cmd = "chafa --bg white -w 1"
|
||||
else:
|
||||
_NEW_CHAFA = True
|
||||
chafa_inline += "--animate=off "
|
||||
else:
|
||||
_NEW_CHAFA = False
|
||||
_NEW_CHAFA = False
|
||||
|
||||
if _NEW_CHAFA and _HAS_ANSIWRAP:
|
||||
_RENDER_IMAGE = True
|
||||
else:
|
||||
# All this code to know if we render image inline or not
|
||||
if _HAS_CHAFA:
|
||||
# starting with 1.10, chafa can return only one frame
|
||||
# which allows us to drop dependancy for PIL
|
||||
return_code = subprocess.run("chafa --version",shell=True, capture_output=True)
|
||||
output = return_code.stdout.decode()
|
||||
# with chafa < 1.10, --version was returned to stderr instead of stdout.
|
||||
if output != '':
|
||||
_NEW_CHAFA = True
|
||||
if _NEW_CHAFA and _HAS_ANSIWRAP:
|
||||
_RENDER_IMAGE = True
|
||||
elif _HAS_TIMG and _HAS_ANSIWRAP:
|
||||
_RENDER_IMAGE = True
|
||||
elif _HAS_CHAFA and _HAS_PIL and _HAS_ANSIWRAP:
|
||||
_RENDER_IMAGE = True
|
||||
else:
|
||||
_RENDER_IMAGE = False
|
||||
print("To render images inline, you need either chafa or timg and ansiwrap.")
|
||||
if not _NEW_CHAFA and not _HAS_TIMG:
|
||||
print("Before Chafa 1.10, you also need python-pil")
|
||||
|
||||
#return ANSI text that can be show by less
|
||||
def inline_image(img_file,width):
|
||||
#Chafa is faster than timg inline. Let use that one by default
|
||||
inline = None
|
||||
ansi_img = ""
|
||||
if _HAS_CHAFA and _HAS_ANSIWRAP:
|
||||
if _HAS_PIL and not _NEW_CHAFA:
|
||||
# this code is a hack to remove frames from animated gif
|
||||
img_obj = Image.open(img_file)
|
||||
if hasattr(img_obj,"n_frames") and img_obj.n_frames > 1:
|
||||
# we remove all frames but the first one
|
||||
img_obj.save(img_file,save_all=False)
|
||||
inline = "chafa --bg white -s %s -w 1 -f symbols"
|
||||
elif _NEW_CHAFA:
|
||||
inline = "chafa --bg white -s %s -w 1 -f symbols --animate=off"
|
||||
if not inline and _HAS_TIMG and _HAS_ANSIWRAP:
|
||||
inline = "timg --frames=1 -p q -g %sx1000"
|
||||
if inline:
|
||||
cmd = inline%width+ " \"%s\""%img_file
|
||||
try:
|
||||
from PIL import Image
|
||||
_HAS_PIL = True
|
||||
if _HAS_ANSIWRAP and _HAS_CHAFA:
|
||||
_RENDER_IMAGE = True
|
||||
else:
|
||||
print("chafa and ansiwrap are required to render images in terminal")
|
||||
_RENDER_IMAGE = False
|
||||
except ModuleNotFoundError:
|
||||
print("python-pil, chafa and ansiwrap are required to render images")
|
||||
_RENDER_IMAGE = False
|
||||
_HAS_PIL = False
|
||||
return_code = subprocess.run(cmd,shell=True, capture_output=True)
|
||||
ansi_img = return_code.stdout.decode()
|
||||
except Exception as err:
|
||||
ansi_img = "***image failed : %s***\n" %err
|
||||
return ansi_img
|
||||
|
||||
def terminal_image(img_file):
|
||||
#Render by timg is better than old chafa.
|
||||
# it is also centered
|
||||
cmd = None
|
||||
if _HAS_TIMG:
|
||||
cmd = "timg --frames=1 -C"
|
||||
elif _HAS_CHAFA:
|
||||
cmd = "chafa --bg white -w 1"
|
||||
if cmd:
|
||||
cmd = cmd + " \"%s\""%img_file
|
||||
subprocess.run(cmd,shell=True)
|
||||
|
||||
|
||||
_HAS_XSEL = shutil.which('xsel')
|
||||
|
@ -741,17 +764,7 @@ class ImageRenderer(AbstractRenderer):
|
|||
spaces = 0
|
||||
else:
|
||||
spaces = int((term_width() - width)//2)
|
||||
try:
|
||||
if _HAS_PIL:
|
||||
img_obj = Image.open(img)
|
||||
if hasattr(img_obj,"n_frames") and img_obj.n_frames > 1:
|
||||
# we remove all frames but the first one
|
||||
img_obj.save(img,save_all=False)
|
||||
cmd = chafa_inline%width+ " \"%s\""%img
|
||||
return_code = subprocess.run(cmd,shell=True, capture_output=True)
|
||||
ansi_img = return_code.stdout.decode()
|
||||
except Exception as err:
|
||||
ansi_img = "***image failed : %s***\n" %err
|
||||
ansi_img = inline_image(img,width)
|
||||
#Now centering the image
|
||||
lines = ansi_img.splitlines()
|
||||
new_img = ""
|
||||
|
@ -761,8 +774,7 @@ class ImageRenderer(AbstractRenderer):
|
|||
def display(self,mode=None,title=None):
|
||||
if title:
|
||||
print(title)
|
||||
cmd = chafa_cmd + " \"%s\""%self.body
|
||||
subprocess.run(cmd,shell=True)
|
||||
terminal_image(self.body)
|
||||
return True
|
||||
|
||||
class HtmlRenderer(AbstractRenderer):
|
||||
|
|
Loading…
Reference in New Issue