예제 #1
0
def drawLeftStatus(vd, scr, vs):
    'Draw left side of status bar.'
    cattr = colors.get_color('color_status')
    active = vs is vd.sheets[0]  # active sheet
    if active:
        cattr = update_attr(cattr, colors.color_active_status, 0)
    else:
        cattr = update_attr(cattr, colors.color_inactive_status, 0)

    if scr is vd.winTop:
        cattr = update_attr(cattr, colors.color_top_status, 1)

    attr = cattr.attr
    error_attr = update_attr(cattr, colors.color_error, 1).attr
    warn_attr = update_attr(cattr, colors.color_warning, 2).attr
    sep = options.disp_status_sep

    x = 0
    y = vs.windowHeight - 1  # status for each window
    try:
        lstatus = vs.leftStatus()
        maxwidth = options.disp_lstatus_max
        if maxwidth > 0:
            lstatus = middleTruncate(lstatus, maxwidth // 2)

        x = clipdraw(scr, y, 0, lstatus, attr, w=vs.windowWidth - 1)

        vd.onMouse(scr,
                   y,
                   0,
                   1,
                   x,
                   BUTTON1_PRESSED='sheets',
                   BUTTON3_PRESSED='rename-sheet',
                   BUTTON3_CLICKED='rename-sheet')
    except Exception as e:
        vd.exceptionCaught(e)

    if not active:
        return

    one = False
    for (pri, msgparts), n in sorted(vd.statuses.items(),
                                     key=lambda k: -k[0][0]):
        try:
            if x > vs.windowWidth:
                break
            if one:  # any messages already:
                x += clipdraw(scr, y, x, sep, attr, w=vs.windowWidth - x)
            one = True
            msg = composeStatus(msgparts, n)

            if pri == 3: msgattr = error_attr
            elif pri == 2: msgattr = warn_attr
            elif pri == 1: msgattr = warn_attr
            else: msgattr = attr
            x += clipdraw(scr, y, x, msg, msgattr, w=vs.windowWidth - x)
        except Exception as e:
            vd.exceptionCaught(e)
예제 #2
0
    def drawColHeader(self, scr, y, h, vcolidx):
        'Compose and draw column header for given vcolidx.'
        col = self.visibleCols[vcolidx]

        # hdrattr highlights whole column header
        # sepattr is for header separators and indicators
        sepcattr = colors.get_color('color_column_sep')

        hdrcattr = self._colorize(col, None)
        if vcolidx == self.cursorVisibleColIndex:
            hdrcattr = update_attr(hdrcattr, colors.color_current_hdr, 2)

        C = options.disp_column_sep
        if (self.keyCols and col is self.keyCols[-1]) or vcolidx == self.rightVisibleColIndex:
            C = options.disp_keycol_sep

        x, colwidth = self._visibleColLayout[vcolidx]

        # AnameTC
        T = getType(col.type).icon
        if T is None:  # still allow icon to be explicitly non-displayed ''
            T = '?'

        hdrs = col.name.split('\n')
        for i in range(h):
            name = ' '  # save room at front for LeftMore
            if h-i-1 < len(hdrs):
                name += hdrs[::-1][h-i-1]

            if len(name) > colwidth-1:
                name = name[:colwidth-len(options.disp_truncator)] + options.disp_truncator

            if i == h-1:
                hdrcattr = update_attr(hdrcattr, colors.color_bottom_hdr, 5)

            clipdraw(scr, y+i, x, name, hdrcattr.attr, colwidth)
            vd.onMouse(scr, y+i, x, 1, colwidth, BUTTON3_RELEASED='rename-col')

            if C and x+colwidth+len(C) < self.windowWidth:
                scr.addstr(y+i, x+colwidth, C, sepcattr.attr)

        clipdraw(scr, y+h-1, x+colwidth-len(T), T, hdrcattr.attr)

        try:
            if vcolidx == self.leftVisibleColIndex and col not in self.keyCols and self.nonKeyVisibleCols.index(col) > 0:
                A = options.disp_more_left
                scr.addstr(y, x, A, sepcattr.attr)
        except ValueError:  # from .index
            pass
예제 #3
0
def input(scr, prompt, **kwargs):
    ymax, xmax = scr.getmaxyx()
    promptlen = visidata.clipdraw(scr, ymax - 1, 0, prompt, 0, w=xmax - 1)

    r = visidata.vd.editline(scr, ymax - 1, promptlen, xmax - promptlen - 2,
                             **kwargs)
    curses.flushinp()
    return r
예제 #4
0
def drawRightStatus(vd, scr, vs):
    'Draw right side of status bar.  Return length displayed.'
    rightx = vs.windowWidth

    ret = 0
    statcolors = [
        (vd.rightStatus(vs), 'color_status'),
    ]

    active = vs is vd.sheets[0]  # active sheet

    if active:
        statcolors.append((vd.keystrokes, 'color_keystrokes'))

    if vs.currentThreads:
        statcolors.insert(0, vd.checkMemoryUsage())
        if vs.progresses:
            gerund = vs.progresses[0].gerund
        else:
            gerund = 'processing'
        statcolors.insert(1, ('  %s %s…' %
                              (vs.progressPct, gerund), 'color_status'))

    if active and vd.currentReplay:
        statcolors.insert(0, (vd.replayStatus, 'color_status_replay'))

    for rstatcolor in statcolors:
        if rstatcolor:
            try:
                rstatus, coloropt = rstatcolor
                rstatus = ' ' + rstatus
                cattr = colors.get_color(coloropt)
                if scr is vd.winTop:
                    cattr = update_attr(cattr, colors.color_top_status, 0)
                if active:
                    cattr = update_attr(cattr, colors.color_active_status, 0)
                else:
                    cattr = update_attr(cattr, colors.color_inactive_status, 0)
                statuslen = clipdraw(scr,
                                     vs.windowHeight - 1,
                                     rightx,
                                     rstatus,
                                     cattr.attr,
                                     w=vs.windowWidth - 1,
                                     rtl=True)
                rightx -= statuslen
                ret += statuslen
            except Exception as e:
                vd.exceptionCaught(e)

    if scr:
        curses.doupdate()
    return ret
예제 #5
0
def input(self, prompt, type=None, defaultLast=False, history=[], **kwargs):
    '''Display prompt and return line of user input.

        type: list of previous items, or a string indicating the type of input.
        defaultLast:  on empty input, if True, return last history item
    '''
    if type:
        if isinstance(type, str):
            history = self.lastInputs[type]
        else:
            history = type

    sheet = self.sheets[0]
    rstatuslen = self.drawRightStatus(sheet._scr, sheet)
    attr = 0
    promptlen = clipdraw(sheet._scr,
                         sheet.windowHeight - 1,
                         0,
                         prompt,
                         attr,
                         w=sheet.windowWidth - rstatuslen - 1)
    ret = self.editText(sheet.windowHeight - 1,
                        promptlen,
                        sheet.windowWidth - promptlen - rstatuslen - 2,
                        attr=colors.color_edit_cell,
                        unprintablechar=options.disp_unprintable,
                        truncchar=options.disp_truncator,
                        history=history,
                        **kwargs)

    if ret:
        if isinstance(type, str):
            self.lastInputs[type].append(ret)
    elif defaultLast:
        history or fail("no previous input")
        ret = history[-1]

    return ret
예제 #6
0
def editline(vd,
             scr,
             y,
             x,
             w,
             i=0,
             attr=curses.A_NORMAL,
             value='',
             fillchar=' ',
             truncchar='-',
             unprintablechar='.',
             completer=lambda text, idx: None,
             history=[],
             display=True,
             updater=lambda val: None):
    'A better curses line editing widget.'
    with EnableCursor():
        ESC = '^['
        ENTER = '^J'
        TAB = '^I'

        history_state = HistoryState(history)
        complete_state = CompleteState(completer)
        insert_mode = True
        first_action = True
        v = str(value)  # value under edit

        # i = 0  # index into v, initial value can be passed in as argument as of 1.2
        if i != 0:
            first_action = False

        left_truncchar = right_truncchar = truncchar

        def rfind_nonword(s, a, b):
            if not s:
                return 0

            while not s[b].isalnum() and b >= a:  # first skip non-word chars
                b -= 1
            while s[b].isalnum() and b >= a:
                b -= 1
            return b

        while True:
            updater(v)

            if display:
                dispval = clean_printable(v)
            else:
                dispval = '*' * len(v)

            dispi = i  # the onscreen offset within the field where v[i] is displayed
            if len(dispval) < w:  # entire value fits
                dispval += fillchar * (w - len(dispval) - 1)
            elif i == len(dispval):  # cursor after value (will append)
                dispi = w - 1
                dispval = left_truncchar + dispval[len(dispval) - w +
                                                   2:] + fillchar
            elif i >= len(dispval) - w // 2:  # cursor within halfwidth of end
                dispi = w - (len(dispval) - i)
                dispval = left_truncchar + dispval[len(dispval) - w + 1:]
            elif i <= w // 2:  # cursor within halfwidth of beginning
                dispval = dispval[:w - 1] + right_truncchar
            else:
                dispi = w // 2  # visual cursor stays right in the middle
                k = 1 if w % 2 == 0 else 0  # odd widths have one character more
                dispval = left_truncchar + dispval[i - w // 2 + 1:i + w // 2 -
                                                   k] + right_truncchar

            prew = clipdraw(scr, y, x, dispval[:dispi], attr, w)
            clipdraw(scr, y, x + prew, dispval[dispi:], attr, w - prew + 1)
            scr.move(y, x + prew)
            ch = vd.getkeystroke(scr)
            if ch == '': continue
            elif ch == 'KEY_IC': insert_mode = not insert_mode
            elif ch == '^A' or ch == 'KEY_HOME': i = 0
            elif ch == '^B' or ch == 'KEY_LEFT': i -= 1
            elif ch in ('^C', '^Q', ESC): raise EscapeException(ch)
            elif ch == '^D' or ch == 'KEY_DC': v = delchar(v, i)
            elif ch == '^E' or ch == 'KEY_END': i = len(v)
            elif ch == '^F' or ch == 'KEY_RIGHT': i += 1
            elif ch in ('^H', 'KEY_BACKSPACE', '^?'):
                i -= 1
                v = delchar(v, i)
            elif ch == TAB:
                v, i = complete_state.complete(v, i, +1)
            elif ch == 'KEY_BTAB':
                v, i = complete_state.complete(v, i, -1)
            elif ch == ENTER:
                break
            elif ch == '^K':
                v = v[:i]  # ^Kill to end-of-line
            elif ch == '^O':
                v = launchExternalEditor(v)
            elif ch == '^R':
                v = str(value)  # ^Reload initial value
            elif ch == '^T':
                v = delchar(splice(v, i - 2, v[i - 1]), i)  # swap chars
            elif ch == '^U':
                v = v[i:]
                i = 0  # clear to beginning
            elif ch == '^V':
                v = splice(v, i, until_get_wch(scr))
                i += 1  # literal character
            elif ch == '^W':
                j = rfind_nonword(v, 0, i - 1)
                v = v[:j + 1] + v[i:]
                i = j + 1  # erase word
            elif ch == '^Z':
                suspend()
            elif history and ch == 'KEY_UP':
                v, i = history_state.up(v, i)
            elif history and ch == 'KEY_DOWN':
                v, i = history_state.down(v, i)
            elif ch.startswith('KEY_'):
                pass
            else:
                if first_action:
                    v = ''
                if insert_mode:
                    v = splice(v, i, ch)
                else:
                    v = v[:i] + ch + v[i + 1:]

                i += 1

            if i < 0: i = 0
            if i > len(v): i = len(v)
            first_action = False
            complete_state.reset()

        return v
예제 #7
0
    def drawRow(self, scr, row, rowidx, ybase, rowcattr: ColorAttr, maxheight,
            isNull='',
            topsep='',
            midsep='',
            botsep='',
            endsep='',
            keytopsep='',
            keymidsep='',
            keybotsep='',
            endtopsep='',
            endmidsep='',
            endbotsep='',
            colsep='',
            keysep='',
            selectednote=''
       ):

            # sepattr is the attr between cell/columns
            sepcattr = update_attr(rowcattr, colors.color_column_sep, 1)

            # apply current row here instead of in a colorizer, because it needs to know dispRowIndex
            if rowidx == self.cursorRowIndex:
                color_current_row = colors.get_color('color_current_row', 5)
                basecellcattr = sepcattr = update_attr(rowcattr, color_current_row)
            else:
                basecellcattr = rowcattr

            displines = {}  # [vcolidx] -> list of lines in that cell

            for vcolidx, (x, colwidth) in sorted(self._visibleColLayout.items()):
                if x < self.windowWidth:  # only draw inside window
                    vcols = self.visibleCols
                    if vcolidx >= len(vcols):
                        continue
                    col = vcols[vcolidx]
                    cellval = col.getCell(row)
                    if colwidth > 1 and isNumeric(col):
                        cellval.display = cellval.display.rjust(colwidth-2)

                    try:
                        if isNull(cellval.value):
                            cellval.note = options.disp_note_none
                            cellval.notecolor = 'color_note_type'
                    except (TypeError, ValueError):
                        pass

                    if col.height > 1:
                        lines = splitcell(cellval.display, width=colwidth-2)
                    else:
                        lines = [cellval.display]
                    displines[vcolidx] = (col, cellval, lines)

            heights = [0]
            for col, cellval, lines in displines.values():
                h = len(lines)   # of this cell
                heights.append(min(col.height, h))

            height = min(max(heights), maxheight) or 1  # display even empty rows

            self._rowLayout[rowidx] = (ybase, height)

            for vcolidx, (col, cellval, lines) in displines.items():
                    if vcolidx not in self._visibleColLayout:
                        continue
                    x, colwidth = self._visibleColLayout[vcolidx]

                    cattr = self._colorize(col, row, cellval)
                    cattr = update_attr(cattr, basecellcattr)

                    note = getattr(cellval, 'note', None)
                    if note:
                        notecattr = update_attr(cattr, colors.get_color(cellval.notecolor), 10)
                        clipdraw(scr, ybase, x+colwidth-len(note), note, notecattr.attr)

                    if len(lines) > height:
                        firstn = sum(len(i)+1 for i in lines[:height-1])
                        lines[height-1] = cellval.display[firstn:]
                        del lines[height:]
                    elif len(lines) < height:
                        lines.extend(['']*(height-len(lines)))

                    for i, line in enumerate(lines):
                        y = ybase+i

                        if vcolidx == self.rightVisibleColIndex:  # right edge of sheet
                            if len(lines) == 1:
                                sepchars = endsep
                            else:
                                if i == 0:
                                    sepchars = endtopsep
                                elif i == len(lines)-1:
                                    sepchars = endbotsep
                                else:
                                    sepchars = endmidsep
                        elif (self.keyCols and col is self.keyCols[-1]): # last keycol
                            if len(lines) == 1:
                                sepchars = keysep
                            else:
                                if i == 0:
                                    sepchars = keytopsep
                                elif i == len(lines)-1:
                                    sepchars = keybotsep
                                else:
                                    sepchars = keymidsep
                        else:
                            if len(lines) == 1:
                                sepchars = colsep
                            else:
                                if i == 0:
                                    sepchars = topsep
                                elif i == len(lines)-1:
                                    sepchars = botsep
                                else:
                                    sepchars = midsep

                        clipdraw(scr, y, x, disp_column_fill+line, cattr.attr, w=colwidth-(1 if note else 0))
                        vd.onMouse(scr, y, x, 1, colwidth, BUTTON3_RELEASED='edit-cell')

                        if x+colwidth+len(sepchars) <= self.windowWidth:
                            scr.addstr(y, x+colwidth, sepchars, basecellcattr.attr)

            if self.isSelected(row):
                clipdraw(scr, ybase, 0, selectednote, basecellcattr.attr)

            return height