Skip to content

Instantly share code, notes, and snippets.

@epsilon-phase
Last active October 9, 2017 20:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save epsilon-phase/c18345ef1841681a4a20e4bd1eb07ba3 to your computer and use it in GitHub Desktop.
Save epsilon-phase/c18345ef1841681a4a20e4bd1eb07ba3 to your computer and use it in GitHub Desktop.
Mudlet Editor
-- Put your Lua functions here. --
-- --
-- Note that you can also use external Scripts --
-------------------------------------------------
Buffer={}
function Buffer:new(name)
local buf={name=name,lines={},current=1,marks={}}
self.__index=self
setmetatable(buf,self)
return buf
end
function Buffer:insert(line,position)
position=self:interpretAddress(position) or self.current
table.insert(self.lines,position,line)
if position <= self.current then
self.current=self.current+1
end
return self.current
end
function Buffer:delete(number,to)
local times=1
number=self:interpretAddress(number) or self.current
if to then
times=self:interpretAddress(to,number)-number
end
for i=1,times do
table.remove(self.lines,number)
if number <= self.current then
self.current=self.current-1
end
end
return self.current
end
function Buffer:swap(a,b)
a=self:interpretAddress(a)
b=self:interpretAddress(b)
local atext=self.lines[a]
local btext=self.lines[b]
self.lines[a]=btext
self.lines[b]=atext
end
function Buffer:combineParagraphs()
local result={}
local first=1
local last=1
for i=1,#self.lines do
if #string.gsub(self.lines[i],'%s+','')==0 or i==#self.lines then
if #string.gsub(self.lines[i],'%s+','')==0 then
last=i-1
else
last=i
end
table.insert(result,table.concat(self.lines,' ',first,last))
first=i+1
end
end
return result
end
function Buffer:interpretAddress(thing,relativeto)
if type(thing)=='table' then
local pos=thing.start or relativeto or self.current
if type(pos)~='number' then
if pos=='^' then
pos=1
elseif pos=='.' then
pos=self.current
elseif pos=='$' then
pos=#self.lines
elseif string.match(pos,'%a') then
pos=self.marks[pos]
end
end
if thing.type=='relative' then
if thing.adjust=='+' then
pos=pos+(thing.amount or 1)
elseif thing.adjust=='-' then
pos=pos-(thing.amount or 1)
end
else
return pos
end
elseif type(thing)=='string' then
if thing=='$' then
return #self.lines
elseif thing=='^' then
return 1
elseif thing=='.' then
return self.current
else
return self.marks[thing]
end
else
return thing
end
end
function Buffer:jump(n)
self.current=self:interpretAddress(n)
end
function Buffer:jumpAfter(n)
self.current=self:interpretAddress(n)+1
end
function Buffer:join(a,b)
a=self:interpretAddress(a)
b=self:interpretAddress(b)
self.lines[a]=table.concat(self.lines,' ',a,b)
self:delete(a+1,b)
end
function Buffer:mark(m,a)
a=self:interpretAddress(a)
self.marks[m]=a
end
function Buffer:save(filename)
local file=nil
if filename then
if string.find(filename,'"') then
_,_,filename=string.find(filename,'.+"(.+)".+')
end
self.location=filename
end
file=assert(io.open(self.location,'w'))
file:write(table.concat(self.lines,'\n'))
file:close()
end
-------------------------------------------------
-- Put your Lua functions here. --
-- --
-- Note that you can also use external Scripts --
-------------------------------------------------
Editor= {buffers={},currentbuffer=-1,linebreak='%r',insertmode=true,shown=false,windowsize=nil}
function Editor:open()
if Editorwindow ==nil then
Editorwindow=Geyser.MiniConsole:new({name="editor",
x="0%",y="0%",
width="40%",
height="40%"}
)
else
showWindow("editor")
end
enableAlias("All Things")
Editor.shown=true
if self.currentbuffer==-1 or 0==#self.buffers then
table.insert(self.buffers,Buffer:new('new'))
self.currentbuffer=1
end
local width,height=calcFontSize(10)
local mainwindowwidth,mainwindowheight=getMainWindowSize()
self.windowsize=math.floor((0.4*mainwindowheight)/height)
self.windowwidth=math.floor((0.35*mainwindowwidth)/width)
setWindowWrap('editor',self.windowwidth)
end
function Editor:close()
Editor.shown=false
hideWindow('editor')
disableAlias("All Things")
end
function Editor:toggle()
if not Editor.shown then
self:open()
else
self:close()
end
end
function Editor:processCommand(string)
if self.insertmode then
if string~='.' then
self.buffers[self.currentbuffer]:insert(string)
else
self.insertmode=false
end
else
local _,_,cn,rest=string.find(string,'(%a+) (.+)')
self.Commands.process(self.buffers[self.currentbuffer],cn,rest)
end
self:afterInsert()
end
function Editor:afterInsert()
clearWindow('editor')
local start=math.max(self.buffers[self.currentbuffer].current-math.floor(self.windowsize/2),1)
local last=math.min(#self.buffers[self.currentbuffer].lines,self.buffers[self.currentbuffer].current+math.floor(self.windowsize/2))
for i=start,last do
if i == self.buffers[self.currentbuffer].current then
cecho('editor',string.format('%d <blue>|<reset> %s <yellow><<reset>\n',i,self.buffers[self.currentbuffer].lines[i]))
else
cecho('editor',string.format('%d <blue>|<reset> %s\n',i,self.buffers[self.currentbuffer].lines[i]))
end
end
end
Editor.Commands={}
function pack(...)
return select(1,arg)
end
function Editor.Commands.join(buffer,arg1,arg2)
buffer:join(arg1,arg2)
end
function Editor.Commands.insert(buffer,arg1)
buffer:jump(arg1)
Editor.insertmode=true
end
function Editor.Commands.append(buffer,arg1)
buffer:jumpAfter(arg1)
Editor.insertmode=true
end
function Editor.Commands.delete(buffer,arg1,arg2)
buffer:delete(arg1,arg2)
end
function Editor.Commands.mark(buffer,arg1,arg2)
buffer:mark(arg1,arg2)
end
function Editor.Commands.swap(buffer,arg1,arg2)
buffer:swap(arg1,arg2)
end
function Editor.Commands.write(buffer,arg1)
local c=arg1
local r=buffer:combineParagraphs()
display(buffer:combineParagraphs())
send(string.format(c,table.concat(r,Editor.linebreak)))
end
function Editor.Commands.save(buffer,arg1)
if #string.gsub(arg1,'%s+','')==0 then
buffer:save(nil)
else
buffer:save(arg1)
end
end
function Editor:newBuffer(name)
table.insert(self.buffers,Buffer:new(name))
self.currentbuffer=#self.buffers
end
function dissectRelative(m)
if tonumber(m) then
if tonumber(m)>0 then
return tonumber(m)
else
return {type='relative',amount=tonumber(m),adjust='-',pos='.'}
end
end
local r=nil
if rex.match(m,"'([a-z])") then
r=pack(rex.match(m,"'([a-z])$"))
return r[1]
end
r=pack(rex.match(m,"('[a-z]|[0-9$^.]+)(?:([-+])([0-9]+))"))
if r==nil then
r=pack(rex.match(m,'([-+])([0-9]+)'))
table.insert(r,'.',1)
end
local result={}
result.pos=tonumber(r[1]) or r[1]
if r[2] == '+' or r[2]=='-' then
result.type='relative'
result.amount=tonumber(r[3])
result.adjust=r[2]
end
return result
end
function transform(matches)
local a1=matches[1]
local a2=matches[2]
return {dissectRelative(a1),dissectRelative(a2)}
end
function Editor.Commands.process(buffer,commandname,rest)
if commandname=='new' then
Editor:newBuffer(rest)
elseif commandname=='save' then
Editor.Commands.save(buffer,rest)
elseif commandname=='write' then
echo("writing with:" .. rest)
Editor.Commands.write(buffer,rest)
elseif commandname=='mark' then
local args=pack(rex.match(rest,'([a-z]) ((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?)'))
Editor.Commands.mark(buffer,args[1],dissectRelative(args[2]))
elseif commandname=='insert' then
local args=pack(rex.match(rest,'((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?)'))
Editor.Commands[commandname](buffer,dissectRelative(args[1]))
else
local args=pack(rex.match(rest,'((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?) ((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?)'))
Editor.Commands[commandname](buffer,unpack(transform(args)))
end
end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE MudletPackage>
<MudletPackage version="1.001">
<ScriptPackage>
<ScriptGroup isActive="yes" isFolder="yes">
<name>Editor</name>
<packageName></packageName>
<script>-------------------------------------------------
-- Put your Lua functions here. --
-- --
-- Note that you can also use external Scripts --
-------------------------------------------------
Editor= {buffers={},currentbuffer=-1,linebreak='%r',insertmode=true,shown=false,windowsize=nil}
function Editor:open()
if Editorwindow ==nil then
Editorwindow=Geyser.MiniConsole:new({name=&quot;editor&quot;,
x=&quot;0%&quot;,y=&quot;0%&quot;,
width=&quot;40%&quot;,
height=&quot;40%&quot;}
)
else
showWindow(&quot;editor&quot;)
end
enableAlias(&quot;All Things&quot;)
Editor.shown=true
if self.currentbuffer==-1 or 0==#self.buffers then
table.insert(self.buffers,Buffer:new('new'))
self.currentbuffer=1
end
local width,height=calcFontSize(10)
local mainwindowwidth,mainwindowheight=getMainWindowSize()
self.windowsize=math.floor((0.4*mainwindowheight)/height)
self.windowwidth=math.floor((0.35*mainwindowwidth)/width)
setWindowWrap('editor',self.windowwidth)
end
function Editor:close()
Editor.shown=false
hideWindow('editor')
disableAlias(&quot;All Things&quot;)
end
function Editor:toggle()
if not Editor.shown then
self:open()
else
self:close()
end
end
function Editor:processCommand(string)
if self.insertmode then
if string~='.' then
self.buffers[self.currentbuffer]:insert(string)
else
self.insertmode=false
end
else
local _,_,cn,rest=string.find(string,'(%a+) (.+)')
self.Commands.process(self.buffers[self.currentbuffer],cn,rest)
end
self:afterInsert()
end
function Editor:afterInsert()
clearWindow('editor')
local start=math.max(self.buffers[self.currentbuffer].current-math.floor(self.windowsize/2),1)
local last=math.min(#self.buffers[self.currentbuffer].lines,self.buffers[self.currentbuffer].current+math.floor(self.windowsize/2))
for i=start,last do
if i == self.buffers[self.currentbuffer].current then
cecho('editor',string.format('%d &lt;blue&gt;|&lt;reset&gt; %s &lt;yellow&gt;&lt;&lt;reset&gt;\n',i,self.buffers[self.currentbuffer].lines[i]))
else
cecho('editor',string.format('%d &lt;blue&gt;|&lt;reset&gt; %s\n',i,self.buffers[self.currentbuffer].lines[i]))
end
end
end
Editor.Commands={}
function pack(...)
return select(1,arg)
end
function Editor.Commands.join(buffer,arg1,arg2)
buffer:join(arg1,arg2)
end
function Editor.Commands.insert(buffer,arg1)
buffer:jump(arg1)
Editor.insertmode=true
end
function Editor.Commands.append(buffer,arg1)
buffer:jumpAfter(arg1)
Editor.insertmode=true
end
function Editor.Commands.delete(buffer,arg1,arg2)
buffer:delete(arg1,arg2)
end
function Editor.Commands.mark(buffer,arg1,arg2)
buffer:mark(arg1,arg2)
end
function Editor.Commands.swap(buffer,arg1,arg2)
buffer:swap(arg1,arg2)
end
function Editor.Commands.write(buffer,arg1)
local c=arg1
local r=buffer:combineParagraphs()
display(buffer:combineParagraphs())
send(string.format(c,table.concat(r,Editor.linebreak)))
end
function Editor.Commands.save(buffer,arg1)
if #string.gsub(arg1,'%s+','')==0 then
buffer:save(nil)
else
buffer:save(arg1)
end
end
function Editor:newBuffer(name)
table.insert(self.buffers,Buffer:new(name))
self.currentbuffer=#self.buffers
end
function dissectRelative(m)
if tonumber(m) then
if tonumber(m)&gt;0 then
return tonumber(m)
else
return {type='relative',amount=tonumber(m),adjust='-',pos='.'}
end
end
local r=nil
if rex.match(m,&quot;'([a-z])&quot;) then
r=pack(rex.match(m,&quot;'([a-z])$&quot;))
return r[1]
end
r=pack(rex.match(m,&quot;('[a-z]|[0-9$^.]+)(?:([-+])([0-9]+))&quot;))
if r==nil then
r=pack(rex.match(m,'([-+])([0-9]+)'))
table.insert(r,'.',1)
end
local result={}
result.pos=tonumber(r[1]) or r[1]
if r[2] == '+' or r[2]=='-' then
result.type='relative'
result.amount=tonumber(r[3])
result.adjust=r[2]
end
return result
end
function transform(matches)
local a1=matches[1]
local a2=matches[2]
return {dissectRelative(a1),dissectRelative(a2)}
end
function Editor.Commands.process(buffer,commandname,rest)
if commandname=='new' then
Editor:newBuffer(rest)
elseif commandname=='save' then
Editor.Commands.save(buffer,rest)
elseif commandname=='write' then
echo(&quot;writing with:&quot; .. rest)
Editor.Commands.write(buffer,rest)
elseif commandname=='mark' then
local args=pack(rex.match(rest,'([a-z]) ((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?)'))
Editor.Commands.mark(buffer,args[1],dissectRelative(args[2]))
elseif commandname=='insert' then
local args=pack(rex.match(rest,'((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?)'))
Editor.Commands[commandname](buffer,dissectRelative(args[1]))
else
local args=pack(rex.match(rest,'((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?) ((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?)'))
Editor.Commands[commandname](buffer,unpack(transform(args)))
end
end
</script>
<eventHandlerList/>
<Script isActive="yes" isFolder="no">
<name>Buffer</name>
<packageName></packageName>
<script>
-- Put your Lua functions here. --
-- --
-- Note that you can also use external Scripts --
-------------------------------------------------
Buffer={}
function Buffer:new(name)
local buf={name=name,lines={},current=1,marks={}}
self.__index=self
setmetatable(buf,self)
return buf
end
function Buffer:insert(line,position)
position=self:interpretAddress(position) or self.current
table.insert(self.lines,position,line)
if position &lt;= self.current then
self.current=self.current+1
end
return self.current
end
function Buffer:delete(number,to)
local times=1
number=self:interpretAddress(number) or self.current
if to then
times=self:interpretAddress(to,number)-number
end
for i=1,times do
table.remove(self.lines,number)
if number &lt;= self.current then
self.current=self.current-1
end
end
return self.current
end
function Buffer:swap(a,b)
a=self:interpretAddress(a)
b=self:interpretAddress(b)
local atext=self.lines[a]
local btext=self.lines[b]
self.lines[a]=btext
self.lines[b]=atext
end
function Buffer:combineParagraphs()
local result={}
local first=1
local last=1
for i=1,#self.lines do
if #string.gsub(self.lines[i],'%s+','')==0 or i==#self.lines then
if #string.gsub(self.lines[i],'%s+','')==0 then
last=i-1
else
last=i
end
table.insert(result,table.concat(self.lines,' ',first,last))
first=i+1
end
end
return result
end
function Buffer:interpretAddress(thing,relativeto)
if type(thing)=='table' then
local pos=thing.start or relativeto or self.current
if type(pos)~='number' then
if pos=='^' then
pos=1
elseif pos=='.' then
pos=self.current
elseif pos=='$' then
pos=#self.lines
elseif string.match(pos,'%a') then
pos=self.marks[pos]
end
end
if thing.type=='relative' then
if thing.adjust=='+' then
pos=pos+(thing.amount or 1)
elseif thing.adjust=='-' then
pos=pos-(thing.amount or 1)
end
else
return pos
end
elseif type(thing)=='string' then
if thing=='$' then
return #self.lines
elseif thing=='^' then
return 1
elseif thing=='.' then
return self.current
else
return self.marks[thing]
end
else
return thing
end
end
function Buffer:jump(n)
self.current=self:interpretAddress(n)
end
function Buffer:jumpAfter(n)
self.current=self:interpretAddress(n)+1
end
function Buffer:join(a,b)
a=self:interpretAddress(a)
b=self:interpretAddress(b)
self.lines[a]=table.concat(self.lines,' ',a,b)
self:delete(a+1,b)
end
function Buffer:mark(m,a)
a=self:interpretAddress(a)
self.marks[m]=a
end
function Buffer:save(filename)
local file=nil
if filename then
if string.find(filename,'&quot;') then
_,_,filename=string.find(filename,'.+&quot;(.+)&quot;.+')
end
self.location=filename
end
file=assert(io.open(self.location,'w'))
file:write(table.concat(self.lines,'\n'))
file:close()
end
</script>
<eventHandlerList/>
</Script>
<Script isActive="no" isFolder="no">
<name>display</name>
<packageName></packageName>
<script>-------------------------------------------------
-- Put your Lua functions here. --
-- --
-- Note that you can also use external Scripts --
-------------------------------------------------
--function Editor:afterInsert()
-- clearWindow('editor')
-- for i=1,#self.buffers[self.currentbuffer].lines do
-- if i == self.buffers[self.currentbuffer].current then
-- cecho('editor',string.format('%d &lt;blue&gt;|&lt;reset&gt; %s &lt;yellow&gt;&lt;&lt;reset&gt;\n',i,self.buffers[self.currentbuffer].lines[i]))
-- else
-- cecho('editor',string.format('%d &lt;blue&gt;|&lt;reset&gt; %s\n',i,self.buffers[self.currentbuffer].lines[i]))
-- end
-- end
--end</script>
<eventHandlerList/>
</Script>
<Script isActive="no" isFolder="no">
<name>Commands</name>
<packageName></packageName>
<script>-------------------------------------------------
-- Put your Lua functions here. --
-- --
-- Note that you can also use external Scripts --
-------------------------------------------------
--Editor.Commands={}
--function pack(...)
-- return select(1,arg)
--end
--function Editor.Commands.join(buffer,arg1,arg2)
-- buffer:join(arg1,arg2)
--end
--function Editor.Commands.insert(buffer,arg1)
-- buffer:jump(arg1)
-- Editor.insertmode=true
--end
--function Editor.Commands.delete(buffer,arg1,arg2)
-- buffer:delete(arg1,arg2)
--end
--
--function Editor.Commands.mark(buffer,arg1,arg2)
-- buffer:mark(arg1,arg2)
--end
--function Editor.Commands.swap(buffer,arg1,arg2)
-- buffer:swap(arg1,arg2)
--end
--function Editor.Commands.write(buffer,arg1)
-- local c=arg1
-- local r=buffer:combineParagraphs()
-- send(string.format(c,table.concat(r,Editor.linebreak)))
--end
--function dissectRelative(m)
-- if tonumber(m) then
-- if tonumber(m)&gt;0 then
-- return tonumber(m)
-- else
-- return {type='relative',amount=tonumber(m),adjust='-',pos='.'}
-- end
-- end
-- local r=nil
-- if rex.match(m,&quot;'([a-z])&quot;) then
-- r=pack(rex.match(m,&quot;'([a-z])$&quot;))
-- return r[1]
-- end
-- r=pack(rex.match(m,&quot;('[a-z]|[0-9$^.]+)(?:([-+])([0-9]+))&quot;))
--
-- if r==nil then
-- r=pack(rex.match(m,'([-+])([0-9]+)'))
-- table.insert(r,'.',1)
-- end
--
-- local result={}
-- result.pos=tonumber(r[1]) or r[1]
-- if r[2] == '+' or r[2]=='-' then
-- result.type='relative'
-- result.amount=tonumber(r[3])
-- result.adjust=r[2]
-- end
-- return result
--end
--function transform(matches)
-- local a1=matches[1]
-- local a2=matches[2]
-- return {dissectRelative(a1),dissectRelative(a2)}
--end
--
--function Editor.Commands.process(buffer,commandname,rest)
-- if commandname=='write' then
-- Editor.Commands.write(buffer,rest)
-- elseif commandname=='mark' then
-- local args=pack(rex.match(rest,'([a-z]) ((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?)'))
-- Editor.Commands.mark(buffer,args[1],dissectRelative(args[2]))
-- else
-- local args=pack(rex.match(rest,'((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?) ((?:[0-9]+|\'[a-z]|[0-9]+|[$^.])(?:[+-][0-9]+)?)'))
-- Editor.Commands[commandname](buffer,unpack(transform(args)))
-- end
--end
-- --</script>
<eventHandlerList/>
</Script>
</ScriptGroup>
</ScriptPackage>
</MudletPackage>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment