Formatting Smaug progs

Posted by Zeno on Sun 22 Feb 2009 07:51 PM — 16 posts, 59,060 views.

USA #0
So I'm thinking about writing a plugin for MUSHclient that would format the display of progs in Smaug. Say if I mpstat'd a mob, it would rewrite the ouput to maybe something color coded. Whatever would help the builder read it better.

Considering builders sometime indent progs their self, probably leave that alone. Thoughts of what this should do? Maybe color each ifcheck (and what it contains) a different color?

Here's an example I would need to parse:
>speech_prog yes
if ispc($n)
 if hasqbit($n) == 55
  tsk
 else
  if handsfull($n)
   mea $n Your hands are full, Snoopy implies.
   break
  endif
  mpqset $n 55
  if rand(25)
   mpoload 1029
   give hat $n
   break
   endif
  if rand(33)
   mpoload 1030
    give suit $n
   break
  endif
  if rand(50)
   mpoload 1031
   give boots $n
   break
   endif
  mpoload 1032
  give beard $n
 endif
endif


Anyone else up to working on this with me?

Pseudo code stuff:
First we need to match something to know we're reading a prog. Progs start off with:
Quote:
>greet_prog 100

So what if we match that? Something like...
^>*_prog (.*?)$


And then we start matching in the prog
^if (.*?)$

^else (.*?)$

^break$

^endif$

etc

I suppose it wouldn't hurt put in an option to indent the prog as well if needed.


[EDIT] Here are some basic color changing triggers for a start:
<triggers>
  <trigger
   custom_colour="14"
   enabled="y"
   match="^&gt;(.*?)_prog (.*?)$"
   regexp="y"
   sequence="100"
  >
  </trigger>
</triggers>

<triggers>
  <trigger
   custom_colour="7"
   enabled="y"
   match="^[\s]*break$"
   regexp="y"
   sequence="100"
  >
  </trigger>
</triggers>

<triggers>
  <trigger
   custom_colour="3"
   enabled="y"
   keep_evaluating="y"
   match="^[\s]*else$"
   regexp="y"
   sequence="100"
  >
  </trigger>
</triggers>

<triggers>
  <trigger
   custom_colour="2"
   enabled="y"
   match="^[\s]*endif$"
   regexp="y"
   sequence="100"
  >
  </trigger>
</triggers>

<triggers>
  <trigger
   custom_colour="11"
   enabled="y"
   match="^[\s]*if (.*?)$"
   regexp="y"
   sequence="100"
  >
  </trigger>
</triggers>

<triggers>
  <trigger
   custom_colour="12"
   enabled="y"
   match="^[\s]*mp[\S]* "
   regexp="y"
   sequence="100"
  >
  </trigger>
</triggers>


[EDIT 2] I have this on the _prog regex:
inprog = 1
indentnum = 0
EnableTrigger("force_indent", true)

But I don't know how to indent lines. The force_indent trigger is a regex that matches anything, but it overwrites everything else.
Amended on Mon 23 Feb 2009 12:35 AM by Zeno
USA #1
Converting this into a plugin gives me this error:
Run-time error
Plugin: Smaug_prog_parse (called from world: SBI)
Function/Sub: SendEndifNote called by trigger
Reason: processing trigger ""
[string "Plugin"]:12: attempt to concatenate field '?' (a nil value)
stack traceback:
        [string "Plugin"]:12: in function <[string "Plugin"]:11>
Error context in script:
   8 :  ColourNote("yellowgreen", "black", "else ", "deepskyblue", "black", "//if "..ifchecklist[indentnum])
   9 : end -- function
  10 : 
  11 : function SendEndifNote (str)
  12*:  ColourNote("yellowgreen", "black", "endif ", "deepskyblue", "black", "//if "..ifchecklist[indentnum])
  13 : if inprog == 1 then
  14 :  indentnum = indentnum - 1
  15 : end
  16 : end -- function


Lua.

ifchecklist and indentnum are valid. Tried changing them to local, didn't help.
Australia Forum Administrator #2
Hmm, Lua can do subtle things at times, especially if you play with local. ;-)

Try, in the line before the error:


require "tprint"; tprint (ifchecklist)
print (indentnum)


Sometimes things get changed when you don't expect it.
USA #3
0
Run-time error
Plugin: Smaug_prog_parse (called from world: SBI)
Function/Sub: SendEndifNote called by trigger
Reason: processing trigger ""
[string "Plugin"]:16: attempt to concatenate field '?' (a nil value)
stack traceback:
        [string "Plugin"]:16: in function <[string "Plugin"]:13>
Error context in script:
  12 : 
  13 : function SendEndifNote (str)
  14 :  require "tprint"; tprint (ifchecklist)
  15 :  print (indentnum)
  16*:  ColourNote("yellowgreen", "black", "endif ", "deepskyblue", "black", "//if "..ifchecklist[indentnum])
  17 : if inprog == 1 then
  18 :  indentnum = indentnum - 1
  19 : end
  20 : end -- function
Amended on Mon 23 Feb 2009 02:43 AM by Zeno
USA #4
Here's the full plugin. Was in the middle of messing with it to fix it, may have some incomplete things:
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<!-- Saved on Sunday, February 22, 2009, 9:54 PM -->
<!-- MuClient version 4.35 -->

<!-- Plugin "Smaug_prog_parse" generated by Plugin Wizard -->

<muclient>
<plugin
   name="Smaug_prog_parse"
   author="Zeno"
   id="ec235cde57534866595eed2a"
   language="Lua"
   purpose="Parses Smaug progs (colors, ifcheck matching, etc)"
   date_written="2009-02-22 21:53:24"
   requires="4.35"
   version="1.0"
   >

</plugin>

<!--  Triggers -->

<triggers>

  <trigger
   custom_colour="17"
   enabled="y"
   match="^[\s]*break$"
   regexp="y"
   sequence="100"
   other_text_colour="firebrick"
  >
  </trigger>

  <trigger
   custom_colour="17"
   enabled="y"
   match="^[\s]*mp[\S]* "
   regexp="y"
   sequence="100"
   other_text_colour="violet"
  >
  </trigger>

  <trigger
   custom_colour="17"
   enabled="y"
   match="^&gt;(.*?)_prog (.*?)$"
   regexp="y"
   send_to="12"
   sequence="100"
   other_text_colour="seagreen"
  >
  <send>inprog = true
</send>
  </trigger>

  <trigger
   custom_colour="17"
   enabled="y"
   match="^[\s]*if (?P&lt;ifcheck&gt;.*?)$"
   regexp="y"
   send_to="12"
   sequence="100"
   other_text_colour="coral"
  >
  <send>if inprog == true then
 indentnum = indentnum + 1
 ifchecklist[indentnum] = "%&lt;ifcheck&gt;"
end</send>
  </trigger>

  <trigger
   enabled="y"
   match="^[\s]*endif$"
   omit_from_output="y"
   regexp="y"
   script="SendEndifNote"
   sequence="100"
  >
  </trigger>

  <trigger
   enabled="y"
   match="^\s*$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>if inprog == true then
 indentnum = 0
 inprog = 0
end</send>
  </trigger>

  <trigger
   enabled="y"
   match="^[\s]*else$"
   omit_from_output="y"
   regexp="y"
   script="SendElseNote"
   send_to="12"
   sequence="100"
  >
  </trigger>

</triggers>


<!--  Script  -->

<script>
<![CDATA[
local indentnum, ifchecks, ifchecklist, inprog
inprog = false
indentnum = 0
ifchecks = 0
ifchecklist = {}

function SendElseNote (str)
 require "tprint"; tprint (ifchecklist)
 print (indentnum)
 ColourNote("yellowgreen", "black", "else ", "deepskyblue", "black", "//if "..ifchecklist[indentnum])
end -- function

function SendEndifNote (str)
 require "tprint"; tprint (ifchecklist)
 print (indentnum)
 ColourNote("yellowgreen", "black", "endif ", "deepskyblue", "black", "//if "..ifchecklist[indentnum])
if inprog == 1 then
 indentnum = indentnum - 1
end
end -- function

function InProgTrue (what)
inprog = true
end -- function
]]>
</script>


</muclient>
Australia Forum Administrator #5
See this:


<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<muclient>
<plugin
   name="Local_Test"
   author="Nick Gammon"
   id="dc0d7a3af05433f612a2627b"
   language="Lua"
   purpose="tests local declaration"
   date_written="2009-02-23 15:04:15"
   requires="4.40"
   version="1.0"
   >

</plugin>


<!--  Aliases  -->

<aliases>
  <alias
   match="zeno"
   enabled="y"
   send_to="12"
   sequence="100"
  >
  <send>

print ("indentnum=", indentnum)

</send>
  </alias>
</aliases>

<!--  Script  -->


<script>
<![CDATA[
local indentnum, ifchecks, ifchecklist, inprog
inprog = false
indentnum = 0
]]>
</script>


</muclient>


Test:


zeno

Output

indentnum= nil



Remove the "local" in front of indentnum. You are giving your script a different copy to what the alias gets (or the trigger, or whatever).

Local variables are local to a compiled block. The script is compiled at one time, the trigger/alias "send to script" are compiled at a different time, in different blocks.
Amended on Mon 23 Feb 2009 03:09 AM by Nick Gammon
USA #6
Thanks, that's what I had before I changed it to local to see if that would fix it. Somehow it works now though.

Here is a preview of the plugin on the imp prog:
http://img.photobucket.com/albums/v123/rebirthseph/mc_plugin_prog.png

It generates C++ style comments on if/elses.
Australia Forum Administrator #7
Very nice.
USA #8
Is there some special way to use entities with ColourNote?
  <!ENTITY else_color "yellowgreen" >

ColourNote("&else_color;", "black", "else ")


It's being colored as default Note().
Amended on Mon 23 Feb 2009 05:00 AM by Zeno
Australia Forum Administrator #9
The CDATA is suppressing the entity replacement. Try something like this:


<!--  Script  -->

<script>

else_color = "&else_color;"

<![CDATA[


-- later on ...

ColourNote(else_color, "black", "else ")

USA #10
Thanks. What about when I am using Note or ColourNote, is there a way to make it the last color from the MUD? I am giving an option to disable syntax coloring, but when I suppress the output of an else and replace it to add on the C++ style comment to show what ifcheck it came from, it is using the default Note() color.

Or some way to simply append to the out of an output line on the MUD.

[EDIT] v1 release: http://zeno.biyg.org/~zeno/Smaug_prog_parse.xml
Amended on Mon 23 Feb 2009 06:19 AM by Zeno
Netherlands #11
You'll probably want to do something along the following lines:



function GetLastColours()
  -- Calculate the line number.
  local most_recent_line = GetLinesInBufferCount()-1
  
  -- Obtain the amount of styles on the most recent line.
  local last_style = GetLineInfo(most_recent_line, 11)
  
  -- Obtain colours in RGB format.
  local last_fg_rgb = GetStyleInfo(most_recent_line, last_style, 14)
  local last_bg_rgb = GetStyleInfo(most_recent_line, last_style, 15)
  
  -- Convert them to a format ColourTell/ColourNote can use.
  local last_fg = RGBColourToName(last_fg_rgb)
  local last_bg = RGBColourToName(last_bg_rgb)
  
  return last_fg, last_bg
end

-- Use like:
ColourNote(unpack(GetLastColours()), "Dumdeedum.")

-- or...
local fg, bg = GetLastColours()
ColourNote(fg, bg, "Dumdeedum once more.")


Do note that I did not test this code, nor that it handles the case in which there is no output whatsoever in the window. That should not be a problem with your usecase, though.

Edit: Oh wait, you said last color from the mud. That can be done too, but I'm too lazy to work that one out. A for-loop and a check with GetLineInfo() having the InfoType of 4 should probably help...
Amended on Mon 23 Feb 2009 06:44 AM by Worstje
USA #12
What if the line was omitted from output per a trigger? That would probably be the line I need to get the style from, will GetLinesInBufferCount count omitted lines?
Australia Forum Administrator #13
If you are using Lua, it is easy because the style runs are passed to the trigger, so you can rework the line, even if it is omitted. That is how the plugins work that send chats to other windows.
USA #14
v1.1 released:
-If an ifcheck had an or, it also appends the or in comments
-Command 'ToggleColoring' turns off Syntax Highlighting (keeps comments).
http://i41.tinypic.com/2628nrq.png

DL: http://www.biyg.org/forums/download/file.php?id=7
If link is dead, it's at the bottom here: http://www.biyg.org/forums/viewtopic.php?f=2&t=2167

Nick, is there a simple mouseover function to use? I know there is MiniWindows etc, but I want something simple (like how MC displays the line time).
Amended on Sun 01 Mar 2009 07:35 PM by Zeno
Australia Forum Administrator #15
No.