예제 #1
0
from visidata import theme, globalCommand, Sheet, CellColorizer

theme('color_diff', 'red', 'color of values different from --diff source')
theme('color_diff_add', 'yellow',
      'color of rows/columns added to --diff source')

globalCommand(None, 'setdiff-sheet', 'setDiffSheet(sheet)')


def makeDiffColorizer(othersheet):
    def colorizeDiffs(sheet, col, row, cellval):
        if not row or not col:
            return None
        vcolidx = sheet.visibleCols.index(col)
        rowidx = sheet.rows.index(row)
        if vcolidx < len(othersheet.visibleCols) and rowidx < len(
                othersheet.rows):
            otherval = othersheet.visibleCols[vcolidx].getDisplayValue(
                othersheet.rows[rowidx])
            if cellval.display != otherval:
                return 'color_diff'
        else:
            return 'color_diff_add'

    return colorizeDiffs


def setDiffSheet(vs):
    Sheet.colorizers.append(CellColorizer(8, None, makeDiffColorizer(vs)))
예제 #2
0
#!/usr/bin/env python3

import curses
from visidata import globalCommand, colors, Sheet, Column, Colorizer, wrapply

globalCommand(None, 'colors', 'vd.push(ColorSheet("vdcolors"))')


class ColorSheet(Sheet):
    rowtype = 'colors'  # rowdef: color number as assigned in the colors object
    columns = [
        Column('color', type=int),
        Column('R',
               getter=lambda col, row: curses.color_content(
                   curses.pair_number(colors[row]) - 1)[0]),
        Column('G',
               getter=lambda col, row: curses.color_content(
                   curses.pair_number(colors[row]) - 1)[1]),
        Column('B',
               getter=lambda col, row: curses.color_content(
                   curses.pair_number(colors[row]) - 1)[2]),
    ]
    colorizers = [Colorizer('row', 7, lambda s, c, r, v: r)]

    def reload(self):
        self.rows = sorted(colors.keys(), key=lambda n: wrapply(int, n))
예제 #3
0
from visidata import theme, globalCommand, Sheet, CellColorizer

theme('color_diff', 'red', 'color of values different from --diff source')
theme('color_diff_add', 'yellow',
      'color of rows/columns added to --diff source')

globalCommand(None, 'setdiff-sheet', 'setDiffSheet(sheet)',
              'set this sheet as diff sheet for all new sheets')


def makeDiffColorizer(othersheet):
    def colorizeDiffs(sheet, col, row, cellval):
        if not row or not col:
            return None
        vcolidx = sheet.visibleCols.index(col)
        rowidx = sheet.rows.index(row)
        if vcolidx < len(othersheet.visibleCols) and rowidx < len(
                othersheet.rows):
            otherval = othersheet.visibleCols[vcolidx].getDisplayValue(
                othersheet.rows[rowidx])
            if cellval.display != otherval:
                return 'color_diff'
        else:
            return 'color_diff_add'

    return colorizeDiffs


def setDiffSheet(vs):
    Sheet.colorizers.append(CellColorizer(8, None, makeDiffColorizer(vs)))
예제 #4
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
예제 #5
0
def vdmenu(self):
    vs = VisiDataSheet('VisiData Main Menu', source=vd)
    vs.reload()
    return vs


def combineColumns(cols):
    'Return Column object formed by joining fields in given columns.'
    return Column("+".join(c.name for c in cols),
                  getter=lambda col, row, cols=cols, ch=' ': ch.join(
                      c.getDisplayValue(row) for c in cols))


# 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)',
예제 #6
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

예제 #7
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')
예제 #8
0
import os.path
import functools
import cProfile
import threading
import collections

from visidata import vd, option, options, status, globalCommand, Sheet, EscapeException
from visidata import elapsed_s, ColumnAttr, Column, ThreadsSheet, ENTER

option('profile', '', 'filename to save binary profiling data')

globalCommand('^_', 'toggle-profile',
              'toggleProfiling(threading.current_thread())')

ThreadsSheet.addCommand(
    ENTER, 'profile-row',
    'vd.push(ProfileSheet(cursorRow.name+"_profile", source=cursorRow.profile.getstats()))'
)

min_thread_time_s = 0.10  # only keep threads that take longer than this number of seconds


def open_pyprof(p):
    return ProfileSheet(p.name, p.open_bytes())


def toggleProfiling(t):
    if not t.profile:
        t.profile = cProfile.Profile()
        t.profile.enable()
        if not options.profile:
예제 #9
0
from visidata import globalCommand, Sheet, Column, options, vd, anytype, ENTER, asyncthread, option
from visidata import CellColorizer, RowColorizer
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()')

globalCommand('zO', 'options-sheet',
              'vd.push(getOptionsSheet(sheet)).reload()')
globalCommand('O', 'options-global', 'vd.push(vd.optionsSheet)')
Sheet.addCommand('C', 'columns-sheet',
                 'vd.push(ColumnsSheet(name+"_columns", source=[sheet]))')
globalCommand(
    '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
예제 #10
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'
예제 #11
0
    return SheetsSheet("sheets_all", source=vd.allSheets)

@VisiData.lazy_property
def sheetsSheet(vd):
    return SheetsSheet("sheets", source=vd.sheets)


@VisiData.api
def quit(vd, *sheets):
    if len(vd.sheets) == len(sheets) and options.quitguard:
        vd.confirm("quit last sheet? ")
    for vs in sheets:
        vd.remove(vs)


globalCommand('S', 'sheets-stack', 'vd.push(vd.sheetsSheet)', 'open Sheets Stack, which contains only the active sheets on the current stack')
globalCommand('gS', 'sheets-all', 'vd.push(vd.allSheetsSheet)', 'open Sheets Sheet, which contains all sheets from current session')

BaseSheet.addCommand('^R', 'reload-sheet', 'reload(); recalc(); status("reloaded")', 'reload current sheet'),
Sheet.addCommand('^G', 'show-cursor', 'status(statusLine)', 'show cursor position and bounds of current sheet on status line'),

Sheet.addCommand('!', 'key-col', 'toggleKeys([cursorCol])', 'toggle current column as a key column')
Sheet.addCommand('z!', 'key-col-off', 'unsetKeys([cursorCol])', 'unset current column as a key column')

Sheet.addCommand('e', 'edit-cell', 'cursorCol.setValues([cursorRow], editCell(cursorVisibleColIndex)); options.cmd_after_edit and sheet.exec_keystrokes(options.cmd_after_edit)', 'edit contents of current cell')
Sheet.addCommand('ge', 'setcol-input', 'cursorCol.setValuesTyped(selectedRows, input("set selected to: ", value=cursorDisplay))', 'set contents of current column for selected rows to same input')

Sheet.addCommand('"', 'dup-selected', 'vs=copy(sheet); vs.name += "_selectedref"; vs.reload=lambda vs=vs,rows=selectedRows: setattr(vs, "rows", list(rows)); vd.push(vs)', 'open duplicate sheet with only selected rows'),
Sheet.addCommand('g"', 'dup-rows', 'vs=copy(sheet); vs.name+="_copy"; vs.rows=list(rows); status("copied "+vs.name); vs.select(selectedRows); vd.push(vs)', 'open duplicate sheet with all rows'),
Sheet.addCommand('z"', 'dup-selected-deep', 'vs = deepcopy(sheet); vs.name += "_selecteddeepcopy"; vs.rows = async_deepcopy(vs, selectedRows); vd.push(vs); status("pushed sheet with async deepcopy of selected rows")', 'open duplicate sheet with deepcopy of selected rows'),
Sheet.addCommand('gz"', 'dup-rows-deep', 'vs = deepcopy(sheet); vs.name += "_deepcopy"; vs.rows = async_deepcopy(vs, rows); vd.push(vs); status("pushed sheet with async deepcopy of all rows")', 'open duplicate sheet with deepcopy of all rows'),
예제 #12
0
    '}', 'go-next-selected',
    'moveToNextRow(lambda row,sheet=sheet: sheet.isSelected(row)) or status("no next selected row")',
    'go down current column to next selected row'),

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

for i in range(1, 11):
    globalCommand(
        ALT + str(i)[-1], 'jump-sheet-' + str(i),
        'vd.push(*(list(s for s in allSheets if s.shortcut=="%s") or fail("no sheet")))'
        % {i}, f'jump to sheet {i}')

BaseSheet.bindkey('KEY_LEFT', 'go-left')
BaseSheet.bindkey('KEY_DOWN', 'go-down')
BaseSheet.bindkey('KEY_UP', 'go-up')
BaseSheet.bindkey('KEY_RIGHT', 'go-right')
BaseSheet.bindkey('KEY_HOME', 'go-leftmost')
BaseSheet.bindkey('KEY_END', 'go-rightmost')
BaseSheet.bindkey('KEY_NPAGE', 'go-pagedown')
BaseSheet.bindkey('KEY_PPAGE', 'go-pageup')

BaseSheet.bindkey('kHOM5', 'go-top')  # Ctrl+Home
BaseSheet.bindkey('KEY_EOL', 'go-bottom')  # Ctrl+End

BaseSheet.bindkey('gKEY_LEFT', 'go-leftmost'),
예제 #13
0
ProfileSheet.addCommand(
    'z^S', 'save-profile',
    'source.dump_stats(input("save profile to: ", value=name+".prof"))',
    'save profile')
ProfileSheet.addCommand(
    ENTER, 'dive-row',
    'vd.push(ProfileSheet(codestr(cursorRow.code)+"_calls", source=cursorRow.calls or fail("no calls")))',
    'open ProfileSheet for calls referenced in current row')
ProfileSheet.addCommand(
    'z' + ENTER, 'dive-cell',
    'vd.push(ProfileSheet(codestr(cursorRow.code)+"_"+cursorCol.name, source=cursorValue or fail("no callers")))',
    'open ProfileSheet for caller referenced in current cell')
ProfileSheet.addCommand(
    '^O', 'sysopen-row',
    'launchEditor(cursorRow.code.co_filename, "+%s" % cursorRow.code.co_firstlineno)',
    'open current file at referenced row in external $EDITOR')
globalCommand('^_', 'toggle-profile',
              'toggleProfiling(threading.current_thread())',
              'turn profiling on for main process')

BaseSheet.addCommand(
    '^C', 'cancel-sheet',
    'cancelThread(*sheet.currentThreads or fail("no active threads on this sheet"))',
    'abort all threads on current sheet')
globalCommand(
    'g^C', 'cancel-all',
    'liveThreads=list(t for vs in vd.sheets for t in vs.currentThreads); cancelThread(*liveThreads); status("canceled %s threads" % len(liveThreads))',
    'abort all secondary threads')
globalCommand('^T', 'threads-all', 'vd.push(vd.threadsSheet)',
              'open Threads Sheet')
예제 #14
0
def launchExternalEditor(v, linenum=0):
    import tempfile
    with tempfile.NamedTemporaryFile() as temp:
        with open(temp.name, 'w') as fp:
            fp.write(v)
        return launchExternalEditorPath(visidata.Path(temp.name))


def launchExternalEditorPath(path, linenum=0):
    if linenum:
        launchEditor(path, '+%s' % linenum)
    else:
        launchEditor(path)

    with open(path, 'r') as fp:
        try:
            return fp.read().rstrip('\n')  # trim inevitable trailing newlines
        except Exception as e:
            visidata.vd.exceptionCaught(e)
            return ''


def suspend():
    import signal
    with SuspendCurses():
        os.kill(os.getpid(), signal.SIGSTOP)


visidata.globalCommand('^Z', 'suspend', 'suspend()',
                       'suspend VisiData process')