diff --git a/README.md b/README.md index 5f22c33..4e29dd5 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Outputs this: This also just works: ``` > x = 2*2 + > x | 4 ``` @@ -44,6 +45,7 @@ No need to use `core.chat_send_player()`, just use `print()` - it will do the ri ``` > objs = core.get_objects_inside_radius(here, 10) + > for i,o in ipairs(objs) do print(i, (o:get_luaentity() or {}).name, o:get_pos()) end < 1 nil (-98.0, 15.5, 33.4) < 2 mobs_animal:kitten (-101.0, 16.5, 30.0) @@ -80,9 +82,12 @@ Show indices for easier manual access: | [1] = #, | [2] = #, | } + > _[2] | # + > pos = _:get_pos() + > pos | { | x = 123.5, @@ -91,3 +96,42 @@ Show indices for easier manual access: | } ``` +### Accessing and changing global variables +You can save some keypresses by not typing `local` in front of every +variable. Assigning to globals won't clobber them, instead using your personal +environment. But you can still read globals as usual. + +``` +> print(myvar) +* Accessing undeclared variable: "myvar" +< nil + +> myvar = 1 +| Done. + +> print(myvar) +< 1 +| Done. +``` + +If you want to create a new global or actually overwrite existing one, +you can access global environment through usual `_G` or `global` +variables. Using them will print a message telling you if global var +already existed. + +``` +> cmd_eval = nil +| Done. + +> cmd_eval -- accesses real global +{ + e = { ... }, ... +} + +> global.cmd_eval = nil +* Overwriting global: "cmd_eval" +| Done. + +> cmd_eval +| nil -- wiped for real +``` diff --git a/init.lua b/init.lua index 9f7b4da..41ea8c0 100644 --- a/init.lua +++ b/init.lua @@ -11,6 +11,11 @@ _G[MODNAME] = api api.e = {} +local function orange_fmt(...) + return core.colorize("#FFA91F", string.format(...)) +end + + local function create_shared_environment(player_name) local magic_keys = { -- These are _functions_ pretending to be _variables_, they will @@ -53,6 +58,21 @@ local function create_shared_environment(player_name) } local g = {} -- "do not warn again" flags + local global_proxy = setmetatable( + {""}, + { + __index = _G, + __newindex = function(t, k, v) + if _G[k] then + core.chat_send_player(player_name, orange_fmt("* Overwriting global: %s", dump(k))) + else + core.chat_send_player(player_name, orange_fmt("* Creating new global: %s", dump(k))) + end + _G[k] = v + end, + } + ) + local eval_env = setmetatable( { my_name = player_name, @@ -64,22 +84,29 @@ local function create_shared_environment(player_name) end core.chat_send_player(player_name, msg) end, - dump = repl_dump, + --global = _G, -- this works, but dumps whole global env if you just print `cmd_eval` value + _G = global_proxy, -- use our proxy to get warnings + global = global_proxy, -- just a different name for globals + --dump = repl_dump, }, { __index = function(self, key) + -- we give warnings on accessing undeclared var because it's likely a typo local res = rawget(_G, key) if res == nil then local magic = magic_keys[key] if magic then return magic() elseif not g[key] then - core.chat_send_player(player_name, string.format("* Accessing undeclared variable: '%s'", key)) + core.chat_send_player(player_name, orange_fmt("* Accessing undeclared variable: %s", dump(key))) g[key] = true -- warn only once end end return res end + -- there's no __newindex method because we allow assigning + -- "globals" inside snippets, since those will be only + -- accessible to eval and stored in `eval_env` } ) return eval_env diff --git a/todo.org b/todo.org index 4fd6473..85145d1 100644 --- a/todo.org +++ b/todo.org @@ -16,3 +16,5 @@ copy relevant parts from there. * add proper REPL Register on chat message and let executing multiple commands without typing `/eval`. Maybe via `/repl` command... +* add a "pager" for long output +To not spam the chat and prevent "Internal error: String too long"