Files
Mush-Soundpack/cosmic rage/worlds/plugins/MUSHclient_Help.xml
2025-07-01 23:28:00 +03:00

565 lines
15 KiB
XML

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<muclient>
<plugin
name="MUSHclient_Help"
author="Nick Gammon"
id="d2fa45d390d935d947cdc169"
language="Lua"
purpose="Shows the MUSHclient help file"
save_state="y"
date_written="2011-06-13 08:58:30"
date_modified="2016-07-17 12:25"
requires="4.76"
version="1.1"
>
<description trim="y">
<![CDATA[
To get general help:
mchelp <search string>
mchelps <search string> --> get help with snippet (context) shown
mchelp <number> --> show help on numbered item from previous search
mchelp --> on its own, shows this help
Search strings can have boolean operators in them, namely the words:
AND NEAR NOT OR
These words must be in all capitals or they are just searched for literally.
For example:
mchelp trigger AND alias
mchelp delete AND trigger NEAR count
mchelp search NOT table
mchelp search -table
mchelp add OR delete
mchelp next NEAR/5 table
mchelp add AND (trigger OR alias)
(The syntax NEAR/5 means if one word is within 5 words of another word, the default is 10)
You can use a wildcard suffix, eg.
mchelp trigg*
You can look for phrases by putting them in quotes, eg.
mchelp "hash a string"
You can restrict the lookup to the item name (eg. the function name) like this:
mchelp name:utils.*
]]>
</description>
</plugin>
<!-- Aliases -->
<aliases>
<alias
script="help_find"
match="^mchelp (.+)$"
enabled="y"
group="help"
regexp="y"
sequence="100"
>
</alias>
<alias
script="help_number"
match="^mchelp (\d+)$"
enabled="y"
group="help"
regexp="y"
sequence="90"
>
</alias>
<alias
script="help_find_snippet"
match="^mchelps (.+)$"
enabled="y"
group="help"
regexp="y"
sequence="100"
>
</alias>
<alias
script="OnHelp"
match="^mchelps?$"
enabled="y"
regexp="y"
>
</alias>
</aliases>
<!-- Script -->
<script>
<![CDATA[
require "pairsbykeys"
-- major headings
local HEADINGCOLOUR = "yellow"
local NAMECOLOUR = "cyan"
local SUMMARYCOLOUR = "white"
local PROTOTYPECOLOUR = "cyan"
local DESCRIPTIONCOLOUR = "white"
local NOTESCOLOUR = "white"
local HELPCOLOUR = "indianred"
-- tags (eg. bold, italic)
local CODECOLOUR = "greenyellow"
local RETURNVALUE = "thistle"
local BOLDCOLOUR = "orange"
local ITALICCOLOUR = "linen"
-- for snippets
local RESET = ANSI (0)
local BOLD = ANSI (1)
local UNBOLD = ANSI (22)
local SNIPPETSIZE = -15 -- how many tokens to show around snippet
local styles
-- SQL fixup function
local function fixsql (s)
-- replace single quotes with two lots of single quotes
if s then
return "'" .. (string.gsub (s, "'", "''")) .. "'"
end -- if string exists
return "NULL"
end -- fixsql
-- for fixing up entities
local entities = {
["&lt;"] = "<";
["&gt;"] = ">";
["&amp;"] = "&";
["&quot;"] = "\"";
} -- end of entities
-- what to do on getting a tag like <b>
local tag_handlers = {
["<b>"] = function () SetNoteColourFore (ColourNameToRGB (BOLDCOLOUR)) end;
["<i>"] = function () SetNoteColourFore (ColourNameToRGB (ITALICCOLOUR)) end;
["<code>"] = function () SetNoteColourFore (ColourNameToRGB (CODECOLOUR)) end;
["<ul>"] = function () end;
["<li/>"] = function () Tell (" * ") end;
["<hr/>"] = function () NoteHr () end;
} -- end of tag_handlers
-- called by LPEG to output an opening, closing, or empty tag
local function tag_output (tag)
-- restore colour on closing tag, save colour on nested tag
if tag:sub (2, 2) == "/" then
SetNoteColourFore (table.remove (styles))
elseif tag:sub (-2, -2) ~= "/" then
table.insert (styles, GetNoteColourFore () )
end -- if
local f = tag_handlers [tag:lower ()]
if f then
f ()
end -- if handler found
end -- tag_output
-- called by LPEG to output straight text
local function text_output (text)
-- fix up entities like &lt;
Tell ((text:gsub ("&%a-;", entities)))
end -- text_output
-- LPEG grammar for (simplified) HTML
local P, R, S, C, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Ct
local TAG = (P"<" * P"/"^-1 * R("AZ", "az")^1 * P"/"^-1 * P">")/tag_output
local NOT_TAG = ((1 - lpeg.P"<")^0/text_output)
local HTML = (NOT_TAG * TAG * NOT_TAG)^1 + NOT_TAG
-- show a help item with a coloured heading, and coloured text
local function show_item (hdg_colour, hdg, text_colour, text, tagged)
if text and text ~= "" then
if hdg and hdg ~= "" then
ColourNote (hdg_colour, "", hdg)
print ""
end -- if any heading
if tagged then
local notecolour = GetNoteColourFore ()
styles = {} -- nested styles - start off with none
SetNoteColourFore (ColourNameToRGB (text_colour))
lpeg.match (HTML, text)
SetNoteColourFore (notecolour)
print "" -- probably doesn't end with newline
else
ColourNote (text_colour, "", text)
end -- if tagged or not
print ""
end -- if any text
end -- show_item
-- normal functions
local function show_functions_help (row)
NoteHr ()
show_item (HEADINGCOLOUR, "Function", NAMECOLOUR, row.name)
show_item (HEADINGCOLOUR, "Summary", SUMMARYCOLOUR, row.summary)
show_item (HEADINGCOLOUR, "Prototype", PROTOTYPECOLOUR, row.prototype)
show_item (HEADINGCOLOUR, "Description", DESCRIPTIONCOLOUR, row.description)
show_item (HEADINGCOLOUR, "Return Value", RETURNVALUE, row.return_value)
show_item (HEADINGCOLOUR, "Lua Example", CODECOLOUR, row.lua_example)
show_item (HEADINGCOLOUR, "Lua Notes", NOTESCOLOUR, row.lua_notes)
end -- show_functions_help
-- general help (major topics)
local function show_general_help (row)
NoteHr ()
show_item (NOTESCOLOUR, "", NAMECOLOUR, row.title)
show_item (HEADINGCOLOUR, "Summary", SUMMARYCOLOUR, row.description, true) -- HTML codes
end -- show_general_help
-- lua functions
local function show_lua_functions_help (row)
NoteHr ()
show_item (HEADINGCOLOUR, "Lua", NAMECOLOUR, row.name)
show_item (HEADINGCOLOUR, "Summary", SUMMARYCOLOUR, row.summary)
show_item (HEADINGCOLOUR, "Prototype", PROTOTYPECOLOUR, row.prototype)
show_item (HEADINGCOLOUR, "Description", DESCRIPTIONCOLOUR, row.description, true) -- HTML codes
end -- show_lua_functions_help
local hyperlink_handlers = {
functions = { sql = "SELECT * FROM functions WHERE name = %s",
handler = show_functions_help };
general = { sql = "SELECT * FROM general_doc WHERE doc_name = %s",
handler = show_general_help };
lua_functions = { sql = "SELECT * FROM lua_functions WHERE name = %s",
handler = show_lua_functions_help };
} -- end of hyperlink_handlers
-- here when hyperlink clicked
function do_hyperlink (s)
local what, name = string.match (s, "([%a_]+):([%a%d_%. :]+)")
if not what then return end
local help = hyperlink_handlers [what]
if not help then
ColourNote ("red", "", "Handler not found for " .. what)
return
end -- if not found
-- should only find one match here ...
for row in db:nrows(string.format (help.sql, fixsql (name))) do
help.handler (row)
end -- finding function
end -- do_hyperlink
help_items = {}
function general_help (search_string, want_snippet)
local searchfor = fixsql (search_string)
AnsiNote (RESET)
if not db then
ColourNote ("red", "", "MUSHclient help database 'help.db' not found.")
return
end -- if
local count = 0
local functions = {}
local general = {}
local lua_functions = {}
help_items = {}
local item_count = 0
function show_snippet (what, name, title, extra, snippet)
item_count = item_count + 1
help_items [item_count] = what .. ":" .. name
Tell " "
Hyperlink ("!!" .. GetPluginID () .. ":do_hyperlink(" .. what .. ":" .. name .. ")",
item_count .. ". " .. title, "Click for help on " .. title, "cyan", "", false)
if extra ~= "" then
Tell (" - ", extra)
end -- if
print ""
-- show snippet
if want_snippet then
-- get rid of newlines, and multiple spaces
AnsiNote (RESET .. string.gsub (snippet, "%s+", " "))
print ""
end -- if snippet wanted
end -- show_snippet
NoteHr ()
-- GENERAL documentation
-- find matching items using FTS
for row in db:nrows(string.format (
[[
SELECT name, summary, snippet(general_doc_lookup, '%s', '%s', ' ... ', -1, %i) AS snippet
FROM general_doc_lookup
WHERE general_doc_lookup MATCH %s]],
BOLD, UNBOLD, SNIPPETSIZE,
searchfor)) do
general [row.name] = { snippet = row.snippet, summary = row.summary }
count = count + 1
end -- finding item
if next (general) then
ColourNote (HEADINGCOLOUR, "", "Topics")
for k, v in pairsByKeys (general) do
show_snippet ("general", k, v.summary, "", v.snippet)
end -- for
end -- if
-- FUNCTIONS documentation
-- find matching items using FTS
for row in db:nrows(string.format (
[[
SELECT name, summary, snippet(functions_lookup, '%s', '%s', ' ... ', -1, %i) AS snippet
FROM functions_lookup
WHERE functions_lookup MATCH %s]],
BOLD, UNBOLD, SNIPPETSIZE,
searchfor)) do
functions [row.name] = { snippet = row.snippet, summary = row.summary }
count = count + 1
end -- finding item
if next (functions) then
ColourNote (HEADINGCOLOUR, "", "Functions")
for k, v in pairsByKeys (functions) do
show_snippet ("functions", k, k, v.summary, v.snippet)
end -- for
end -- if
-- LUA FUNCTIONS documentation
-- find matching items using FTS
for row in db:nrows(string.format (
[[
SELECT name, summary, snippet(lua_functions_lookup, '%s', '%s', ' ... ', -1, %i) AS snippet
FROM lua_functions_lookup
WHERE lua_functions_lookup MATCH %s]],
BOLD, UNBOLD, SNIPPETSIZE,
searchfor)) do
lua_functions [row.name] = { snippet = row.snippet, summary = row.summary }
count = count + 1
end -- finding item
if next (lua_functions) then
ColourNote (HEADINGCOLOUR, "", "Lua")
for k, v in pairsByKeys (lua_functions) do
show_snippet ("lua_functions", k, k, v.summary, v.snippet)
end -- for
end -- if
if count == 0 then
print ("Nothing found for:", search_string)
elseif item_count == 1 then
do_hyperlink (help_items [1]) -- automatically show only match
end -- if
end -- general_help
-- here when they want to search the help
function help_find (name, line, wildcards)
general_help (wildcards [1], false)
end -- help_find
function help_find_snippet (name, line, wildcards)
general_help (wildcards [1], true)
end -- help_find_snippet
local function fix_description (s)
if not s then
return ""
end -- if
-- get rid of tags
s = s:gsub ("</?%a+/?>", "")
-- convert entities ...
s = s:gsub ("&%a-;", entities)
return s
end -- fix_description
function help_number (name, line, wildcards)
local which = tonumber (wildcards [1])
if #help_items == 0 then
print ("No recent search done which gave any results")
return
end -- if
if which < 1 or which > #help_items then
print (string.format ("Requested help item %i not recently displayed - valid range is 1 to %i",
which, #help_items))
return
end -- if
do_hyperlink (help_items [which])
end -- help_number
function OnPluginInstall ()
-- open database on disk
if not db then
db = assert (sqlite3.open(GetInfo (66) .. "help.db"))
end -- if
local commands = false
-- see if commands table exists
for row in db:nrows("SELECT * FROM sqlite_master WHERE type = 'table' AND name = 'commands'") do
commands = true
end
if not commands then
ColourNote ("red", "", "MUSHclient help database 'help.db' not found.")
db:close ()
db = nil
return
end -- if
local fts4 = false
-- see if fts4 tables exist
for row in db:nrows("SELECT * FROM sqlite_master WHERE type = 'table' AND name = 'commands_lookup'") do
fts4 = true
end
-- if no fts4 tables, make them
if not fts4 then
local start = utils.timer ()
ColourNote ("cyan", "", "Creating help database full-text lookup tables ...")
-- START
assert (db:execute [[
BEGIN TRANSACTION;
DROP TABLE IF EXISTS commands_lookup;
DROP TABLE IF EXISTS dialogs_lookup;
DROP TABLE IF EXISTS functions_lookup;
DROP TABLE IF EXISTS general_doc_lookup;
DROP TABLE IF EXISTS errors_lookup;
DROP TABLE IF EXISTS lua_functions_lookup;
]])
-- COMMANDS
assert (db:execute "CREATE VIRTUAL TABLE commands_lookup USING FTS4(name, summary, description)")
-- fix up HTML stuff
for row in db:nrows("SELECT command_name, short_description, description FROM commands") do
assert (db:execute (string.format ([[
INSERT INTO commands_lookup (name, summary, description)
VALUES (%s, %s, %s)]],
fixsql (row.command_name),
fixsql (row.short_description),
fixsql (fix_description (row.description)))))
end -- for
-- DIALOGS
assert (db:execute "CREATE VIRTUAL TABLE dialogs_lookup USING FTS4(name, summary, description)")
-- fix up HTML stuff
for row in db:nrows("SELECT dialog_name, title, description FROM dialogs") do
assert (db:execute (string.format ([[
INSERT INTO dialogs_lookup (name, summary, description)
VALUES (%s, %s, %s)]],
fixsql (row.dialog_name),
fixsql (row.title),
fixsql (fix_description (row.description)))))
end -- for
-- WORLD FUNCTIONS
assert (db:execute "CREATE VIRTUAL TABLE functions_lookup USING FTS4(name, summary, description, lua_example, lua_notes)")
assert (db:execute [[INSERT INTO functions_lookup (name, summary, description, lua_example, lua_notes)
SELECT name, summary, description, lua_example, lua_notes FROM functions]])
-- GENERAL TOPICS
assert (db:execute "CREATE VIRTUAL TABLE general_doc_lookup USING FTS4(name, summary, description)")
-- fix up HTML stuff
for row in db:nrows("SELECT doc_name, title, description FROM general_doc") do
assert (db:execute (string.format ([[
INSERT INTO general_doc_lookup (name, summary, description)
VALUES (%s, %s, %s)]],
fixsql (row.doc_name),
fixsql (row.title),
fixsql (fix_description (row.description)))))
end -- for
-- ERRORS
assert (db:execute "CREATE VIRTUAL TABLE errors_lookup USING FTS4(name, error_code, description)")
assert (db:execute [[INSERT INTO errors_lookup (name, error_code, description)
SELECT error_name, error_code, meaning FROM errors ]])
-- LUA FUNCTIONS
assert (db:execute "CREATE VIRTUAL TABLE lua_functions_lookup USING FTS4(name, summary, description)")
-- fix up HTML stuff
for row in db:nrows("SELECT name, summary, description FROM lua_functions") do
assert (db:execute (string.format ([[
INSERT INTO lua_functions_lookup (name, summary, description)
VALUES (%s, %s, %s)]],
fixsql (row.name),
fixsql (row.summary),
fixsql (fix_description (row.description)))))
end -- for
-- DONE
assert (db:execute "COMMIT;")
ColourNote ("cyan", "", string.format ("Done. Took %0.3f seconds.", utils.timer () - start))
end -- if
end -- OnPluginInstall
function OnHelp ()
NoteHr ()
ColourNote (HELPCOLOUR, "", world.GetPluginInfo (world.GetPluginID (), 3))
end
]]>
</script>
</muclient>