icat: Add an option to only detect image display support

This commit is contained in:
Kovid Goyal
2017-12-15 14:04:40 +05:30
parent 50470b5747
commit 1f093b4ff2
2 changed files with 44 additions and 10 deletions

View File

@@ -304,6 +304,8 @@ def defval_for_opt(opt):
dv = dv.lower() in ('true', 'yes', 'y') dv = dv.lower() in ('true', 'yes', 'y')
elif typ == 'list': elif typ == 'list':
dv = [] dv = []
elif typ in ('int', 'float'):
dv = (int if typ == 'int' else float)(dv or 0)
return dv return dv
@@ -345,6 +347,7 @@ class Options:
opt = self.opt_for_alias(alias) opt = self.opt_for_alias(alias)
typ = opt.get('type', '') typ = opt.get('type', '')
name = opt['dest'] name = opt['dest']
nmap = {'float': float, 'int': int}
if typ == 'bool-set': if typ == 'bool-set':
self.values_map[name] = True self.values_map[name] = True
elif typ == 'bool-reset': elif typ == 'bool-reset':
@@ -358,6 +361,13 @@ class Options:
raise SystemExit('{} is not a valid value for the {} option. Valid values are: {}'.format( raise SystemExit('{} is not a valid value for the {} option. Valid values are: {}'.format(
val, emph(alias), ', '.join(choices))) val, emph(alias), ', '.join(choices)))
self.values_map[name] = val self.values_map[name] = val
elif typ in nmap:
f = nmap[typ]
try:
self.values_map[name] = f(val)
except Exception:
raise SystemExit('{} is not a valid value for the {} option, a number is required.'.format(
val, emph(alias)))
else: else:
self.values_map[name] = val self.values_map[name] = val

View File

@@ -45,7 +45,7 @@ OPTIONS = '''\
type=choices type=choices
choices=center,left,right choices=center,left,right
default=center default=center
Horizontal alignment for the displayed image. Defaults to centered. Horizontal alignment for the displayed image.
--transfer-mode --transfer-mode
@@ -57,6 +57,20 @@ auto-detect. |_ file| means to use a temporary file and |_ stream| means to
send the data via terminal escape codes. Note that if you use the |_ file| send the data via terminal escape codes. Note that if you use the |_ file|
transfer mode and you are connecting over a remote session then image display transfer mode and you are connecting over a remote session then image display
will not work. will not work.
--detect-support
type=bool-set
Detect support for image display in the terminal. If not supported, will exit
with exit code 1, otherwise will exit with code 0 and print the supported
transfer mode to stderr, which can be used with the |_ --transfer-mode| option.
--detection-timeout
type=float
default=10
The amount of time (in seconds) to wait for a response form the terminal, when
detecting image display support.
''' '''
@@ -208,12 +222,13 @@ def scan(d):
yield os.path.join(dirpath, f), mt yield os.path.join(dirpath, f), mt
def detect_support(wait_for=10): def detect_support(wait_for=10, silent=False):
fd = sys.stdin.fileno() fd = sys.stdin.fileno()
old = termios.tcgetattr(fd) old = termios.tcgetattr(fd)
oldfl = fcntl.fcntl(fd, fcntl.F_GETFL) oldfl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldfl | os.O_NONBLOCK) fcntl.fcntl(fd, fcntl.F_SETFL, oldfl | os.O_NONBLOCK)
print('Checking for graphics ({}s max. wait)...'.format(wait_for), end='\r') if not silent:
print('Checking for graphics ({}s max. wait)...'.format(wait_for), end='\r')
sys.stdout.flush() sys.stdout.flush()
tty.setraw(fd) tty.setraw(fd)
try: try:
@@ -248,7 +263,8 @@ def detect_support(wait_for=10):
for key, mask in sel.select(0.1): for key, mask in sel.select(0.1):
read() read()
finally: finally:
sys.stdout.buffer.write(b'\033[J'), sys.stdout.flush() if not silent:
sys.stdout.buffer.write(b'\033[J'), sys.stdout.flush()
termios.tcsetattr(fd, termios.TCSADRAIN, old) termios.tcsetattr(fd, termios.TCSADRAIN, old)
fcntl.fcntl(fd, fcntl.F_SETFL, oldfl) fcntl.fcntl(fd, fcntl.F_SETFL, oldfl)
detect_support.has_files = bool(responses.get(2)) detect_support.has_files = bool(responses.get(2))
@@ -256,24 +272,32 @@ def detect_support(wait_for=10):
def main(args=sys.argv): def main(args=sys.argv):
msg = (
'A cat like utility to display images in the terminal.'
' You can specify multiple image files and/or directories.'
' Directories are scanned recursively for image files.')
args, items = parse_args(args[1:], options_spec, 'image-file ...', msg, '{} icat'.format(appname))
signal.signal(signal.SIGWINCH, lambda: screen_size(refresh=True)) signal.signal(signal.SIGWINCH, lambda: screen_size(refresh=True))
if not sys.stdout.isatty() or not sys.stdin.isatty(): if not sys.stdout.isatty() or not sys.stdin.isatty():
raise SystemExit( raise SystemExit(
'Must be run in a terminal, stdout is currently not a terminal' 'Must be run in a terminal, stdout is currently not a terminal'
) )
if screen_size().width == 0: if screen_size().width == 0:
if args.detect_support:
raise SystemExit(1)
raise SystemExit( raise SystemExit(
'Terminal does not support reporting screen sizes via the TIOCGWINSZ ioctl' 'Terminal does not support reporting screen sizes via the TIOCGWINSZ ioctl'
) )
msg = ( if args.detect_support:
'A cat like utility to display images in the terminal.' if not detect_support(wait_for=args.detection_timeout, silent=True):
' You can specify multiple image files and/or directories.' raise SystemExit(1)
' Directories are scanned recursively for image files.') print('file' if detect_support.has_files else 'stream', end='', file=sys.stderr)
args, items = parse_args(args[1:], options_spec, 'image-file ...', msg, '{} icat'.format(appname)) return
if not items: if not items:
raise SystemExit('You must specify at least one file to cat') raise SystemExit('You must specify at least one file to cat')
if args.transfer_mode == 'detect': if args.transfer_mode == 'detect':
if not detect_support(): if not detect_support(wait_for=args.detection_timeout):
raise SystemExit('This terminal emulator does not support the graphics protocol, use a terminal emulator such as kitty that does support it') raise SystemExit('This terminal emulator does not support the graphics protocol, use a terminal emulator such as kitty that does support it')
else: else:
detect_support.has_files = args.transfer_mode == 'file' detect_support.has_files = args.transfer_mode == 'file'