monome / crow

Crow speaks and listens and remembers bits of text. A scriptable USB-CV-II machine
GNU General Public License v3.0
165 stars 34 forks source link

queryable help functions #36

Closed trentgill closed 4 years ago

trentgill commented 5 years ago
> midi.showevents() -- midi.help() -- m.help()
crow.m.note_on = function( note, velocity, channel )
  — handle a note_on
end

…

> input.showevents() -- input.help()
crow.input.change = function( channel, direction )
  — handle a detected rising/falling event
end
crow.input.stream = function( channel, value )
  — handle a stream of values read from the CV input jack
end
...

the above could be called with m.help() or input.help() and also give a line or two of how to use it. this kind of locally stored documentation seems like a great way to minimize the need for being connected to the internet when you’re already somewhat familiar with how it works. i can implement those things in C so they don’t have RAM implications, just flash. obviously they need to be as short as possible so they don’t flood the repl and take ages to send over the pipe.

of course we could add a help() global function which prints out how to use the via-repl-help functions and gives a list of the different modules that are available. this stuff seems like it could happen quickly once we have the readline app working, as i’m sure this ideas will need to be massaged into working in that context, vs working in maiden (is that how a user will talk to crow for norns?).

> help()
--- CAW! this is crow help.
-- crow has the following modules loaded:
_c -- crow standard library
input -- CV input
out -- CV output
m -- MIDI input
metro -- Timers & metronomes
asl -- 'a slope language'
asllib -- standard slopes

-- you can find out available functions by typing <module_name>.help(), like this:
input.help()
tehn commented 5 years ago

i like this idea! how do you feel about flash usage for this?

on norns now, when i forget a function name in a lib i use (for example): tab.print(metro) and it gives a function dump (tab.print is a simple helper function). luadocs are hosted on-device but i really don't like it so much.

of course, norns has so many functions so the luadoc helps auto-sort everything. maintaining a changing lib would be somewhat difficult--- tracking and manually editing the .help() print functions (but not insurmountable). of course with crow the libs are incredibly constrained so this is a nice alternative to web-hosted docs etc.

though of course i plan to make a nice reference sheet also!

yes i like the idea indeed (if flash permits)


aside: i don't think there's a real benefit to shortening midi to m

trentgill commented 5 years ago

i take your point on maintainability of the docs. i propose to add a convention whereby any function the user should be able to call from a script or the repl is preceded by an single line comment: --expose_help

it's then easy to write a lua script to scan all the files in /lua and generate a C char[] for each file, only including those lines. i'm already doing this for the i2c descriptors, so i can probably just lift most of the parsing from there. then these char arrays are wrapped in a single C-header and included in lualink.

thoughts on what the symbol should be? i want to make sure it's clear to a developer what the flag is meant for.

tehn commented 5 years ago

norns libs use ldoc which has some syntax conventions, ie https://github.com/monome/norns/blob/master/lua/engine.lua

i'd suggest something like

-- @help helper text for the function below
function do_stuff()

if it's a pain to parse this you could even add the function name as the first arg after the tag ie

-- @help do_stuff helper text for the function below
function do_stuff()

and then build the help table with the first word as the index... would mean the help tag doesn't necessarily need to have an enforced position

trentgill commented 5 years ago

thanks for these points. i never undertood the @ convention that i've seen in source code for years! haha

i'm not going to try running ldoc on crow itself, mostly because we don't want these helpers to build strings in the lua environment for speed & ram reasons. the l2h util is already stripping all comment lines from the source before it's uploaded.

but i will try and follow this convention. in contrast to norns, i'm thinking that often we don't need 'helper text' at all, but rather, the help() printout is really just the function prototypes. this makes sure argument names are well chosen because they should also be self-documenting! the only trick is giving a name to return values and printing a different prototype if the function returns a value. see:

climb_n_stairs( number_of_stairs )
-- vs
stairs = stairs_climbed_so_far()

both of the above would be printed exactly like that, so they can be dropped in and the user just has to change the argument in the first, and the return value in the second.

this requires the equivalent of @return in ldoc. perhaps we can use @help and @helpR return_name though i appreciate the 'R' is very opaque to the casual reader. better ideas?

i don't think the parsing will be too hard (i'll do it in a lua script), and building the c header is easy.

tehn commented 5 years ago

oh i wasn't suggesting we add ldoc onboard!

i suspect that a one-line description might still be enlightening as to the function's purpose, but i agree that well-documented args will do much to clarify.

my inclination is to make the implementation more dumb. ie, just capture the @help text per function and display whatever is there... not get too fancy... but i'll defer to your designs

trentgill commented 4 years ago

I think my initial idea here was a little too far-reaching for the constrained context. Main issues:

  1. Names/spelling of functions in a library
  2. Arguments to a given function
  3. How fns work (eg. does x() change the table?)

Some proposed solutions:

  1. Add a tab.print() function like you mentioned (it's so easy! should have done it long ago!)
  2. Add args() function which takes a function as argument, and prints the first line of the source of that function. This should cover most crow-library functions (that are statically defined in flash)
  3. Add source() function which takes a function as argument, and prints the whole source of that function. This is more difficult because it requires matching ends. Perhaps there is access to the lua parser in the VM to do this automatically (using debug library?).
trentgill commented 4 years ago

Closing this as it seems we're running out of Flash space and it feels a better fit for the druid environment or similar.