[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  General
. . -> [Subject]  GetLineInfo questions

GetLineInfo questions

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


Posted by Ked   Russia  (524 posts)  [Biography] bio
Date Fri 23 May 2003 03:00 PM (UTC)
Message
I was reading through the online help for the GetLineInfo callback, and a few questions surfaced in my mind. First of all, the help emphasizes the difference between the line count in buffer and actual count of lines recieved. I can appreciate that but what count should I use with GetLineInfo exactly? I am guessing that it's GetLinesInBufferCount but would like to be sure about that.

Another question pertains to the part of the help which mentions the possibility of the last line being blank. This is more important for me, due to the task I am employing GetLineInfo for. I want to make a trigger which would match on a specific message and call a script to:
1. Find the line number of the matched line
2. Get the text of the line that follows immediately next
3. See if the latter line does NOT match a specific regexp
4. Perform some actions based on the results of 3

Now, I know that the line in 1 will be coming with a newline, so I need to know exactly if Muclient will add a blank line after that one or not. Meaning: whether I should do GetLineInfo(lastLine + 1) or GetLineInfo(lastLine + 2) (exact syntax ommited) to grab the following line? Hope that makes sense.

This also brings up another question: if Muclient will add a blank line after a newline, then would doing GetLinesInBufferCount in script called by a trigger return the number of the matched line or the number of the blank line following it? Sorry, but field testing all of this is just plain painful, so I am hoping that the answers exist already.

Thanks in advance.
[Go to top] top

Posted by Ked   Russia  (524 posts)  [Biography] bio
Date Reply #1 on Fri 23 May 2003 03:45 PM (UTC)
Message
erm, the script would have to look backwards in the buffer, not forward obviously
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #2 on Fri 23 May 2003 09:32 PM (UTC)
Message
Hmm - this raises some complex questions, and it is hard to debug with world.Note because obviously doing that adds stuff to line count as you are doing it.

First you use GetLinesInBufferCount to find the last line, the example under GetLineInfo makes that pretty clear. The GetLinesInBufferCount returns the number of lines currently in the buffer, and GetLineInfo gets information about the lines presently in the buffer.

However there is another problem, and that is that there are two sorts of lines. The first is the physical line, which you actually see on the screen, and which GetLineInfo returns information about, and the "logical" lines (paragraphs, really) which end in a newline from the MUD. Depending on the MUD type, and your screen width, physical and logical lines might be the same. However with a narrow screen width they are probably not. Here is an example:


01: ‘Twas brillig, and the slithy toves
02: Did gyre and gimble in the wabe: (newline)
03: All mimsy were the borogoves,
04: And the mome raths outgrabe.
05: "Beware the Jabberwock, my son! (newline)
06: The jaws that bite, the claws that catch!
07: Beware the Jubjub bird, and shun
08: The frumious Bandersnatch!" (newline)


In this hypothetical example, there are 8 physical lines in the screen, however only 3 logical lines (ending in newline). Newline is the character 0x0A (\n) which you receive from the MUD.

Triggers match on logical lines, and thus a trigger that matched on "Jubjub" would match when line 8 arrived, however the trigger match text woiuld be lines 6, 7, and 8 concatenated (ie. the match text would be 'The jaws that bite, the claws that catch! Beware the Jubjub bird, and shun The frumious Bandersnatch!" '.

The reason for this is triggers should match on logical lines, regardless of how you currently have the screen width set up.

So you can see your problem is more complicated than "subtracting one". In this example, you would need to scan backwards, looking for a line with the "hard return" flag set, which would the the last line from the previous logical line, and then keep scanning backwards until you got (yet another) line with the "hard return" flag set, and then add one. The difference between those two batches of lines would be the previous logical line. You then need to get the text from those line(s), concatenate them together, and then do whatever you want with them.

As for your question about the blank line at the end, as far as I can see from the trigger matching code, when the trigger fires that blank line has not been added yet, so the last line in the buffer should actually be the line that caused the trigger to fire (allowing for the multiple line problem I just described).

What is probably much, much simpler, is simply to do this ...


  1. Make a "catch all" trigger that matches every line (eg. match on * if you don't mind missing blank lines).
  2. Give this trigger a low sequence (eg. 50) and set it to "keep evaluating" (so other triggers are still processed).
  3. Have this trigger save the matching line as "the previous line" in your script (eg. in a variable)
  4. Have your "real" trigger have a lower sequence (eg. 40) - so the previous line is not stored yet
  5. When the real trigger fires, it can look at the saved line (from the other trigger) to see what was received in the previous line, run its regexp on it, and then do whatever.


That way you achieve the same result without mucking around with lines in the line buffer. Let the program do all that work for you.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Shadowfyr   USA  (1,786 posts)  [Biography] bio
Date Reply #3 on Sat 24 May 2003 03:04 AM (UTC)

Amended on Sat 24 May 2003 03:06 AM (UTC) by Shadowfyr

Message
Unless you are trying to retrieve color information, in which case the logic used to get such information still won't work. I knew this sort of thing would crop up back when I complained about there being no way to retrieve the 'actual' pre-processed line contents, for which 'no' command or function exists. Having to rummage through the output lines to find what you want is imho seriously against the design principle of keeping things simple so they work right. It makes something that should be simple rediculously complicated. But that is the design choice you made for these functions, in spite of everything I did to change your mind. ;)
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #4 on Sat 24 May 2003 07:34 AM (UTC)

Amended on Sat 24 May 2003 07:36 AM (UTC) by Nick Gammon

Message
Quote:

... there being no way to retrieve the 'actual' pre-processed line contents, for which 'no' command or function exists ...


Well, if you really want it, there is OnPluginPacketReceived.

I would be pleased to know how there is a "simple" way of retrieving colour information from raw (pre-processed) lines.

For a start, ANSI colours can be expressed in a number of ways. For instance, red on yellow might appear as:


ESC [ 31 m ESC [ 43 m
ESC [ 43 m ESC [ 31 m
ESC [ 31; 43 m


(spaces added for clarity).

Do you really want to parse all this yourself? They are not even together, you might have:


some text ESC[31m some more text ESC[43m blah blah


To find the colour "blah blah" is in you have to carefully parse the entire line, and even this isn't enough. You need to know what colour the line started in. If the previous line was green on blue then the words "some text" are not white on black, they are green on blue.

Sounds like a big job to me. Then there is MXP. Using MXP tags you can change text to any colour, eg.


blah blah <color fore=maroon back=lightgreen> some more text


Seeing the "raw data" means you now need to parse MXP as well. Then you have the problem that the MXP server might be using user-defined tags, so you might actually see:


blah blah <foo> some more text


Where <foo> sets the colour to bold italic grey on purple.



It seems to me that the unprocessed line is really useless to you, and that is why there is no mechanism to get it, besides OnPluginPacketReceived if you want to be a masochist.

If you want to know how the line ended up, then you need to define some sort of "colour information" system (there is not one I know of, excepting maybe HTML tags) which you are then going to have to re-parse yourself, which wouldn't be the fastest thing in the world in an interpreted script engine. Maybe something like this:


blah blah <color fore=red back=blue><bold>some more text</bold></color>


The system I presently have, of letting you follow style runs, lets you retrieve colour information reasonably quickly, without having to write a "colour parser" yourself.

I know it isn't perfect, and am open to reasonable suggestions for improvements - suggests that take into account the points raised above. Also take into account the issue raised earlier on in this thread, the difference between logical and physical lines. :)




- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Shadowfyr   USA  (1,786 posts)  [Biography] bio
Date Reply #5 on Sat 24 May 2003 08:44 PM (UTC)
Message
True... I am not sure any 'good' solution exists. The only one I can thinf of would require something like:

1. Logical line recieved.

2. Processed to convert tags to output format.

3. Capture stage, trigger/script function can 'grab' the processed, but as yet undisplayed, line with the formatting. Note this requires that the sub recieve not just the text, but an array of the styles and positions in the logical line that they appear. Such a sub would also require that the used test to see if it is the right one, so is not as effective as if a special trigger could be used that would give you (Name, Output, Wildcards, LineStyles, StylePositions).

4. Actually send the formatted content to the output window.

It should work in theory, but flies in the face of the existing implimentation which apparently displays the line as it processes it, thus probably not practical. Though the trigger 'might' be set up to only match when a complete matching logical line is found, but that would mean a seperate process for such triggers than the normal ones.

There is definitely one quirks though that drives me nuts and often screws up the best laid plans intended to make such things possible. World.note's habit of sometimes screwing up some of my plugin outputs due to it not bothering to wait for a newline before acting is one example. Ironically the only real issue for that is 'lag', prompts and timers. Having changed my prompt to include a newline, this is not as big an issue for me, but for those that can't or when you use timed output... The reasons why things work that way are obvious, but doesn't change the fact that the solution on the user end is sometimes either more complex that one done in the client itself or may even be completely impossible to fix at all for the user (i.e. when using the timers).

Though, if you could set a flag that specified 'display notes only on newline', then those of us that can safely use them that way would be a lot less frustrated. This is after all generally only an issue with notes sent by scripts linked to timers, which don't automatically require a newline before taking effect. Of course some triggers don't either, but that 'can' be fixed with a few changes to the trigger's design. The user could enable that flag as the first thing in the timer's script, then disable it before the script exits, as long as the already sent note output is buffered to await the next newline of course. It wouldn't be much use if disabling it suddenly caused all of it to send instantly anyway.

To go back the the line style issue. Worrying about notes sent by the script you are in is not, even as things stand, a major issue. You simple find the first line you want, read all the styles and positions into a dynamic array until you hit the end of the logical line and use that information in the rest of your script. It is silly to start sending a mess of notes to output before you have all the data needed to do it properly.

Though imho, no solution to this is 100% fool proof if a timer's script output can hammer the contents of the logical line you are trying to do something with. Unfortunately no solution directly addresses the 'I want to replace one word in a line, but still keep all the colors' problem that people sometimes bring up. ;) This however I don't see any solution to short of altering the actual contents of the packets themselves using some external proxy, a dangerous and extremely complex solution in and of itself.
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #6 on Sat 24 May 2003 08:54 PM (UTC)
Message
I was aware of the potential for trigger output to get confused when I initially wrote it, so the "send" box (if you simply send to output) is actually deferred (into a string) so that gets sent later.

However the problem is when you do colournotes, that they are not deferred (they are not just simple strings for one thing, and for another they are not directly tied to a trigger).

One possible thing would be to build up an ANSI coded string into a variable and output it a moment later (with a timer maybe), however this isn't a brilliant solution either.

I understand about the problem of wanting to replace text, and keep the colours. Maybe there is a solution somewhere, like switching from "prompt" mode (where text is displayed as it is received, during the login phase) to "line-by-line" mode later on. Perhaps that would do it.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Shadowfyr   USA  (1,786 posts)  [Biography] bio
Date Reply #7 on Sat 24 May 2003 09:28 PM (UTC)

Amended on Sat 24 May 2003 09:29 PM (UTC) by Shadowfyr

Message
Yes. I understand that ColourTell, ColourNote, Tell and Note are not deferred. However, my point is that they don't normally need to be, except when you use a timer, since timers, unlike triggers, don't care if you are in the middle of a paragraph that is going to be 50 lines long in output. It would be useful for the user to have the option to specifically tell the client to defer the lines they are building in a script, so that they can avoid this. I am a bit confused here, since what then stops you from providing the user option to buffer the note/colournote information to defer its display, then just give the output the contents of the buffer when the newline arrives? In fact, I am even more confused, because I know for a fact that one recent change you made was to delay output of colourtells until a note or colournote terminated the process of building that line. This means you already have the result ready to be sent to output or placed into a seperate buffer to intentionally defer it, you simply need a provision to test if that option is on/off and defer output of the buffered content until a newline. Exactly what about these lines prevents them from being handled this way?

As for a prompt mode/line-by-line mode.. That is definitely an idea, though it really only solves the problem for people that can use it. Most muds leave you hanging with an incomplete line when waiting for input and that kind of screws up any line-by-line system. You wouldn't be able to test for when to turn it off once you turned it on. :p
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #8 on Sat 24 May 2003 09:44 PM (UTC)

Amended on Thu 24 Jul 2003 09:44 PM (UTC) by Nick Gammon

Message
Quote:

In fact, I am even more confused, because I know for a fact that one recent change you made was to delay output of colourtells until a note or colournote terminated the process of building that line.


It wasn't delayed, the screen refresh was omitted. If you did a colourtell, and then moved another window in front of MUSHclient and moved it away again, it would refresh and show you what was there. That was to stop flicker, more than anything, and to reduce the delay caused by lots of screen redraws.

The reason I didn't buffer it was simply that it was easy to store a simple string (just append it) but to buffer colourtells would involve storing styles (eg. XXX colour red/green, followed by YYY colour blue/black).




- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Shadowfyr   USA  (1,786 posts)  [Biography] bio
Date Reply #9 on Sat 24 May 2003 10:01 PM (UTC)
Message
Ah.. I see. So it would require some serious redesign to impliment. Unfortunate. :p
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #10 on Sat 11 Dec 2004 02:42 AM (UTC)

Amended on Sat 11 Dec 2004 03:59 AM (UTC) by Nick Gammon

Message
Quote:

Unless you are trying to retrieve color information, in which case the logic used to get such information still won't work. I knew this sort of thing would crop up back when I complained about there being no way to retrieve the 'actual' pre-processed line contents, for which 'no' command or function exists.


Shadowfyr, I have seen the light, you will be pleased to know. :)

Version 3.59 of MUSHclient has a fairly small change to the OnPluginPacketReceived function, which allows you to *change* the contents of the packet (simply by returning the value that you want it to become).

For example:


Function OnPluginPacketReceived (s)
  OnPluginPacketReceived = Replace (s, "east", "EAST")
end function


This is done in the initial processing of packets, before trigger matching, ANSI code processing etc. (however, after MCCP decompression).

So now you can change words to your heart's content, throw in extra ANSI codes, discard others and so on.

My earlier caveats about this still apply, you get packets, not lines, so (in the above example) if the word "east" was split over two packets then it wouldn't be detected.

However what it does do is give you an incredible amount of power, if used wisely, to change how things look. You can:


  • Discard lines *before* they are displayed

  • Add colour codes (ANSI codes)

  • Drop or change colour codes

  • Detect MXP codes

  • Insert your own MXP codes

  • Change words

  • Change line-wrappping (eg. by throwing away newlines in the middle of paragraphs).

  • Fix troublesome MXP implementations. eg if a MUD has a habit of sending <west> when it should send &lt;west&gt; then you can fix it up and sent it on.


What I suggest you do, to retain some semblance of order, is to batch up packets into lines yourself, especially as one packet may have multiple lines in it. eg.


  • Take the incoming packet and append to any previously-saved partial packet

  • Break this into lines (ie. split at newlines)

  • Apply your processing to each line (eg. discard, search, change)

  • Save any partial lines (ie. any lines not terminated by a newline) for next time

  • Concatentate the changed/fixed lines back into a single string, separated by newlines.

  • Return that string


Effectively this is adding a preprocessing stage to what MUSHclient normally does.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #11 on Sat 11 Dec 2004 03:07 AM (UTC)
Message
One thing you will discover pretty quickly if you try this, is that the prompt line goes away (if you use the above technique) because it doesn't have a newline after it.

However you could conceivably have a special test - if the packet matches a regular expression (ie. it looks like a prompt line) then you could return it, so that the prompt line still appears.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #12 on Sat 11 Dec 2004 03:41 AM (UTC)
Message
Just to document what I did to do a reasonable test of this ... here is what I wrote in Lua to do what I described above. This plugin saves partial lines, breaks input into lines, applies a test against each one, and returns the result.

In this particular demo it excludes blank lines, and lines with the word "turkey" on them.



<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<!-- Saved on Saturday, December 11, 2004, 12:46 PM -->
<!-- MuClient version 3.59 -->

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

<muclient>
<plugin
   name="packet_received_test"
   author="Nick Gammon"
   id="1013a5322db1b693d084bd0f"
   language="Lua"
   purpose="Testing OnPluginPacketReceived"
   date_written="2004-12-11 12:45:32"
   requires="3.59"
   version="1.0"
   >
</plugin>

<!--  Script  -->

<script>
<![CDATA[

partial = ""  -- partial line from last time through

function OnPluginPacketReceived (s)

  -- add packet to what we already have (excluding carriage-returns)
  
  partial = partial .. string.gsub (s, "\r", "")
  
  t = {}  -- table of lines to be returned
  
  -- iterate over each line
  
  partial = string.gsub (partial, "(.-)\n", 
    function (line)
      if line ~= "" and   -- discard blank lines
         not string.find (line, "turkey", 1, true) then  
        table.insert (t, line)
      end -- if
    end)  -- function
  
  if table.getn (t) > 0 then
    table.insert (t, "")  -- to get final linefeed
  end -- if
  
  -- return table of lines, concatenated with newlines between each one
  return table.concat (t, "\n")
  
end -- function OnPluginPacketReceived
]]>
</script>

</muclient>

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] 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.


20,749 views.

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

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

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

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]