Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

New Guides API #2134

Merged
merged 11 commits into from
Nov 26, 2023
1 change: 1 addition & 0 deletions visidata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def getGlobals():
import visidata.textsheet
import visidata.threads
import visidata.path
import visidata.guide

import visidata._input
import visidata.tuiwin
Expand Down
1 change: 1 addition & 0 deletions visidata/cliptext.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ def clipdraw_chunks(scr, y, x, chunks, cattr:ColorAttr=ColorAttr(), w=None, clea
def _markdown_to_internal(text):
'Return markdown-formatted `text` converted to internal formatting (like `[:color]text[/]`).'
text = re.sub(r'`(.*?)`', r'[:code]\1[/]', text)
text = re.sub(r'(#.*?)$', r'[:h1]\1[/]', text)
text = re.sub(r'\*\*(.*?)\*\*', r'[:bold]\1[/]', text)
text = re.sub(r'\*(.*?)\*', r'[:italic]\1[/]', text)
text = re.sub(r'\b_(.*?)_\b', r'[:underline]\1[/]', text)
Expand Down
61 changes: 54 additions & 7 deletions visidata/experimental/guide.py → visidata/guide.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
'''
# A Guide to VisiData Guides
Each guide shows you how to use a particular feature in VisiData.
Each guide shows you how to use a particular feature in VisiData. Gray guides have not been written yet. Why not contribute one?
anjakefala marked this conversation as resolved.
Show resolved Hide resolved

[:keys]Up/Down[/] to move the row cursor
[:keys]Enter[/] to view a topic
[:keys]Backspace[/] to come back to this list of guides
- [:keystrokes]Up/Down[/] to move the row cursor
- [:keystrokes]Enter[/] to view a topic
- [:keystrokes]Backspace[/] to come back to this list of guides
Copy link
Owner

@saulpw saulpw Nov 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this (- [:keystrokes]gg[/] to {helpstr}) should be the general pattern for commands.

'''

import re

from visidata import vd, BaseSheet, Sheet, ItemColumn, Column, VisiData
from visidata import vd, BaseSheet, Sheet, ItemColumn, Column, VisiData, ENTER, RowColorizer
from visidata import wraptext

vd.guides = {} # guidename -> guideobj

@VisiData.api
def addGuide(vd, guidename, guideobj):
vd.guides[guidename] = guideobj

@VisiData.api
class GuideGuide(Sheet):
help = __doc__
columns = [
ItemColumn('n', 0, type=int),
ItemColumn('sheetname', 1, width=0),
ItemColumn('guidename', 1, width=0),
anjakefala marked this conversation as resolved.
Show resolved Hide resolved
ItemColumn('topic', 2, width=60),
Column('points', type=int, getter=lambda c,r: 0),
Column('max_points', type=int, getter=lambda c,r: 100),
]
colorizers = [
RowColorizer(7, 'color_guide_dne', lambda s,c,r,v: r and r[1] not in vd.guides)
anjakefala marked this conversation as resolved.
Show resolved Hide resolved
]
def iterload(self):
i = 0
for line in '''
Expand Down Expand Up @@ -86,4 +95,42 @@ def iterload(self):
yield [i] + list(m.groups())
i += 1

BaseSheet.addCommand('', 'open-guide', 'vd.push(GuideGuide("VisiData_Guide"))')
def openRow(self, row):
guidename = row[1]
return vd.getGuide(guidename)

class GuideSheet(Sheet):
rowtype = 'lines'
filetype = 'guide'
columns = [
ItemColumn('linenum', 0, type=int, width=0),
ItemColumn('guide', 1, width=80, displayer='full'),
]
precious = False
guide = ''

def iterload(self):
winWidth = 78
for startingLine, text in enumerate(self.guide.splitlines()):
text = text.strip()
if text:
for i, (L, _) in enumerate(wraptext(str(text), width=winWidth)):
yield [startingLine+i+1, L]
else:
yield [startingLine+1, text]



@VisiData.api
def getGuide(vd, guidename):
if guidename in vd.guides:
return vd.guides[guidename]
vd.warning(f'there is no guide: {guidename}')
anjakefala marked this conversation as resolved.
Show resolved Hide resolved

BaseSheet.addCommand('', 'open-guide', 'vd.push(GuideGuide("VisiData_Guide"))', 'opens guide to features in VisiData')
anjakefala marked this conversation as resolved.
Show resolved Hide resolved

vd.addMenuItems('''
Help > Guide > open-guide
anjakefala marked this conversation as resolved.
Show resolved Hide resolved
''')

vd.addGlobals({'GuideSheet':GuideSheet})
2 changes: 2 additions & 0 deletions visidata/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
vd.theme_option('color_selected_row', '215 yellow', 'color of selected rows')
vd.theme_option('color_clickable', 'underline', 'color of internally clickable item')
vd.theme_option('color_code', 'bold white on 237', 'color of code sample')
vd.theme_option('color_h1', 'bold 200', 'color of h1 header')
anjakefala marked this conversation as resolved.
Show resolved Hide resolved
vd.theme_option('color_guide_unwritten', '243 on black', 'color of unwritten guides in GuideGuide')

vd.theme_option('force_256_colors', False, 'use 256 colors even if curses reports fewer')

Expand Down
26 changes: 24 additions & 2 deletions visidata/macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from visidata.cmdlog import CommandLog, CommandLogJsonl
from visidata import vd, UNLOADED, asyncthread
from visidata import IndexSheet, VisiData, Sheet, Path, VisiDataMetaSheet, Column, ItemColumn, BaseSheet
from visidata import IndexSheet, VisiData, Sheet, Path, VisiDataMetaSheet, Column, ItemColumn, BaseSheet, GuideSheet

vd.macroMode = None
vd.macrobindings = {}
Expand Down Expand Up @@ -125,15 +125,37 @@ def startMacro(cmdlog):
vd.status("recording macro; stop recording with `m`")
vd.macroMode = CommandLogJsonl('current_macro', rows=[])


@VisiData.before
def run(vd, *args, **kwargs):
vd.macrosheet

class MacrosGuide(GuideSheet):
guide = '''# Macros
Macros allow you to bind a series of commands to a key and then replay those commands within a session by using that keystroke.
anjakefala marked this conversation as resolved.
Show resolved Hide resolved

The basic usage is:
1. Press `m` (macro-record) to begin recording the macro.
2. Go through the commands you wish to record.
3. Then type `m` again to complete the recording, and prompt for the keystroke or longname to bind it to.

The macro will then be executed everytime the provided keystroke is used. Note: the Alt+keys and the function keys are left unbound; overridding other keys may conflict with existing bindings, now or in the future.

Executing a macro will the series of commands starting on the current row and column on the current sheet.

# The Macros Sheet

Use `gm` (`macro-sheet`) to open an index existing macros.

Macros can be marked for deletion (with `d`). Changes can then be committed with `z Ctrl+S`.

`Enter` will open the macro in the current row, and you can view the series of commands composing it.'''


Sheet.addCommand('m', 'macro-record', 'vd.cmdlog.startMacro()', 'record macro')
Sheet.addCommand('gm', 'macro-sheet', 'vd.push(vd.macrosheet)', 'open macros sheet')

vd.addMenuItems('''
System > Macros sheet > macro-sheet
''')

vd.addGuide('MacrosSheet', MacrosGuide())
Loading