diff --git a/doc/manpages/qvm-ls.rst b/doc/manpages/qvm-ls.rst index 02c4272c..7b5e2150 100644 --- a/doc/manpages/qvm-ls.rst +++ b/doc/manpages/qvm-ls.rst @@ -47,14 +47,6 @@ Options Decrease verbosity. -.. option:: --spinner - - Have a spinner spinning while the spinning mainloop spins new table cells. - -.. option:: --no-spinner - - No spinner today. - Authors ------- | Joanna Rutkowska diff --git a/qubesadmin/spinner.py b/qubesadmin/spinner.py deleted file mode 100644 index 58e67586..00000000 --- a/qubesadmin/spinner.py +++ /dev/null @@ -1,147 +0,0 @@ -# vim: fileencoding=utf-8 - -# -# The Qubes OS Project, https://www.qubes-os.org/ -# -# Copyright (C) 2017 Wojtek Porczyk -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, see . -# - -'''Qubes CLI spinner - -A novice asked the master: “In the east there is a great tree-structure that -men call `Corporate Headquarters'. It is bloated out of shape with vice -presidents and accountants. It issues a multitude of memos, each saying `Go, -Hence!' or `Go, Hither!' and nobody knows what is meant. Every year new names -are put onto the branches, but all to no avail. How can such an unnatural -entity be?" - -The master replied: “You perceive this immense structure and are disturbed that -it has no rational purpose. Can you not take amusement from its endless -gyrations? Do you not enjoy the untroubled ease of programming beneath its -sheltering branches? Why are you bothered by its uselessness?” - -(Geoffrey James, “The Tao of Programming”, 7.1) -''' - -import curses -import io -import itertools - -CHARSET = '-\\|/' -ENTERPRISE_CHARSET = CHARSET * 4 + '-._.-^' * 2 - -class AbstractSpinner(object): - '''The base class for all Spinners - - :param stream: file-like object with ``.write()`` method - :param str charset: the sequence of characters to display - - The spinner should be used as follows: - 1. exactly one call to :py:meth:`show()` - 2. zero or more calls to :py:meth:`update()` - 3. exactly one call to :py:meth:`hide()` - ''' - def __init__(self, stream, charset=CHARSET): - self.stream = stream - self.charset = itertools.cycle(charset) - - def show(self, prompt): - '''Show the spinner, with a prompt - - :param str prompt: prompt, like "please wait" - ''' - raise NotImplementedError() - - def hide(self): - '''Hide the spinner and the prompt''' - raise NotImplementedError() - - def update(self): - '''Show next spinner character''' - raise NotImplementedError() - - -class DummySpinner(AbstractSpinner): - '''Dummy spinner, does not do anything''' - def show(self, prompt): - pass - - def hide(self): - pass - - def update(self): - pass - - -class QubesSpinner(AbstractSpinner): - '''Basic spinner - - This spinner uses standard ASCII control characters''' - def __init__(self, *args, **kwargs): - super(QubesSpinner, self).__init__(*args, **kwargs) - self.hidelen = 0 - self.cub1 = '\b' - - def show(self, prompt): - self.hidelen = len(prompt) + 2 - self.stream.write('{} {}'.format(prompt, next(self.charset))) - self.stream.flush() - - def hide(self): - self.stream.write('\r' + ' ' * self.hidelen + '\r') - self.stream.flush() - - def update(self): - self.stream.write(self.cub1 + next(self.charset)) - self.stream.flush() - - -class QubesSpinnerEnterpriseEdition(QubesSpinner): - '''Enterprise spinner - - This is tty- and terminfo-aware spinner. Recommended. - ''' - def __init__(self, stream, charset=None): - # our Enterprise logic follows - self.stream_isatty = stream.isatty() - if charset is None: - charset = ENTERPRISE_CHARSET if self.stream_isatty else '.' - - super(QubesSpinnerEnterpriseEdition, self).__init__(stream, charset) - - if self.stream_isatty: - try: - curses.setupterm() - self.has_terminfo = True - self.cub1 = curses.tigetstr('cub1').decode() - except (curses.error, io.UnsupportedOperation): - # we are in very non-Enterprise environment - self.has_terminfo = False - else: - self.cub1 = '' - - def hide(self): - if self.stream_isatty: - hideseq = '\r' + ' ' * self.hidelen + '\r' - if self.has_terminfo: - hideseq_l = (curses.tigetstr('cr'), curses.tigetstr('clr_eol')) - if all(seq is not None for seq in hideseq_l): - hideseq = ''.join(seq.decode() for seq in hideseq_l) - else: - hideseq = '\n' - - self.stream.write(hideseq) - self.stream.flush() diff --git a/qubesadmin/tools/qvm_ls.py b/qubesadmin/tools/qvm_ls.py index e45a9123..26c5ec92 100644 --- a/qubesadmin/tools/qvm_ls.py +++ b/qubesadmin/tools/qvm_ls.py @@ -34,7 +34,6 @@ import textwrap import qubesadmin -import qubesadmin.spinner import qubesadmin.tools import qubesadmin.utils import qubesadmin.vm @@ -387,10 +386,9 @@ class Table(object): :param qubes.Qubes app: Qubes application object. :param list colnames: Names of the columns (need not to be uppercase). ''' - def __init__(self, app, colnames, spinner, raw_data=False): + def __init__(self, app, colnames, raw_data=False): self.app = app self.columns = tuple(Column.columns[col.upper()] for col in colnames) - self.spinner = spinner self.raw_data = raw_data def get_head(self): @@ -402,7 +400,6 @@ def get_row(self, vm): ret = [] for col in self.columns: ret.append(col.cell(vm)) - self.spinner.update() return ret def write_table(self, stream=sys.stdout): @@ -413,12 +410,9 @@ def write_table(self, stream=sys.stdout): table_data = [] if not self.raw_data: - self.spinner.show('please wait...') table_data.append(self.get_head()) - self.spinner.update() for vm in sorted(self.app.domains): table_data.append(self.get_row(vm)) - self.spinner.hide() qubesadmin.tools.print_table(table_data, stream=stream) else: for vm in sorted(self.app.domains): @@ -529,16 +523,6 @@ def get_parser(): help='Display specify data of specified VMs. Intended for ' 'bash-parsing.') - parser.add_argument('--spinner', - action='store_true', dest='spinner', - help='reenable spinner') - - parser.add_argument('--no-spinner', - action='store_false', dest='spinner', - help='disable spinner') - - parser.set_defaults(spinner=True) - # parser.add_argument('--conf', '-c', # action='store', metavar='CFGFILE', # help='Qubes config file') @@ -571,15 +555,8 @@ def main(args=None, app=None): if col.upper() not in Column.columns: PropertyColumn(col.lower()) - if args.spinner: - # we need Enterprise Edition™, since it's the only one that detects TTY - # and uses dots if we are redirected somewhere else - spinner = qubesadmin.spinner.QubesSpinnerEnterpriseEdition(sys.stderr) - else: - spinner = qubesadmin.spinner.DummySpinner(sys.stderr) - args.app.domains.get_all_data() - table = Table(args.app, columns, spinner) + table = Table(args.app, columns) table.write_table(sys.stdout) return 0