Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ Lua ➜ unpack() or ColourNote() weirdness

unpack() or ColourNote() weirdness

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Ked   Russia  (524 posts)  Bio
Date Sat 27 May 2006 11:05 PM (UTC)
Message
While trying to answer a question about displaying a prompt with colours preserved, in this thread: http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=6589&page=999999, I've stumbled upon Lua's unpack() function, which solves a problem I've encountered a while ago, when trying to do essentially what the thread above asks. The problem was needing multiple ColourTell calls to display a prompt, which can be very bad for performance in some cases. Back then I opted for parsing packets in OnPluginPartialLine, which turned out to be much faster, but now I'd like to try to do it the "clean" way. There's a new problem however. Here's the function:


function echoLastPrompt()
   prompt = table.remove(prompts)
   -- if prompt is nil then we are out of prompts to
   -- display for now
   if prompt == nil then
      return
   end

   local args = {}  -- a table to hold ColourNote arguments

   -- iterate over the styles in the prompt
   for chunk,style in prompt do
      table.insert(args, RGBColourToName(style.textcolour))
      table.insert(args, RGBColourToName(style.backcolour))
      table.insert(args, style.text)
   end

   ColourNote(unpack(args))
end


This looks like it should work, but every time I try to use it, I get an error complaining about a bad last argument to ColourNote (no value instead of string). The really confusing part is that if I add a print(unpack(args)) statement right before ColourNote(unpack(args)) then everything works just fine, except I get an extra note printed on the screen.

I've tried just unpacking the list prior to calling ColourNote, in hope that this is some quirk of unpack() that for some reason requires me to call it twice, so I can usefully employ the return from the second call, but with no luck - it seems to only work when I use print(unpack(args)).

Any ideas?

Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #1 on Sat 27 May 2006 11:42 PM (UTC)

Amended on Sat 27 May 2006 11:43 PM (UTC) by Nick Gammon

Message
Well this works for me with no errors, and displaying as it should:


local args = {}  -- a table to hold ColourNote arguments


   table.insert(args, "blue")
   table.insert(args, "green")
   table.insert(args, "Hello")

   table.insert(args, "white")
   table.insert(args, "red")
   table.insert(args, ", world")

   ColourNote(unpack(args))



Try doing: tprint (args)

Just to check your args are set up as you expect.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Ked   Russia  (524 posts)  Bio
Date Reply #2 on Sun 28 May 2006 12:28 AM (UTC)

Amended on Sun 28 May 2006 12:29 AM (UTC) by Ked

Message
Still no luck and no clue. tprint(args) shows that I have the table laid out correctly, and the function works every time I use tprint(args) before ColourNote(unpack(args)). Just as it works when I use print() or print(anything) before the ColourNote. But stops working as soon as I skip the printing and use the ColourNote alone.

Now I am suspecting that ColourNote is somehow to blame. I've changed the function a bit, to display a label before the echoed prompt:


function echoLastPrompt()
   local prompt = table.remove(prompts)
   -- if prompt is nil then we are out of prompts to
   -- display for now
   if prompt == nil then
      return
   end

   local args = {}  -- a table to hold ColourNote arguments

   -- iterate over the styles in the prompt
   for chunk,style in ipairs(prompt) do
      table.insert(args, RGBColourToName(style.textcolour))
      table.insert(args, RGBColourToName(style.backcolour))
      table.insert(args, style.text)
   --tprint(args)
   end

   ColourNote("silver", "", "[Note]", unpack(args))
end


I call the function from the command line after making sure that some prompts have been collected in the global table. The first time I call echoLastPrompt() I get the following error message and nothing on the screen:


Error number: 0
Event:        Run-time error
Description:  [string "Script file"]:41: bad argument #6 to `ColourNote' (string expected, got no value)
stack traceback:
	[C]: in function `ColourNote'
	[string "Script file"]:41: in function `echoLastPrompt'
	[string "Command line"]:1: in main chunk
Called by:    Immediate execution


If I call echoLastPrompt() again right afterwards (without reloading the script or touching anything else), then I get this string printed with all the correct colours:

[Note][Note]4073h, 3380m, 19265e, 15800w exd-


Top

Posted by Ked   Russia  (524 posts)  Bio
Date Reply #3 on Sun 28 May 2006 12:49 AM (UTC)
Message
Another weirdness... The error message I posted above is displayed for a ColourNote that should print a prompt with two style runs and that "[Note]" prepend, so there should be a total of 9 arguments (3 parts * 3 args each), yet the error reports a 6th argument missing. How is that even possible? If one of the arguments is indeed missing (which it is not but I am willing to play along) then I am passing 8 arguments, all of which are strings. How is it able to figure out that the 6th argument out of 8 is missing? Shouldn't it be reporting argument #9?
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #4 on Sun 28 May 2006 04:53 AM (UTC)

Amended on Sun 28 May 2006 05:18 AM (UTC) by Nick Gammon

Message
This isn't all making total sense. For one thing, your function echoLastPrompt is changing its environment (by doing table.remove) so I would expect different behaviour if you called it twice in a row.

Second, I would tprint at the end of the loop, to see what we are sending to ColourNote, not in each iteration,

Try this - I have removed the deletion of the last element, and am printing both the prompt table, and the args table.


function echoLastPrompt()
   -- get last prompt
   local prompt = prompts [table.getn (prompts)]
   if prompt == nil then
      return
   end

   print ("Prompt table = ")
   tprint (prompt)

   local args = {}  -- a table to hold ColourNote arguments

   -- iterate over the styles in the prompt
   for chunk,style in ipairs(prompt) do
      table.insert(args, RGBColourToName(style.textcolour))
      table.insert(args, RGBColourToName(style.backcolour))
      table.insert(args, style.text)
   end

   print ("args table = ")
   tprint(args)

   print ("arg count = ", table.getn (args))

   ColourNote("silver", "", "[Note]", unpack(args))
end


Quote:

How is it able to figure out that the 6th argument out of 8 is missing?


See this test:



ColourNote ("white", "red", "hi there", 
            "blue", "green", nil, 
            "white", "black", "everyone")


Output

[string "Immediate"]:17: bad argument #6 to `ColourNote' (string expected, got nil)
stack traceback:
	[C]: in function `ColourNote'
	[string "Immediate"]:17: in main chunk



In this example, I have 9 arguments, but it is reporting an error on argument 6, that is possible for it to do.

Your error was "got no value", not "got nil", so this example is probably not what is happening to you. However without the printout that I have inserted (print ("arg count = ", table.getn (args))) you can't really be sure you have 9 arguments there.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #5 on Sun 28 May 2006 04:55 AM (UTC)
Message
What version of MUSHclient are you using?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Ked   Russia  (524 posts)  Bio
Date Reply #6 on Sun 28 May 2006 05:19 AM (UTC)
Message
The latest one - 3.74
Top

Posted by Ked   Russia  (524 posts)  Bio
Date Reply #7 on Sun 28 May 2006 05:34 AM (UTC)
Message
The tprint() ended up inside the loop because I wanted to try out all possible points where I could put it - it was originally outside.

And as for the nil argument example, that's perfectly reasonable: it expects a string in the 6th argument and gets a nil there, so it complains about argument #6 being wrong. But in my case it gets strings in all arguments except (presumably) 9th, yet complains about the 6th, which should be perfectly fine. So there has to be something fishy going on inside ColourNote, as I doubt that unpack() can magically insert a hole inside an argument list of another function. This could happen if, for example, some outter function (also called ColourNote), upon receiving 9 arguments for ColourNote were to call the real ColourNote with the first three, then itself with the last 6 arguments -> ColourNote with the first 3 out of 6 -> itself with the last 3 -> ColourNote with 3. Then at the second step there it would indeed report the 6th argument missing. That's about the only idea I have.

Finally, you are probably on to something with the table.remove() call - removing it and passing the prompt to be displayed as an argument to the function solved the problem completely. It's still pretty intriguing.
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #8 on Sun 28 May 2006 05:35 AM (UTC)
Message
Here is an interesting clue:


local args = {}  -- a table to hold ColourNote arguments


   table.insert(args, "blue")    -- 1
   table.insert(args, "green")   -- 2
   table.insert(args, "Hello")   -- 3
   table.insert(args, "white")   -- 4
 
   ColourNote (unpack(args))

Output
[string "Immediate"]:9: bad argument #6 to `ColourNote' (string expected, got no value)
stack traceback:
	[C]: in function `ColourNote'
	[string "Immediate"]:9: in main chunk



In this example there is no argument 5 either, however it is objecting to argument 6.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #9 on Sun 28 May 2006 05:48 AM (UTC)
Message
Try as I might with various combinations I can't reproduce your error message.

Your loop:


-- iterate over the styles in the prompt
   for chunk,style in ipairs(prompt) do
      table.insert(args, RGBColourToName(style.textcolour))
      table.insert(args, RGBColourToName(style.backcolour))
      table.insert(args, style.text)
   end


... should always be putting values in groups of 3 into args, so I don't see how the last one is discarded.

Quote:

This could happen if, for example, some outter function (also called ColourNote) ...


Are you in fact calling the real ColourNote or some wrapper you wrote?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Ked   Russia  (524 posts)  Bio
Date Reply #10 on Sun 28 May 2006 05:52 AM (UTC)
Message
Doesn't tell me anything :) But check this out (in the command window and one after the other, not all at once):


ColourNote(unpack({"white", "", "hello", "red", ""}))
ColourNote(unpack({"white", "", "hello", "red", ""}))
print()


Output:


hellohello
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #11 on Sun 28 May 2006 06:05 AM (UTC)
Message
I can't reproduce that either. I get an error message. Are you sure you haven't written your own ColourNote function? Try this:


/tprint (debug.getinfo (ColourNote))

Output

"source"="=[C]"
"what"="C"
"func"=function: 010ECFC8
"short_src"="[C]"
"currentline"=-1
"namewhat"=""
"linedefined"=-1
"nups"=0


Your address will probably be different, but you should see a C function. However if you have your own wrapper, you will see something like this:


"source"="Script file"
"what"="Lua"
"func"=function: 01154A30
"name"="ColourNote"
"nups"=0
"currentline"=-1
"namewhat"="global"
"linedefined"=657
"short_src"="[string "Script file"]"

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Ked   Russia  (524 posts)  Bio
Date Reply #12 on Sun 28 May 2006 06:30 AM (UTC)

Amended on Sun 28 May 2006 06:31 AM (UTC) by Ked

Message
Nope, I am using it directly, and I don't have a wrapper lost somewhere - I am doing all this on a clean world file with no plugins and my debug.getinfo shows the same thing as yours, except for the address.

Quote:
I can't reproduce that either. I get an error message.


You get two - one for each ColourNote. You just need to dismiss them by pressing the Close button and do the next ColourNote, then print().
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #13 on Sun 28 May 2006 06:58 AM (UTC)
Message
So you are referring to the fact that they are on the same line?

I would expect that. All that ColourNote does in Lua is do repeated calls to ColourTell, except that the last one is a call to ColourNote.

So, if it crashes halfway through, you have done some ColourTells without the final ColourNote.

And, as you can see, you won't save any particular time doing it the way you are proposing, to manually doing your own ColourTells in a loop.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


31,587 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.