def toggle_scroll_fix(sheet):

    # Disable scroll fix
    if options.scroll_fix_enabled:
        options.scroll_fix_enabled = False
        status('scroll fix disabled')

        Sheet.addCommand(None, 'go-down', 'cursorDown(+1)', 'go down')
        Sheet.addCommand(None, 'go-up', 'cursorDown(-1)', 'go up')

    # Enable scrollfix
    else:
        options.scroll_fix_enabled = True
        status('scroll fix enabled')

        Sheet.addCommand(None, 'go-up',
                         'sheet.topRowIndex -= 1; sheet.cursorRowIndex -= 1',
                         'move cursor up with a fixed position')
        Sheet.addCommand(
            None, 'go-down',
            'sheet.topRowIndex = sheet.nRows - sheet.nScreenRows if sheet.topRowIndex + sheet.nScreenRows >= sheet.nRows else sheet.topRowIndex + 1; sheet.cursorRowIndex += 1',
            'move cursor down with a fixed position')
Example #2
0
def newSheet(vd, ncols, name='', **kwargs):
    return Sheet(name,
                 columns=[ColumnItem('', i, width=8) for i in range(ncols)],
                 **kwargs)
Example #3
0
from copy import copy
from visidata import vd, asyncthread, Progress, Sheet, options

Sheet.init('_ordering', list, copy=True)  # (col:Column, reverse:bool)


@Sheet.api
def orderBy(sheet, *cols, reverse=False):
    'Add cols to the internal ordering. No cols (or first col None) remove any previous ordering. call sort() if the ordering changes.'
    if options.undo:
        vd.addUndo(setattr, sheet, '_ordering', copy(sheet._ordering))
        if sheet._ordering:
            vd.addUndo(sheet.sort)
        else:
            vd.addUndo(setattr, sheet, 'rows', copy(sheet.rows))

    do_sort = False
    if not cols or cols[0] is None:
        sheet._ordering.clear()
        cols = cols[1:]
        do_sort = True

    for c in cols:
        sheet._ordering.append((c, reverse))
        do_sort = True

    if do_sort:
        sheet.sort()

class Reversor:
    def __init__(self, obj):
Example #4
0
from visidata import vd, Sheet, Progress, option, asyncthread, options, rotateRange, Fanout, undoAttrCopyFunc, copy
option('bulk_select_clear',
       False,
       'clear selected rows before new bulk selections',
       replay=True)

Sheet.init('_selectedRows', dict)  # rowid(row) -> row


@Sheet.api
def isSelected(self, row):
    'True if given row is selected. O(log n).'
    return self.rowid(row) in self._selectedRows


@Sheet.api
@asyncthread
def toggle(self, rows):
    'Toggle selection of given `rows`.'
    self.addUndoSelection()
    for r in Progress(rows, 'toggling', total=len(self.rows)):
        if not self.unselectRow(r):
            self.selectRow(r)


@Sheet.api
def selectRow(self, row):
    'Select given row. O(log n)'
    self._selectedRows[self.rowid(row)] = row

Example #5
0
import functools
import datetime
from visidata import options, theme, Sheet, TypedWrapper

from .vdtui import vdtype

try:
    import dateutil.parser
except ImportError:
    pass

theme('disp_date_fmt', '%Y-%m-%d',
      'default fmtstr to strftime for date values')

Sheet.addCommand('z~', 'type-any', 'cursorCol.type = anytype'),
Sheet.addCommand('~', 'type-string', 'cursorCol.type = str'),
Sheet.addCommand('@', 'type-date', 'cursorCol.type = date'),
Sheet.addCommand('#', 'type-int', 'cursorCol.type = int'),
Sheet.addCommand('z#', 'type-len', 'cursorCol.type = len'),
Sheet.addCommand('$', 'type-currency', 'cursorCol.type = currency'),
Sheet.addCommand('%', 'type-float', 'cursorCol.type = float'),

floatchars = '+-0123456789.'


def currency(s=''):
    'dirty float (strip non-numeric characters)'
    if isinstance(s, str):
        s = ''.join(ch for ch in s if ch in floatchars)
    return float(s) if s else TypedWrapper(float, None)
Example #6
0
import re
import random

from visidata import asyncthread, warning, option, options, vd
from visidata import BaseSheet, Sheet, Column, Progress

Sheet.addCommand(
    ':', 'split-col',
    'addRegexColumns(makeRegexSplitter, sheet, cursorColIndex, cursorCol, input("split regex: ", type="regex-split"))',
    'add new columns from regex split; number of columns determined by example row at cursor'
)
Sheet.addCommand(
    ';', 'capture-col',
    'addRegexColumns(makeRegexMatcher, sheet, cursorColIndex, cursorCol, input("match regex: ", type="regex-capture"))',
    'add new column from capture groups of regex; requires example row')
Sheet.addCommand(
    '*', 'addcol-subst',
    'addColumn(Column(cursorCol.name + "_re", getter=regexTransform(cursorCol, input("transform column by regex: ", type="regex-subst"))), cursorColIndex+1)',
    'add column derived from current column, replacing regex with subst (may include \1 backrefs)'
)
Sheet.addCommand(
    'g*', 'setcol-subst', 'setSubst([cursorCol], selectedRows)',
    'regex/subst - modify selected rows in current column, replacing regex with subst, (may include backreferences \\1 etc)'
)
Sheet.addCommand(
    'gz*', 'setcol-subst-all', 'setSubst(visibleCols, selectedRows)',
    'modify selected rows in all visible columns, replacing regex with subst (may include \\1 backrefs)'
)


@Sheet.api
Example #7
0
from visidata import Sheet

Sheet.addCommand('t', 'stoggle-row', 'toggle([cursorRow]); cursorDown(1)'),
Sheet.addCommand('s', 'select-row', 'select([cursorRow]); cursorDown(1)'),
Sheet.addCommand('u', 'unselect-row', 'unselect([cursorRow]); cursorDown(1)'),

Sheet.addCommand('gt', 'stoggle-rows', 'toggle(rows)'),
Sheet.addCommand('gs', 'select-rows', 'select(rows)'),
Sheet.addCommand('gu', 'unselect-rows', '_selectedRows.clear()'),

Sheet.addCommand('zt', 'stoggle-before', 'toggle(rows[:cursorRowIndex])'),
Sheet.addCommand('zs', 'select-before', 'select(rows[:cursorRowIndex])'),
Sheet.addCommand('zu', 'unselect-before', 'unselect(rows[:cursorRowIndex])'),
Sheet.addCommand('gzt', 'stoggle-after', 'toggle(rows[cursorRowIndex:])'),
Sheet.addCommand('gzs', 'select-after', 'select(rows[cursorRowIndex:])'),
Sheet.addCommand('gzu', 'unselect-after', 'unselect(rows[cursorRowIndex:])'),

Sheet.addCommand(
    '|', 'select-col-regex',
    'selectByIdx(vd.searchRegex(sheet, regex=input("|", type="regex", defaultLast=True), columns="cursorCol"))'
),
Sheet.addCommand(
    '\\', 'unselect-col-regex',
    'unselectByIdx(vd.searchRegex(sheet, regex=input("\\\\", type="regex", defaultLast=True), columns="cursorCol"))'
),
Sheet.addCommand(
    'g|', 'select-cols-regex',
    'selectByIdx(vd.searchRegex(sheet, regex=input("g|", type="regex", defaultLast=True), columns="visibleCols"))'
),
Sheet.addCommand(
    'g\\', 'unselect-cols-regex',
Example #8
0
from visidata import globalCommand, Sheet, TextSheet, vd, error, stacktrace

globalCommand(
    '^E', 'error-recent',
    'vd.lastErrors and vd.push(ErrorSheet("last_error", vd.lastErrors[-1])) or status("no error")'
)
globalCommand(
    'g^E', 'errors-all',
    'vd.push(ErrorSheet("last_errors", sum(vd.lastErrors[-10:], [])))')

Sheet.addCommand(
    'z^E', 'error-cell',
    'vd.push(ErrorSheet("cell_error", getattr(cursorCell, "error", None) or fail("no error this cell")))'
)


class ErrorSheet(TextSheet):
    pass
Example #9
0
@Sheet.api
def paste_after(sheet, rowidx):
    vd.addUndo(sheet.rows.pop, rowidx + 1)
    sheet.rows[rowidx + 1:rowidx + 1] = list(
        deepcopy(r) for s, i, r in vd.cliprows)


@Sheet.api
def paste_before(sheet, rowidx):
    sheet.rows[sheet.cursorRowIndex:sheet.cursorRowIndex] = list(
        deepcopy(r) for s, i, r in vd.cliprows)
    vd.addUndo(sheet.rows.pop, rowidx)


Sheet.addCommand('y', 'copy-row', 'copyRows([cursorRow])',
                 'yank (copy) current row to clipboard')
Sheet.addCommand('d', 'delete-row', 'delete_row(cursorRowIndex)',
                 'delete (cut) current row and move it to clipboard')
Sheet.addCommand('p', 'paste-after', 'paste_after(cursorRowIndex)',
                 'paste clipboard rows after current row')
Sheet.addCommand('P', 'paste-before', 'paste_before(cursorRowIndex)',
                 'paste clipboard rows before current row')

Sheet.addCommand('gd', 'delete-selected',
                 'copyRows(selectedRows); deleteSelected()',
                 'delete (cut) selected rows and move them to clipboard')
Sheet.addCommand('gy', 'copy-selected', 'copyRows(selectedRows)',
                 'yank (copy) selected rows to clipboard')

Sheet.addCommand('zy', 'copy-cell', 'copyCells(cursorCol, [cursorRow])',
                 'yank (copy) current cell to clipboard')
Example #10
0
from visidata import Sheet, rotate_range


def evalmatcher(sheet, expr):
    def matcher(r):
        return sheet.evalexpr(expr, r)

    return matcher


def search_func(sheet, rows, func, reverse=False):
    for i in rotate_range(len(sheet.rows),
                          sheet.cursorRowIndex,
                          reverse=reverse):
        try:
            if func(sheet.rows[i]):
                return i
        except Exception:
            pass


Sheet.addCommand(
    'z/', 'search-expr',
    'sheet.cursorRowIndex=search_func(sheet, rows, evalmatcher(sheet, inputExpr("search by expr: "))) or status("no match")'
)
Sheet.addCommand(
    'z?', 'searchr-expr',
    'sheet.cursorRowIndex=search_func(sheet, rows, evalmatcher(sheet, inputExpr("search by expr: ")), reverse=True) or status("no match")'
)
Example #11
0
@Column.api
def toggleVisibility(self):
    if self.height == 1:
        self.height = 10
    else:
        self.height = 1


def unhide_cols(cols, rows):
    'sets appropriate width if column was either hidden (0) or unseen (None)'
    for c in cols:
        c.setWidth(abs(c.width or 0) or c.getMaxWidth(rows))


Sheet.addCommand(
    '_', 'resize-col-max',
    'cursorCol.toggleWidth(cursorCol.getMaxWidth(visibleRows))',
    'toggle width of current column between full and default width'),
Sheet.addCommand(
    'z_', 'resize-col-input',
    'width = int(input("set width= ", value=cursorCol.width)); cursorCol.setWidth(width)',
    'adjust width of current column to N')
Sheet.addCommand(
    'g_', 'resize-cols-max',
    'for c in visibleCols: c.setWidth(c.getMaxWidth(visibleRows))',
    'toggle widths of all visible clumns between full and default width'),
Sheet.addCommand(
    'gz_', 'resize-cols-input',
    'width = int(input("set width= ", value=cursorCol.width)); Fanout(visibleCols).setWidth(width)'
)

Sheet.addCommand('-', 'hide-col', 'cursorCol.hide()', 'hide current column')
Example #12
0
'''slide rows/columns around'''

from visidata import Sheet, moveListItem, globalCommand, vd

@Sheet.api
def slide_col(sheet, colidx, newcolidx):
    vd.addUndo(moveVisibleCol, sheet, newcolidx, colidx)
    return moveVisibleCol(sheet, colidx, newcolidx)

@Sheet.api
def slide_row(sheet, rowidx, newcolidx):
    vd.addUndo(moveListItem, sheet.rows, newcolidx, rowidx)
    return moveListItem(sheet.rows, rowidx, newcolidx)


Sheet.addCommand('H', 'slide-left', 'sheet.cursorVisibleColIndex = slide_col(cursorVisibleColIndex, cursorVisibleColIndex-1)', 'slide current column left')
Sheet.addCommand('L', 'slide-right', 'sheet.cursorVisibleColIndex = slide_col(cursorVisibleColIndex, cursorVisibleColIndex+1)', 'slide current column right')
Sheet.addCommand('J', 'slide-down', 'sheet.cursorRowIndex = slide_row(cursorRowIndex, cursorRowIndex+1)', 'slide current row down')
Sheet.addCommand('K', 'slide-up', 'sheet.cursorRowIndex = slide_row(cursorRowIndex, cursorRowIndex-1)', 'slide current row up')
Sheet.addCommand('gH', 'slide-leftmost', 'slide_col(cursorVisibleColIndex, 0)', 'slide current column all the way to the left of sheet')
Sheet.addCommand('gL', 'slide-rightmost', 'slide_col(cursorVisibleColIndex, nVisibleCols-1)', 'slide current column all the way to the right of sheet')
Sheet.addCommand('gJ', 'slide-bottom', 'slide_row(cursorRowIndex, nRows)', 'slide current row all the way to the bottom of sheet')
Sheet.addCommand('gK', 'slide-top', 'slide_row(cursorRowIndex, 0)', 'slide current row to top of sheet')
Sheet.addCommand('zH', 'slide-left-n', 'slide_col(cursorVisibleColIndex, cursorVisibleColIndex-int(input("slide col left n=", value=1)))', 'slide current column N positions to the left')
Sheet.addCommand('zL', 'slide-right-n', 'slide_col(cursorVisibleColIndex, cursorVisibleColIndex+int(input("slide col left n=", value=1)))', 'slide current column N positions to the right')
Sheet.addCommand('zJ', 'slide-down-n', 'slide_row(cursorRowIndex, cursorRowIndex+int(input("slide row down n=", value=1)))', 'slide current row N positions down')
Sheet.addCommand('zK', 'slide-up-n', 'slide_row(cursorRowIndex, cursorRowIndex-int(input("slide row up n=", value=1)))', 'slide current row N positions up')

Sheet.addCommand('BUTTON1_RELEASED','release-mouse','onRelease(cursorVisibleColIndex, cursorRowIndex, mouseX, mouseY)')

@Sheet.api
Example #13
0
                yield [startingLine+1, text]


# .source is Sheet error came from
# .lines is list of source text lines to 'load'
class ErrorSheet(TextSheet):
    precious = False
    def iterload(self):
        'Uses .lines; .source is sheet causing the error.'
        for i, line in enumerate(self.lines):
            yield [i, line]

@VisiData.property
def allErrorsSheet(self):
    return ErrorSheet("errors_all", lines=sum(vd.lastErrors, []))

@VisiData.property
def recentErrorsSheet(self):
    return ErrorSheet("errors_recent", lines=sum(vd.lastErrors[-1:], []))


globalCommand('^E', 'error-recent', 'vd.lastErrors and vd.push(recentErrorsSheet) or status("no error")', 'view traceback for most recent error')
globalCommand('g^E', 'errors-all', 'vd.push(vd.allErrorsSheet)', 'view traceback for most recent errors')

Sheet.addCommand(None, 'view-cell', 'vd.push(ErrorSheet("%s[%s].%s" % (name, cursorRowIndex, cursorCol.name), source=sheet, lines=cursorDisplay.splitlines()))', 'view contents of current cell in a new sheet'),
Sheet.addCommand('z^E', 'error-cell', 'vd.push(ErrorSheet(sheet.name+"_cell_error", source=sheet, lines=getattr(cursorCell, "error", None) or fail("no error this cell")))', 'view traceback for error in current cell')

TextSheet.addCommand('v', 'visibility', 'sheet.options.wrap = not sheet.options.wrap; reload(); status("text%s wrapped" % ("" if sheet.options.wrap else " NOT")); ')

TextSheet.options.save_filetype = 'txt'
Example #14
0
    with p.open_text(mode="w") as fp:
        fp.write(tbl)

    status(f"{p} save finished")


def save_tabulate(sheet, givenpath, confirm_overwrite=True):
    p = Path(givenpath)

    if p.exists():
        if confirm_overwrite:
            confirm(f"{givenpath} already exists. overwrite? ")

    _save_table(sheet, options.tabulate_format, p)


Sheet.copy_tabulate = copy_tabulate
Sheet.save_tabulate = save_tabulate

Sheet.addCommand(
    None, "tabulate-copy",
    "vd.sheet.copy_tabulate(input('copy sheet to clipboard as table format: ', value = options.tabulate_format))"
)

Sheet.addCommand(
    None, "tabulate-save",
    "vd.sheet.save_tabulate(inputFilename('save to: ', value = (sheet.name.strip('.') or 'directory') + '.txt'), confirm_overwrite = options.confirm_overwrite)"
)

addGlobals({"save_tabulate": save_tabulate})
Example #15
0

def evalmatcher(sheet, expr):
    def matcher(r):
        return sheet.evalexpr(expr, r)

    return matcher


def search_func(sheet, rows, func, reverse=False):
    for i in rotateRange(len(sheet.rows),
                         sheet.cursorRowIndex,
                         reverse=reverse):
        try:
            if func(sheet.rows[i]):
                return i
        except Exception:
            pass


Sheet.addCommand(
    'z/', 'search-expr',
    'sheet.cursorRowIndex=search_func(sheet, rows, evalmatcher(sheet, inputExpr("search by expr: "))) or status("no match")',
    'search by Python expression forwards in current column (with column names as variables)'
)
Sheet.addCommand(
    'z?', 'searchr-expr',
    'sheet.cursorRowIndex=search_func(sheet, rows, evalmatcher(sheet, inputExpr("search by expr: ")), reverse=True) or status("no match")',
    'search by Python expression backwards in current column (with column names as variables)'
)
Example #16
0
                yield p/fn


        basepath = str(self.source)

        folders = set()
        f = _walkfiles if options.dir_recurse else _listfiles

        hidden_files = options.dir_hidden
        for p in f(self.source):
            if hidden_files and p.name.startswith('.'):
                continue

            yield p


class FileListSheet(DirSheet):
    _ordering = []
    def iterload(self):
        for fn in self.source.open_text():
            yield Path(fn.rstrip())

globalCommand('', 'open-dir-current', 'vd.push(vd.currentDirSheet)')

Sheet.addCommand('z;', 'addcol-sh', 'cmd=input("sh$ ", type="sh"); addShellColumns(cmd, sheet)', 'create new column from bash expression, with $columnNames as variables')

DirSheet.addCommand(ENTER, 'open-row', 'vd.push(openSource(cursorRow or fail("no row"), filetype=cursorRow.ext))', 'open current file as a new sheet')
DirSheet.addCommand('g'+ENTER, 'open-rows', 'for r in selectedRows: vd.push(openSource(r))', 'open selected files as new sheets')
DirSheet.addCommand('^O', 'sysopen-row', 'launchEditor(cursorRow)', 'open current file in external $EDITOR')
DirSheet.addCommand('g^O', 'sysopen-rows', 'launchEditor(*selectedRows)', 'open selected files in external $EDITOR')
Example #17
0
    return list()


@Sheet.api
@asyncthread
def normalize_column_names(sheet):
    """
    Normalize the names of all non-hidden columns on the active sheet.
    """

    init_names = []
    gen = gen_normalize_names(c.name for c in sheet.visibleCols)
    prog = Progress(gen, gerund="normalizing", total=sheet.nVisibleCols)

    for i, norm_name in enumerate(prog):
        col = sheet.visibleCols[i]
        init_names.append(col.name)  # Store for undo
        col.name = norm_name

    @asyncthread
    def undo():
        for i, c in enumerate(init_names):
            sheet.visibleCols[i].name = c

    vd.addUndo(undo)


# Add longname-commands to VisiData to execute these methods
Sheet.addCommand(None, "normalize-col-names",
                 "vd.sheet.normalize_column_names()")
Example #18
0
import itertools
import re

from visidata import vd, VisiData, error, status, Sheet, Column, regex_flags, rotate_range, fail

vd.searchContext = {}  # regex, columns, backward to kwargs from previous search

Sheet.addCommand('c', 'go-col-regex', 'sheet.cursorVisibleColIndex=nextColRegex(sheet, input("column name regex: ", type="regex-col", defaultLast=True))')
Sheet.addCommand('r', 'search-keys', 'tmp=cursorVisibleColIndex; vd.moveRegex(sheet, regex=input("row key regex: ", type="regex-row", defaultLast=True), columns=keyCols or [visibleCols[0]]); sheet.cursorVisibleColIndex=tmp')
Sheet.addCommand('zc', 'go-col-number', 'sheet.cursorVisibleColIndex = int(input("move to column number: "))')
Sheet.addCommand('zr', 'go-row-number', 'sheet.cursorRowIndex = int(input("move to row number: "))')

Sheet.addCommand('/', 'search-col', 'vd.moveRegex(sheet, regex=input("/", type="regex", defaultLast=True), columns="cursorCol", backward=False)'),
Sheet.addCommand('?', 'searchr-col', 'vd.moveRegex(sheet, regex=input("?", type="regex", defaultLast=True), columns="cursorCol", backward=True)'),
Sheet.addCommand('n', 'next-search', 'vd.moveRegex(sheet, reverse=False)'),
Sheet.addCommand('N', 'prev-search', 'vd.moveRegex(sheet, reverse=True)'),

Sheet.addCommand('g/', 'search-cols', 'vd.moveRegex(sheet, regex=input("g/", type="regex", defaultLast=True), backward=False, columns="visibleCols")'),
Sheet.addCommand('g?', 'searchr-cols', 'vd.moveRegex(sheet, regex=input("g?", type="regex", defaultLast=True), backward=True, columns="visibleCols")'),

Sheet.addCommand('<', 'prev-value', 'moveToNextRow(lambda row,sheet=sheet,col=cursorCol,val=cursorValue: col.getValue(row) != val, reverse=True) or status("no different value up this column")'),
Sheet.addCommand('>', 'next-value', 'moveToNextRow(lambda row,sheet=sheet,col=cursorCol,val=cursorValue: col.getValue(row) != val) or status("no different value down this column")'),
Sheet.addCommand('{', 'prev-selected', 'moveToNextRow(lambda row,sheet=sheet: sheet.isSelected(row), reverse=True) or status("no previous selected row")'),
Sheet.addCommand('}', 'next-selected', 'moveToNextRow(lambda row,sheet=sheet: sheet.isSelected(row)) or status("no next selected row")'),

Sheet.addCommand('z<', 'prev-null', 'moveToNextRow(lambda row,col=cursorCol,isnull=isNullFunc(): isnull(col.getValue(row)), reverse=True) or status("no null down this column")'),
Sheet.addCommand('z>', 'next-null', 'moveToNextRow(lambda row,col=cursorCol,isnull=isNullFunc(): isnull(col.getValue(row))) or status("no null down this column")'),


def moveToNextRow(vs, func, reverse=False):
    'Move cursor to next (prev if reverse) row for which func returns True.  Returns False if no row meets the criteria.'
Example #19
0
def main_vd():
    'Open the given sources using the VisiData interface.'
    import argparse
    parser = argparse.ArgumentParser(description=__doc__)

    parser.add_argument('inputs', nargs='*', help='initial sources')
    parser.add_argument('-f', dest='filetype', default='', help='uses loader for filetype instead of file extension')
    parser.add_argument('-y', dest='confirm_overwrite', default=None, action='store_false', help='overwrites existing files without confirmation')
    parser.add_argument('-p', '--play', dest='play', default=None, help='replays a saved .vd file within the interface')
    parser.add_argument('-P', dest='preplay', action='append', default=[], help='VisiData command to preplay before cmdlog replay')
    parser.add_argument('-b', '--batch', dest='batch', action='store_true', default=False, help='replays in batch mode (with no interface and all status sent to stdout)')
    parser.add_argument('-o', '--output', dest='output', default=None, help='saves the final visible sheet to output at the end of replay')
    parser.add_argument('-w', dest='replay_wait', default=0, help='time to wait between replayed commands, in seconds')
    parser.add_argument('-d', dest='delimiter', help='delimiter to use for tsv/usv filetype')
    parser.add_argument('--diff', dest='diff', default=None, help='show diffs from all sheets against this source')
    parser.add_argument('-v', '--version', action='version', version=__version_info__)

    args = vd.parseArgs(parser)

    # fetch motd and plugins *after* options parsing/setting
    visidata.PluginsSheet().reload()
    domotd()

    locale.setlocale(locale.LC_ALL, '')

    flPipedInput = not sys.stdin.isatty()
    flPipedOutput = not sys.stdout.isatty()

    vd._stdin, vd._stdout = duptty()  # always dup stdin/stdout

    stdinSource = Path('-', fp=vd._stdin)

    # parse args, including +sheetname:subsheet:4:3 starting at row:col on sheetname:subsheet[:...]
    start_positions = []  # (list_of_sheetstr, str, str)  # empty sheetstr means all sheets
    startsheets, startrow, startcol = [], None, None
    fmtargs = []
    fmtkwargs = {}
    inputs = []
    for arg in args.inputs:
        if arg.startswith('+'):  # position cursor at start
            if ':' in arg:
                pos = arg[1:].split(':')
                if len(pos) == 1:
                    startsheet = [Path(inputs[-1]).name] if inputs else None
                    start_positions.append((startsheet, pos[0], None))
                elif len(pos) == 2:
                    startsheet = [Path(inputs[-1]).name] if inputs else None
                    startrow, startcol = pos
                    start_positions.append((None, startrow, startcol))
                elif len(pos) >= 3:
                    startsheets = pos[:-2]
                    startrow, startcol = pos[-2:]
                    start_positions.append((startsheets, startrow, startcol))
            else:
                start_positions.append((None, arg[1:], None))

        elif args.play and '=' in arg:
            # parse 'key=value' pairs for formatting cmdlog template in replay mode
            k, v = arg.split('=')
            fmtkwargs[k] = v
        elif arg == '-':
            inputs.append(stdinSource)
        else:
            inputs.append(arg)
            fmtargs.append(arg)

    if args.diff:
        vs = openSource(args.diff)
        vd.push(vs)
        vs.reload()
        setDiffSheet(vs)

    if args.batch:
        options.undo = False
        vd.status = lambda *args, **kwargs: print(*args, file=sys.stderr)  # ignore kwargs (like priority)
        vd.editline = lambda *args, **kwargs: ''
        vd.execAsync = lambda func, *args, **kwargs: func(*args, **kwargs) # disable async

    for cmd in args.preplay:
        Sheet('').exec_keystrokes(cmd)

    if not args.play:
        if flPipedInput and not inputs:  # '|vd' without explicit '-'
            inputs.append(stdinSource)

    sources = []
    for src in inputs:
        vs = openSource(src)
        vd.cmdlog.openHook(vs, src)
        sources.append(vs)

    vd.sheets.extend(sources)  # purposefully do not load everything

    if not vd.sheets and not args.play and not args.batch:
        vd.push(vd.vdmenu)

    if not args.play:
        if args.batch:
            vd.push(sources[0])
            sources[0].reload()

        for startsheets, startrow, startcol in start_positions:
            sheets = []  # sheets to apply startrow:startcol to
            if not startsheets:
                sheets = sources  # apply row/col to all sheets
            else:
                vs = vd.getSheet(startsheets[0]) or sources[-1]
                vd.sync(vs.ensureLoaded())
                vd.clearCaches()
                for startsheet in startsheets[1:]:
                    rowidx = vs.getRowIndexFromStr(startsheet)
                    if rowidx is None:
                        vs = None
                        vd.warning(f'no sheet "{startsheet}"')
                        break
                    vs = vs.rows[rowidx]
                    vd.sync(vs.ensureLoaded())
                    vd.clearCaches()
                if vs:
                    vd.push(vs)
                    sheets = [vs]

            if startrow:
                for vs in sheets:
                    if vs:
                        vs.moveToRow(startrow) or vd.warning(f'{vs} has no row "{startrow}"')

            if startcol:
                for vs in sheets:
                    if vs:
                        vs.moveToCol(startcol) or vd.warning(f'{vs} has no column "{startcol}"')

        if not args.batch:
            run(vd.sheets[0])
    else:
        if args.play == '-':
            vdfile = stdinSource
            vdfile.name = 'stdin.vd'
        else:
            vdfile = Path(args.play)

        vs = eval_vd(vdfile, *fmtargs, **fmtkwargs)
        vd.sync(vs.reload())
        if args.batch:
            if vd.replay_sync(vs):  # error
                return 1
        else:
            vd.replay(vs)
            run()

    if vd.sheets and (flPipedOutput or args.output):
        outpath = Path(args.output or '-')
        saveSheets(outpath, vd.sheets[0], confirm_overwrite=False)
        vd.sync()

    vd._stdout.flush()

    return 0
Example #20
0
@Sheet.api
def toggle_scroll_fix(sheet):

    # Disable scroll fix
    if options.scroll_fix_enabled:
        options.scroll_fix_enabled = False
        status('scroll fix disabled')

        Sheet.addCommand(None, 'go-down', 'cursorDown(+1)', 'go down')
        Sheet.addCommand(None, 'go-up', 'cursorDown(-1)', 'go up')

    # Enable scrollfix
    else:
        options.scroll_fix_enabled = True
        status('scroll fix enabled')

        Sheet.addCommand(None, 'go-up',
                         'sheet.topRowIndex -= 1; sheet.cursorRowIndex -= 1',
                         'move cursor up with a fixed position')
        Sheet.addCommand(
            None, 'go-down',
            'sheet.topRowIndex = sheet.nRows - sheet.nScreenRows if sheet.topRowIndex + sheet.nScreenRows >= sheet.nRows else sheet.topRowIndex + 1; sheet.cursorRowIndex += 1',
            'move cursor down with a fixed position')


Sheet.addCommand('w',
                 'scroll-fix-toggle',
                 'toggle_scroll_fix()',
                 helpstr='toggle scroll fix behaviour')
Example #21
0

# copy vd.sheets so that ColumnsSheet itself isn't included (for recalc in addRow)
globalCommand('gC', 'columns-all',
              'vd.push(ColumnsSheet("all_columns", source=list(vd.sheets)))',
              'open Columns Sheet with all visible columns from all sheets')
globalCommand('gO', 'options-global', 'vd.push(vd.globalOptionsSheet)',
              'open Options Sheet: edit global options (apply to all sheets)')

BaseSheet.addCommand('V', 'open-vd', 'vd.push(vd.vdmenu)')
BaseSheet.addCommand(
    'O', 'options-sheet', 'vd.push(sheet.optionsSheet)',
    'open Options Sheet: edit sheet options (apply to current sheet only)')

Sheet.addCommand('C', 'columns-sheet',
                 'vd.push(ColumnsSheet(name+"_columns", source=[sheet]))',
                 'open Columns Sheet')

# used ColumnsSheet, affecting the 'row' (source column)
ColumnsSheet.addCommand('g!', 'key-selected', 'setKeys(someSelectedRows)',
                        'toggle selected rows as key columns on source sheet')
ColumnsSheet.addCommand('gz!', 'key-off-selected',
                        'unsetKeys(someSelectedRows)',
                        'unset selected rows as key columns on source sheet')

ColumnsSheet.addCommand('g-', 'hide-selected', 'someSelectedRows.hide()',
                        'hide selected columns on source sheet')
ColumnsSheet.addCommand(
    None, 'resize-source-rows-max',
    'for c in selectedRows or [cursorRow]: c.setWidth(c.getMaxWidth(c.sheet.visibleRows))',
    'adjust widths of selected source columns')
Example #22
0
from visidata import globalCommand, Sheet, Column, options, Colorizer, vd, anytype, ENTER, asyncthread, option
from visidata import ColumnAttr, ColumnEnum, ColumnItem
from visidata import getGlobals, TsvSheet, Path, bindkeys, commands, composeStatus, Option

globalCommand('^P', 'statuses', 'vd.push(StatusSheet("statusHistory"))')
globalCommand('gC', 'columns-all',
              'vd.push(ColumnsSheet("all_columns", source=vd.sheets))')
globalCommand('S', 'sheets', 'vd.push(vd.sheetsSheet)')
globalCommand('gS', 'sheets-graveyard', 'vd.push(vd.graveyardSheet).reload()')

Sheet.addCommand('O', 'options-sheet',
                 'vd.push(getOptionsSheet(sheet)).reload()')
Sheet.addCommand('gO', 'options-global', 'vd.push(vd.optionsSheet)')
Sheet.addCommand('C', 'columns-sheet',
                 'vd.push(ColumnsSheet(name+"_columns", source=[sheet]))')
Sheet.addCommand(
    'z^H', 'help-commands',
    'vd.push(HelpSheet(name + "_commands", source=sheet, revbinds={}))')

option('visibility', 0, 'visibility level (0=low, 1=high)')


def getOptionsSheet(sheet):
    optsheet = getattr(sheet, 'optionsSheet', None)
    if not optsheet:
        sheet.optionsSheet = OptionsSheet(sheet.name + "_options",
                                          source=sheet)

    return sheet.optionsSheet

Example #23
0
    compiledExpr = compile(expr, '<expr>', 'eval')
    vd.addUndoSetValues([self], rows)
    for row in Progress(rows, 'setting'):
        self.setValueSafe(row, self.sheet.evalexpr(compiledExpr, row))
    self.recalc()
    status('set %d values = %s' % (len(rows), expr))


@Sheet.api
def inputExpr(self, prompt, *args, **kwargs):
    return vd.input(prompt,
                    "expr",
                    *args,
                    completer=CompleteExpr(self),
                    **kwargs)


Sheet.addCommand(
    '=', 'addcol-expr',
    'addColumn(ColumnExpr(inputExpr("new column expr=")), index=cursorColIndex+1)',
    'create new column from Python expression, with column names as variables')
Sheet.addCommand(
    'g=', 'setcol-expr',
    'cursorCol.setValuesFromExpr(selectedRows, inputExpr("set selected="))',
    'set current column for selected rows to result of Python expression')
Sheet.addCommand(
    'z=', 'setcell-expr',
    'cursorCol.setValues([cursorRow], evalexpr(inputExpr("set expr="), cursorRow))',
    'evaluate Python expression on current row and set current cell with result of Python expression'
)
Example #24
0
 def newRow(self):
     return Sheet('', columns=[ColumnItem('', 0)], rows=[])
Example #25
0
        # variables, similar to VisiData's `execCommand` context.
        new_locals = LazyChainMap(Dummy(), vd, vd.sheet)
        locals().update(new_locals)
    except Exception as e:
        vd.exceptionCaught(e)

    with SuspendCurses():
        try:
            history_file = (Path(vd.options.visidata_dir).expanduser() /
                            "cache" / "ptpython" / "history")
            Path.mkdir(history_file.parent, parents=True, exist_ok=True)
            shell = InteractiveShellEmbed.instance(
                history_filename=str(history_file),
                vi_mode=True,
            )
            shell.python_input.title = "VisiData IPython REPL (ptipython)"
            shell.python_input.show_exit_confirmation = False
            embed()
        except Exception as e:
            vd.exceptionCaught(e)
        finally:
            # The embedded IPython session is a singleton by default,
            # but launching it via `open-repl` in VisiData a second time
            # seems to either freeze or leave an exit message up from the
            # previous instance. Clean out the existing instance so any
            # future invocations get a fresh start.
            InteractiveShellEmbed.clear_instance()


Sheet.addCommand("", "open-repl", "vd.openRepl()")
Example #26
0
    Given a sheet, pushes a new sheet in which only non-duplicate rows are
    included.
    """
    vs = copy(sheet)
    vs.name += "_deduped"
    vd.push(vs)

    for row, is_dupe in gen_identify_duplicates(sheet):
        if is_dupe == False:
            vs.addRow(row)

# Set the two main functions above as methods on the Sheet class
Sheet.select_duplicate_rows = select_duplicate_rows
Sheet.dedupe_rows = dedupe_rows

# Add longname-commands to VisiData to execute these methods
Sheet.addCommand(None, "select-duplicate-rows", "vd.sheet.select_duplicate_rows()")
Sheet.addCommand(None, "dedupe-rows", "vd.sheet.dedupe_rows()")

"""
# Changelog

## 0.0.1 - 2019-01-01

Internal change, no external effects: Migrates from ._selectedRows to .selectedRows.

## 0.0.0 - 2018-12-30

Initial release.
"""
from copy import copy
import shutil
import subprocess
import sys
import tempfile
import functools

from visidata import vd, asyncthread, sync, status, fail, option, options
from visidata import Sheet, saveSheets

vd.cliprows = []  # list of (source_sheet, source_row_idx, source_row)
vd.clipcells = []  # list of strings

Sheet.addCommand('y', 'copy-row', 'vd.cliprows = [(sheet, cursorRowIndex, cursorRow)]')
Sheet.addCommand('d', 'delete-row', 'vd.cliprows = [(sheet, cursorRowIndex, rows.pop(cursorRowIndex))]')
Sheet.addCommand('p', 'paste-after', 'rows[cursorRowIndex+1:cursorRowIndex+1] = list(deepcopy(r) for s,i,r in vd.cliprows)')
Sheet.addCommand('P', 'paste-before', 'rows[cursorRowIndex:cursorRowIndex] = list(deepcopy(r) for s,i,r in vd.cliprows)')

Sheet.addCommand('gd', 'delete-selected', 'vd.cliprows = list((None, i, r) for i, r in enumerate(selectedRows)); deleteSelected()')
Sheet.addCommand('gy', 'copy-selected', 'vd.cliprows = list((None, i, r) for i, r in enumerate(selectedRows)); status("%d %s to clipboard" % (len(vd.cliprows), rowtype))')

Sheet.addCommand('zy', 'copy-cell', 'vd.clipcells = [cursorDisplay]')
Sheet.addCommand('zp', 'paste-cell', 'cursorCol.setValuesTyped([cursorRow], vd.clipcells[0])')
Sheet.addCommand('zd', 'delete-cell', 'vd.clipcells = [cursorDisplay]; cursorCol.setValues([cursorRow], None)')
Sheet.addCommand('gzd', 'delete-cells', 'vd.clipcells = list(sheet.cursorCol.getDisplayValue(r) for r in selectedRows); cursorCol.setValues(selectedRows, None)')

Sheet.addCommand('gzy', 'copy-cells', 'vd.clipcells = [sheet.cursorCol.getDisplayValue(r) for r in selectedRows]; status("%d values to clipboard" % len(vd.clipcells))')
Sheet.addCommand('gzp', 'paste-cells', 'for r, v in zip(selectedRows or rows, itertools.cycle(vd.clipcells)): cursorCol.setValuesTyped([r], v)')

Sheet.addCommand('Y', 'syscopy-row', 'saveToClipboard(sheet, [cursorRow], input("copy current row to system clipboard as filetype: ", value=options.save_filetype))')
Sheet.addCommand('gY', 'syscopy-selected', 'saveToClipboard(sheet, selectedRows or rows, input("copy rows to system clipboard as filetype: ", value=options.save_filetype))')
Example #28
0
import os
import stat
import pwd
import grp
import subprocess
import contextlib

from visidata import Column, Sheet, LazyMapRow, asynccache, exceptionCaught, DeferredSetColumn
from visidata import Path, ENTER, date, asyncthread, confirm, fail, error, FileExistsError
from visidata import CellColorizer, RowColorizer

Sheet.addCommand('z;', 'addcol-sh',
                 'cmd=input("sh$ ", type="sh"); addShellColumns(cmd, sheet)')


def open_dir(p):
    return DirSheet(p.name, source=p)


def addShellColumns(cmd, sheet):
    shellcol = ColumnShell(cmd, source=sheet, width=0)
    for i, c in enumerate([
            shellcol,
            Column(cmd + '_stdout',
                   srccol=shellcol,
                   getter=lambda col, row: col.srccol.getValue(row)[0]),
            Column(cmd + '_stderr',
                   srccol=shellcol,
                   getter=lambda col, row: col.srccol.getValue(row)[1]),
    ]):
        sheet.addColumn(c, index=sheet.cursorColIndex + i + 1)
Example #29
0

@Column.api
def to_entries(col):
    '''
    Convert values from a dict into a list of Key/Value pairs, similar
    to the to_entries function in jq:

    Abort if the specified column's value for any row is _not_ a dict.
    '''
    sheet = col.sheet
    rows = sheet.rows

    new_idx = sheet.columns.index(col) + 1
    new_col = sheet.addColumn(SettableColumn(col.name), index=new_idx)
    isNull = isNullFunc()
    for r in rows:
        val = col.getValue(r)
        if isNull(val):
            continue
        if not isinstance(val, dict):
            sheet.columns.pop(new_idx)
            vd.fail('Column "{}" is not a dict'.format(col.name))
        new_col.setValue(r, [{'Key': k, 'Value': v} for k, v in val.items()])
    col.hide()
    return new_col


Sheet.addCommand("z(", "setcol-fromentries", "cursorCol.from_entries()")
Sheet.addCommand("z)", "setcol-toentries", "cursorCol.to_entries()")
Example #30
0
import itertools
import random

from copy import copy
from visidata import Sheet, Column, asyncthread, Progress, status, error
from visidata import *

option('filetype', '', 'specify file type', replay=True)

IndexSheet.options.header = 0
IndexSheet.options.skip = 0

Sheet.addCommand(
    None, 'random-rows',
    'nrows=int(input("random number to select: ", value=nRows)); vs=copy(sheet); vs.name=name+"_sample"; vs.rows=random.sample(rows, nrows or nRows); vd.push(vs)',
    'open duplicate sheet with a random population subset of N rows')

Sheet.addCommand('a', 'add-row',
                 'addNewRows(1, cursorRowIndex); cursorDown(1)',
                 'append a blank row')
Sheet.addCommand(
    'ga', 'add-rows',
    'addNewRows(int(input("add rows: ", value=1)), cursorRowIndex)',
    'append N blank rows')
Sheet.addCommand('za', 'addcol-new',
                 'addColumn(SettableColumn(""), cursorColIndex+1)',
                 'append an empty column')
Sheet.addCommand(
    'gza', 'addcol-bulk',
    'for c in range(int(input("add columns: "))): addColumn(SettableColumn(""), cursorColIndex+1)',
    'append N empty columns')