NFOs are a standardized format for documenting a user's scripts, as well as their usage and arguments. They are hosted under a user's "nfo" script (i.e. on @kaitlyn, I would upload kaitlyn.nfo). The information is public, and designed to be easily accessible for other scripts.
"the main idea of a standard is other scripts can tie into it; i.e. i'll have ls pull brief usage out to make ls listings more useful, kait will make a fuller man page viewer, etc" - @dtr
The format looks like this:
{
version: "1.0.0", // semver, incase we decide on any major structure changes
scripts: {
scriptname: { // scriptname isn't literal, for example if this was for kaitlyn.profiles, i would call this profiles
usage: "{to: \"user\", msg: \"msg\" }", // usage example, as seen in scripts like sys.manage, generally your "default args"
desc: "a description of the purpose of the script, and maybe general use cases",
// we typically try to use "modes" to categorize arguments, if this applies to your script then they are used like this:
modes: [
{
name: "mode1",
args: [
{name:"arg1",type:"expected typeof, i.e. string, truthy, object/boolean",optional:false,desc:"description of argument"}
],
desc: "description of mode",
returns: "description of what data to expect in return, i.e. \"object if is_script, otherwise string\""
}
],
// if you don't think your script has "modes" that it can be categorized into, then just use args and returns on the top level, like this:
args: [
{name:"arg1", type:"expected typeof, i.e. string, truthy, object/boolean", optional:true, desc:"description of argument"}
],
returns: "ok object",
subscript: true, // can your script be subscripted?
scriptor: false, // can your script be used as a scriptor?
cli: false // can your script be used on the cli?
}
}
}
As a practical demonstration, here is the source of kaitlyn.nfo:
function() {
return {
version: "1.0.0",
scripts: {
identicon: {
usage: "{ info: true }",
desc: "hackmud implementation of http:/\/identicon.net/",
args: [
{name:"bg", type:"string",optional:true,desc:"color code for \"background\" pixels, default is z"},
{name:"box", type:"truthy",optional:true,desc:"draws a box around generated identicon"},
{name:"boxc",type:"string",optional:true,desc:"sets color of box if box is true"},
{name:"chat",type:"truthy",optional:true,desc:"sends identicon to specified channel"},
{name:"fg", type:"string",optional:true,desc:"color code for \"foreground\" pixels, default is determined by username"},
{name:"s", type:"string",optional:true,desc:"string to be hashed for identicon generation. default is caller's username"}
],
returns: "string",
subscript: true,
scriptor: true,
cli: true
},
mark: {
usage: null,
desc: "marks caller",
args: [],
returns: "string",
subscript: true,
scriptor: true,
cli: true
},
parse_specs: {
usage: null,
desc: "script-friendly sys.specs output. uses #hs.sys.specs\() if no args, otherwise uses args (whole thing) as specs",
args: "sys.specs string",
returns: "object",
subscript: true,
scriptor: true,
cli: true
},
profiles: {
usage: "{ view: \"user\" }",
desc: "public users.inspect profile database",
modes: [
{
args: [
{name:"changelog",type:"truthy",optional:true,desc:"displays script changelog history"}
],
desc: "defaults",
returns: "string"
},
{
name: "add",
args: [
{name:"add",type:"string",optional:false,desc:"user whose profile to add to the database"},
{name:"s",type:"scriptor",optional:false,desc:"users.inspect scriptor, to view user's profile. can be circumvented with kaitlyn.highsec_profiles"}
],
desc: "when both add and s are passed, and a channel (or hardline connection) is shared with user specified in add, adds user to the database.",
returns: "database object if is_script, otherwise string"
},
{
name: "view",
args: [
{name:"name",type:"string",optional:false,desc:"user whose profile to view",aliases:["view"]},
],
desc: "displays profile of specified user.",
returns: "database object if is_script, otherwise string"
},
{
name: "list",
args: [
{name:"list",type:"truthy/number",optional:false,desc:"activates list mode. if number, takes the place of page"},
{name:"page",type:"number",optional:true,desc:"page of list to view."}
],
desc: "displays a paginated list of (unhidden) profiles, or an unpaginated list if page is \"all\".",
returns: "string"
},
{
name: "search",
args: [
{name:"search",type:"object",optional:false,desc:"mongodb-style query object"}
],
desc: "searches full database, including hidden profiles, using provided query. please play nice",
returns: "string"
},
{
name: "data",
args: [
{name:"data",type:"string",optional:false,desc:"which dataset to view. currently supports avatars, badges, or titles"}
],
desc: "returns various datasets",
returns: "object if is_script, otherwise string"
}
],
subscript: true,
scriptor: true,
cli: true
},
top_users: {
usage: null,
desc: "pretty users.top output, using data from kaitlyn.profiles for avatar and corp",
args: [],
returns: "object if is_script, otherwise string",
subscript: true,
scriptor: true,
cli: true
},
useful_forum_posts: {
usage: null,
desc: "list of useful guides or references from the forums",
args: [],
returns: "string",
subscript: true,
scriptor: true,
cli: true
}
}
}
}