blarghargh

This commit is contained in:
Diego Martínez 2013-07-07 21:05:53 -03:00
parent c4abd7288c
commit fd89fce7a3
4 changed files with 375 additions and 264 deletions

269
init.lua
View File

@ -1,267 +1,8 @@
local WP = minetest.get_worldpath().."/wiki"
local MODPATH = minetest.get_modpath("wiki")
local internal_pages = {
----------------------------------------------------------------
----------------------------------------------------------------
[".Intro"] = [[
Thank you for using the Wiki Mod.
wikilib = { }
This is a mod that allows one to edit pages via a block. You
can use it to document interesting places in a server, to provide
a place to post griefing reports, or any kind of text you want.
To create a new page, enter the name in the field at the top of the
form, then click "Go". If the page already exists, it's contents will
be displayed. Edit the page as you see fit, then click on "Save" to
write the changes to disk.
Please note that page names starting with a dot ('.') are reserved
for internal topics such as this one. Users cannot edit/create such
pages from the mod interface.
See also:
* [.Tags]
* [.License]
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".Tags"] = [[
The wiki supports some special tags.
You can place hyperlinks to other pages in the Wiki, by surrounding
text in square brackets (for example, [.Intro]). Such links will
appear at the bottom of the form.
See also:
* [.Intro]
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".License"] = [[
Wiki Mod for Minetest - License
-------------------------------
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
See also:
* [.Intro]
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".NotFound"] = [[
The specified internal page cannot be found. You may want to:
* Go back to [Main].
* Go to [.Intro].
]],
----------------------------------------------------------------
----------------------------------------------------------------
}
local WIKI_FORMNAME = "wiki:wiki"
local f = io.open(WP.."/.dummy")
if f then
f:close()
else
os.execute("mkdir \""..WP.."\"")
local f = io.open(WP.."/.dummy", "w")
if f then
f:write("DO NOT DELETE!!!\n")
f:close()
end
end
f = nil
local function name_to_filename(name)
name = name:gsub("[^A-Za-z0-9-]", function(c)
if c == " " then
return "_"
else
return ("%%%02X"):format(c:byte(1))
end
end)
return name:lower()
end
local function filename_to_name(filename)
filename = name:gsub("_", " "):gsub("%%[0-9a-fA-F][0-9a-fA-F]", function(c)
return string.char(tonumber(c:sub(2, 3), 16))
end)
return filename
end
local function find_links(text)
local links = { }
for link in text:gmatch("%[(.-)%]") do
links[#links + 1] = link
end
return links
end
local function parse_wiki_file(f)
local text = ""
local links_n = 0
for line in f:lines() do
text = text..line.."\n"
end
return text, find_links(text)
end
local function create_wiki_page(name, text)
if name == "" then return end
if name:sub(1, 1) == "." then return end
local fn = WP.."/"..name_to_filename(name)
local f = io.open(fn, "w")
if not f then return end
local nl = ""
if text:sub(-1) ~= "\n" then nl = "\n" end
f:write(text..nl)
f:close()
end
local function get_wiki_page(name, player)
if name == "" then name = "Main" end
local text, links
if name:sub(1, 1) == "." then
text = internal_pages[name] or internal_pages[".NotFound"]
links = find_links(text)
else
local fn = WP.."/"..name_to_filename(name)
local f = io.open(fn)
if f then
text, links = parse_wiki_file(f)
f:close()
else
if name == "Main" then
text = internal_pages[".Intro"]
links = find_links(text)
else
text = "This page does not exist yet."
links = { }
end
end
end
local buttons = ""
local bx = 0
local by = 7.5
local esc = minetest.formspec_escape
for i, link in ipairs(links) do
if (i % 5) == 0 then
bx = 0
by = by + 0.3
end
link = esc(link)
buttons = buttons..(("button[%f,%f;2.4,0.3;page_%s;%s]"):format(bx, by, link, link))
bx = bx + 2.4
end
local toolbar
if minetest.check_player_privs(player, {wiki=true}) then
toolbar = "button[0,9;2.4,1;save;Save]"
else
toolbar = "label[0,9;You are not authorized to edit the wiki.]"
end
return ("size[12,10]"
.. "field[0,1;11,1;page;Page;"..esc(name).."]"
.. "button[11,1;1,0.5;go;Go]"
.. "textarea[0,2;12,6;text;"..esc(name)..";"..esc(text).."]"
.. buttons
.. toolbar
)
end
local function show_wiki_page(player, name)
local formspec = get_wiki_page(name, player)
minetest.show_formspec(player, WIKI_FORMNAME, formspec)
end
minetest.register_node("wiki:wiki", {
description = "Wiki",
tiles = { "default_wood.png", "default_wood.png", "default_bookshelf.png" },
groups = { choppy=3, oddly_breakable_by_hand=2, flammable=3 },
sounds = default.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", "Wiki")
end,
on_rightclick = function(pos, node, clicker, itemstack)
if clicker then
show_wiki_page(clicker:get_player_name(), "Main")
end
end,
})
minetest.register_privilege("wiki", {
description = "Allow editing wiki pages",
give_to_singleplayer = true,
})
local BS = "default:bookshelf"
local BSL = { BS, BS, BS }
minetest.register_craft({
output = "wiki:wiki",
recipe = { BSL, BSL, BSL },
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if (not formname) or (formname ~= WIKI_FORMNAME) then return end
local plname = player:get_player_name()
if fields.save then
create_wiki_page(fields.page, fields.text)
show_wiki_page(plname, fields.page)
elseif fields.go then
show_wiki_page(plname, fields.page)
elseif fields.back then
show_wiki_page(plname, prev)
else
for k in pairs(fields) do
if type(k) == "string" then
local name = k:match("^page_(.*)")
if name then
show_wiki_page(plname, name)
end
end
end
end
end)
dofile(MODPATH.."/strfile.lua")
dofile(MODPATH.."/wikilib.lua")
dofile(MODPATH.."/internal.lua")

130
internal.lua Normal file
View File

@ -0,0 +1,130 @@
wikilib.internal_pages = {
----------------------------------------------------------------
----------------------------------------------------------------
[".Intro"] = [[
Thank you for using the Wiki Mod.
This is a mod that allows one to edit pages via a block. You
can use it to document interesting places in a server, to provide
a place to post griefing reports, or any kind of text you want.
To create a new page, enter the name in the field at the top of the
form, then click "Go". If the page already exists, it's contents will
be displayed. Edit the page as you see fit, then click on "Save" to
write the changes to disk.
Please note that page names starting with a dot ('.') are reserved
for internal topics such as this one. Users cannot edit/create such
pages from the mod interface.
See also:
* [.Tags]
* [.License]
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".Tags"] = [[
The wiki supports some special tags.
You can place hyperlinks to other pages in the Wiki, by surrounding
text in square brackets (for example, [.Intro]). Such links will
appear at the bottom of the form.
See also:
* [.Intro]
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".License"] = [[
Copyright (c) 2013, Diego Martínez
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
* Go to [.Intro].
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".NotFound_Internal"] = [[
The specified internal page cannot be found. You may want to:
* Back to [Main].
* Go to [.Intro].
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".NotFound"] = [[
This page does not exist yet.
* Back to [Main].
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".BadPageName"] = [[
The page name you entered is wrong. See [.Page Names] for more info.
* Back to [Main].
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".Help Index"] = [[
* [.Page Names]
* [.User Pages]
* Back to [Main].
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".Page Names"] = [[
Page names must be in any of the following formats:
<pagename>
Display global page <pagename>.
:<n>
Display page <n> from your user space. <n> must be a number between
0 and 9. See [.User Pages] for more info.
:
This is equivalent to ":0" (shows your private page).
:<user>:<n>
Display page "Page Name" from the specified user's space. Note that page
number 0 is never accessible this way, even if you specify yourself as
<user>.
* Back to [.Help Index].
* Back to [Main].
]],
----------------------------------------------------------------
----------------------------------------------------------------
[".User Pages"] = [[
Users can have up to 10 pages in their "user space", numbered 0-9. These pages
are accessed through the special page names ":<n>", and ":<user>:<n>". Page 0
is your private page. This page is not accessible to anyone but you. You can
use it to write down secret locations, etc.
* Back to [.Help Index].
* Back to [Main].
]],
----------------------------------------------------------------
----------------------------------------------------------------
}

28
strfile.lua Normal file
View File

@ -0,0 +1,28 @@
strfile = { }
function strfile.open(s)
return {
_buf = s,
_pos = 1,
_readline = function(self)
if self._pos == nil then
return nil
end
local nl = self._buf:find("\n", self._pos, true)
local line
if nl then
line = self._buf:sub(self._pos, nl - 1)
nl = nl + 1
else
line = self._buf:sub(self._pos)
end
self._pos = nl
return line
end,
lines = function(self)
return self._readline, self, true
end,
close = function(self) end,
}
end

212
wikilib.lua Normal file
View File

@ -0,0 +1,212 @@
local WP = minetest.get_worldpath().."/wiki"
local WIKI_FORMNAME = "wiki:wiki"
local WIN32, DIR_SEP
if os.getenv("WINDIR") then
WIN32 = true
DIR_SEP = "\\"
else
WIN32 = false
DIR_SEP = "/"
end
local function mkdir(dir)
local f = io.open(dir..DIR_SEP..".dummy")
if f then
f:close()
else
if WIN32 then
dir = dir:gsub("/", "\\")
else
dir = dir:gsub("\\", "/")
end
os.execute("mkdir \""..dir.."\"")
local f = io.open(dir..DIR_SEP..".dummy", "w")
if f then
f:write("DO NOT DELETE!!!\n")
f:close()
end
end
end
mkdir(WP)
mkdir(WP.."/users")
local function name_to_filename(name)
name = name:gsub("[^A-Za-z0-9-]", function(c)
if c == " " then
return "_"
else
return ("%%%02X"):format(c:byte(1))
end
end)
return name:lower()
end
local function get_page_path(name, player) --> path, is_file
if name:sub(1, 1) == "." then
local text = wikilib.internal_pages[name] or wikilib.internal_pages[".NotFound_Internal"]
return text, false
elseif name:sub(1, 1) == ":" then
if name:match("^:[0-9]?$") then
local n = tonumber(name:sub(2,2)) or 0
path = "users/"..player.."/page"..n
mkdir(WP.."/users/"..player)
elseif name:match("^:.-:[1-9]$") then
local user, n = name:match("^:(.-):([1-9])$")
path = "users/"..user.."/page"..n
mkdir(WP.."/users/"..user)
else
return wikilib.internal_pages[".BadPageName"], false
end
else
path = name_to_filename(name)
end
return WP.."/"..path, true
end
local function find_links(lines) --> links
local links = { }
local links_n = 0
for _,line in ipairs(lines) do
for link in line:gmatch("%[(.-)%]") do
links_n = links_n + 1
links[links_n] = link
end
end
return links
end
local function load_page(name, player) --> text, links
local path, is_file = get_page_path(name, player)
local f
if is_file then
f = io.open(path)
if not f then
f = strfile.open(wikilib.internal_pages[".NotFound"])
end
else
f = strfile.open(path)
end
local lines = { }
local lines_n = 0
for line in f:lines() do
lines_n = lines_n + 1
lines[lines_n] = line
end
f:close()
local text = table.concat(lines, "\n")
local links = find_links(lines)
return text, links
end
local function save_page(name, player, text)
local path, is_file = get_page_path(name, player)
if not is_file then return end
local f = io.open(path, "w")
if not f then return end
f:write(text)
f:close()
end
local esc = minetest.formspec_escape
local function show_wiki_page(player, name)
if name == "" then name = "Main" end
local text, links = load_page(name, player)
local buttons = ""
local bx = 0
local by = 7.5
for i, link in ipairs(links) do
if (i % 5) == 0 then
bx = 0
by = by + 0.3
end
link = esc(link)
buttons = buttons..(("button[%f,%f;2.4,0.3;page_%s;%s]"):format(bx, by, link, link))
bx = bx + 2.4
end
local toolbar
if is_user or minetest.check_player_privs(player, {wiki=true}) then
toolbar = "button[0,9;2.4,1;save;Save]"
else
toolbar = "label[0,9;You are not authorized to edit this page.]"
end
minetest.show_formspec(player, WIKI_FORMNAME, ("size[12,10]"
.. "field[0,1;11,1;page;Page;"..esc(name).."]"
.. "button[11,1;1,0.5;go;Go]"
.. "textarea[0,2;12,6;text;"..esc(name)..";"..esc(text).."]"
.. buttons
.. toolbar
))
end
minetest.register_node("wiki:wiki", {
description = "Wiki",
tiles = { "default_wood.png", "default_wood.png", "default_bookshelf.png" },
groups = { choppy=3, oddly_breakable_by_hand=2, flammable=3 },
sounds = default.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", "Wiki")
end,
on_rightclick = function(pos, node, clicker, itemstack)
if clicker then
show_wiki_page(clicker:get_player_name(), "Main")
end
end,
})
minetest.register_privilege("wiki", {
description = "Allow editing wiki pages",
give_to_singleplayer = true,
})
local BS = "default:bookshelf"
local BSL = { BS, BS, BS }
minetest.register_craft({
output = "wiki:wiki",
recipe = { BSL, BSL, BSL },
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if (not formname) or (formname ~= WIKI_FORMNAME) then return end
local plname = player:get_player_name()
if fields.save then
save_page(fields.page, plname, fields.text)
show_wiki_page(plname, fields.page)
elseif fields.go then
show_wiki_page(plname, fields.page)
else
for k in pairs(fields) do
if type(k) == "string" then
local name = k:match("^page_(.*)")
if name then
show_wiki_page(plname, name)
end
end
end
end
end)