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.
 Entire forum ➜ MUSHclient ➜ Lua ➜ String split.

String split.

Posting of new messages is disabled at present.

Refresh page


Posted by Blainer   (191 posts)  Bio
Date Sat 20 Jun 2009 02:40 PM (UTC)

Amended on Sat 20 Jun 2009 03:52 PM (UTC) by Blainer

Message
Can anyone tell me how to split these into a table with the colour code and text. I am tying to get to the same layout as the styles table from triggers.

"a @Bblue @wpotion"
"an adventurer's head"
"@Y(@w!@Y(@WEyes of the Wolf@Y)@w!@Y)@w"


This is as far as I have got after like 9 hours and it doesn't work at all.


function string_test()
colours={}
	
colours={
		R = "darkred",
		B = "darkblue",
		C = "darkcyan",
		M = "darkmagenta",
		Y = "darkyellow",
		G = "darkgreen",
		W = "darkwhite",
		D = "gray",
		r = "red",
		b = "blue",
		c = "cyan",
		m = "magenta",
		y = "yellow",
		g = "green",
		w = "white"
		}
	bground="black"
	
	inv_description="a @Bblue @wpotion"
	inv_description="a bone sword"
	inv_description="@Y(@w!@Y(@WEyes of the Wolf@Y)@w!@Y)@w"
	t={}
	function split(str, pat)
	   local t = {}  -- NOTE: use {n = 0} in Lua-5.0
	   local fpat = "(.-)" .. pat
	   local last_end = 1
	   local s, e, cap = str:find(fpat, 1)
	   while s do
	      if s ~= 1 or cap ~= "" then
		 			table.insert(t,cap)
	      end
	      last_end = e+1
	      s, e, cap = str:find(fpat, last_end)
	   end
	   if last_end <= #str then
	      cap = str:sub(last_end)
	      table.insert(t, cap)
	   end
	   return t
	end

	for i,v in pairs(split(inv_description, "\@([BCMYGWDrbcmygw])")) do
		colour = inv_description:match("\@([BCMYGWDrbcmygw])", i+1)
		if colour == "" then
			colour = "white"
		else
			colour = colours[colour]
		end

		t[i]={
					["textcolour"]=colour,
					["backcolour"]=bground,
					["length"]=string.len(v),
					["style"]=0,
					["text"]=v
					}
	end
	tprint(t)
end


More test data:
a long spike
@R(@w!@R(@rLight Relief@R)@w!@R)
@ya @ypot of @Ygold
an adventurer's head
a Pet Store Employee ID Card
a @WT@wrusty @RA@wylorian @YM@wace
@WGueldar's @wcrafted leather bracer
goblin ceremonial robes
a bone sword
a helm made from a dragon's skull
a bone sword
an evil looking black dagger
ornate robes
a bright ball of light
a well used backpack
a @Bblue @wpotion
a potion of protection
@Y(@w!@Y(@WEyes of the Wolf@Y)@w!@Y)
@wa @rdragon@R'@rs @Wbr@wea@Wth
@wa @rdragon@R'@rs @Wbr@wea@Wth
@WChalice of the @B<(@W=@YWatchmen@W=@B)>
a potion of protection
@G(@w!@G(@cGreen Tea@G)@w!@G)
@RVladia's @WShopping Bag
@YAylorian @CAcademy @Wcanoe
@YAcademy Healing Potion
an @RAardwolf @WAdventurer's Guide@w (type @Rread guide@w)
a potion of protection
@YAylorian @CAcademy @Wcanoe


Thanks
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #1 on Sat 20 Jun 2009 09:53 PM (UTC)

Amended on Sat 20 Jun 2009 09:54 PM (UTC) by Nick Gammon

Message
See this thread:

http://www.gammon.com.au/forum/?id=8947

The code in that (colourtext function) breaks up a string with Aardwolf colour codes (which it looks like you are using) and displays them, in colour, in a miniwindow.

- Nick Gammon

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

Posted by Blainer   (191 posts)  Bio
Date Reply #2 on Sun 21 Jun 2009 02:32 PM (UTC)
Message
Thanks Nick.
Top

Posted by Erendir   Germany  (47 posts)  Bio
Date Reply #3 on Mon 22 Jun 2009 09:39 AM (UTC)

Amended on Mon 22 Jun 2009 09:41 AM (UTC) by Erendir

Message
You can benefit from LPEG, now integrated into the MUSHclient. Here:


local function colour_conversion(c)

-- copied from http://www.gammon.com.au/forum/?id=8947
local BLACK = 1
local RED = 2
local GREEN = 3  
local YELLOW = 4 
local BLUE = 5 
local MAGENTA = 6 
local CYAN = 7 
local WHITE = 8

-- colour styles (eg. @r is normal red, @R is bold red)

-- @- is shown as ~
-- @@ is shown as @

-- This table uses the colours as defined in the MUSHclient ANSI tab, however the
-- defaults are shown on the right if you prefer to use those.
local t = {
   k = GetNormalColour (BLACK)   ,   -- 0x000000 
   r = GetNormalColour (RED)     ,   -- 0x000080 
   g = GetNormalColour (GREEN)   ,   -- 0x008000 
   y = GetNormalColour (YELLOW)  ,   -- 0x008080 
   b = GetNormalColour (BLUE)    ,   -- 0x800000 
   m = GetNormalColour (MAGENTA) ,   -- 0x800080 
   c = GetNormalColour (CYAN)    ,   -- 0x808000 
   w = GetNormalColour (WHITE)   ,   -- 0xC0C0C0 
   K = GetBoldColour   (BLACK)   ,   -- 0x808080 
   R = GetBoldColour   (RED)     ,   -- 0x0000FF 
   G = GetBoldColour   (GREEN)   ,   -- 0x00FF00 
   Y = GetBoldColour   (YELLOW)  ,   -- 0x00FFFF 
   B = GetBoldColour   (BLUE)    ,   -- 0xFF0000 
   M = GetBoldColour   (MAGENTA) ,   -- 0xFF00FF 
   C = GetBoldColour   (CYAN)    ,   -- 0xFFFF00 
   W = GetBoldColour   (WHITE)   ,   -- 0xFFFFFF 
   
   -- add custom colours here

  }  -- end conversion table

 return t[c] or -1

end -- colour_conversion
-----------
-- my code:

local P, C, Ct, Cs = lpeg.P, lpeg.C, lpeg.Ct, lpeg.Cs
local A = lpeg.R("az","AZ") -- symbols allowed to code a color
local NOTA = P(1) - A
local ANY = P(1) - P"@"
local text = Cs( (ANY + P"@-"/"~" + P"@@"/"@" + P"@"*NOTA)^1 ) -- skip any symbol but @, subst @-, @@. Skip @z, where z is not allowed by A. Try again.
local color = P"@"*(A/colour_conversion) -- replace @z with color code for z.
local res = Ct( ( text + color)^0) -- try text, then color. 0 or more times.

split_colors = function (s)
 return res:match(s)
end -- split


usage:

require 'tprint'
tprint( split_colors"an @RAardwolf @WAdventurer's Guide@w (type @Rread guide@w)")

gives:

1="an "
2=255
3="Aardwolf "
4=16777215
5="Adventurer's Guide"
6=12632256
7=" (type "
8=255
9="read guide"
10=12632256
11=")"
Top

Posted by WillFa   USA  (525 posts)  Bio
Date Reply #4 on Mon 22 Jun 2009 08:56 PM (UTC)
Message
Slightly different LPEG...


local function colour_conversion(c)

-- copied from http://www.gammon.com.au/forum/?id=8947
local BLACK = 1
local RED = 2
local GREEN = 3  
local YELLOW = 4 
local BLUE = 5 
local MAGENTA = 6 
local CYAN = 7 
local WHITE = 8

-- colour styles (eg. @r is normal red, @R is bold red)

-- @- is shown as ~
-- @@ is shown as @

-- This table uses the colours as defined in the MUSHclient ANSI tab, however the
-- defaults are shown on the right if you prefer to use those.
local t = {
   k = GetNormalColour (BLACK)   ,   -- 0x000000 
   r = GetNormalColour (RED)     ,   -- 0x000080 
   g = GetNormalColour (GREEN)   ,   -- 0x008000 
   y = GetNormalColour (YELLOW)  ,   -- 0x008080 
   b = GetNormalColour (BLUE)    ,   -- 0x800000 
   m = GetNormalColour (MAGENTA) ,   -- 0x800080 
   c = GetNormalColour (CYAN)    ,   -- 0x808000 
   w = GetNormalColour (WHITE)   ,   -- 0xC0C0C0 
   K = GetBoldColour   (BLACK)   ,   -- 0x808080 
   R = GetBoldColour   (RED)     ,   -- 0x0000FF 
   G = GetBoldColour   (GREEN)   ,   -- 0x00FF00 
   Y = GetBoldColour   (YELLOW)  ,   -- 0x00FFFF 
   B = GetBoldColour   (BLUE)    ,   -- 0xFF0000 
   M = GetBoldColour   (MAGENTA) ,   -- 0xFF00FF 
   C = GetBoldColour   (CYAN)    ,   -- 0xFFFF00 
   W = GetBoldColour   (WHITE)   ,   -- 0xFFFFFF 
   
   -- add custom colours here

  }  -- end conversion table

 return t[c] or -1

end -- colour_conversion
-----------
-- my code:

local P, C, Ct, Cs, Cg, S, Cc = lpeg.P, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Cg, lpeg.S, lpeg.Cc
local ColorFlags = "cmykrgbw"
local Colors = P"@" * C(S(ColorFlags .. ColorFlags:upper()))
local ANY = P(1) - P"@"
local text = Cg(Cs( (ANY + P"@-"/"~" + P"@@"/"@" + (P(1) - Colors) )^1 ),"text") 
local color = Cg( (Colors + Cc('w')) / colour_conversion ,"textcolour") 
local res = Ct( Ct( color * text)^1) 

split_colors = function (s)
 return res:match(s)
end -- split


this returns:


1:
  "text"="an "
  "textcolour"=12632256
2:
  "text"="Aardwolf "
  "textcolour"=255
3:
  "text"="Adventurer's Guide"
  "textcolour"=16777215
4:
  "text"=" (type "
  "textcolour"=12632256
5:
  "text"="read guide"
  "textcolour"=255
6:
  "text"=")"
  "textcolour"=12632256


Since you said you'd like to replicate the layout of the styleruns table.

This is also a little more resilient, and will allow for malformed tags (i.e. "foo@1oo" or "re@aad" since @a isn't a valid color tag)
Top

Posted by Erendir   Germany  (47 posts)  Bio
Date Reply #5 on Mon 22 Jun 2009 09:26 PM (UTC)
Message
The code

(Colors + Cc('w')) / colour_conversion

makes

local function colour_conversion(c)
 [...]
 return t[c] or -1
end -- colour_conversion

obsolete.

(And yes, it's a very nice improvement :))
Top

Posted by Blainer   (191 posts)  Bio
Date Reply #6 on Tue 23 Jun 2009 02:25 AM (UTC)
Message
And it works perfectly. I have the Aardwolf inventory displayed in a miniwindow as it is sent from the MUD. :)
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #7 on Tue 23 Jun 2009 08:07 AM (UTC)
Message
That looks great! Love to see LPEG in use. :)

Can you post your inventory plugin? I bet it would be popular.

BTW, with the function colour_conversion - does that get called for every conversion? Or is it instantiated once? If more than once, you are doing a table creation many, many times. If so, it might be faster to move the colour table outside the function.

- Nick Gammon

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

Posted by WillFa   USA  (525 posts)  Bio
Date Reply #8 on Tue 23 Jun 2009 02:12 PM (UTC)

Amended on Tue 23 Jun 2009 03:00 PM (UTC) by WillFa

Message
Hmm, would the table be created just once when the function is compiled?

As Erendir pointed out, the function call "or -1" is obsolete because of the Constant capture {i.e. " + Cc('w')"} , and you can actually just have a table called instead of a function.



-- copied from http://www.gammon.com.au/forum/?id=8947
local BLACK = 1
local RED = 2
local GREEN = 3  
local YELLOW = 4 
local BLUE = 5 
local MAGENTA = 6 
local CYAN = 7 
local WHITE = 8

-- colour styles (eg. @r is normal red, @R is bold red)

-- @- is shown as ~
-- @@ is shown as @

-- This table uses the colours as defined in the MUSHclient ANSI tab, however the
-- defaults are shown on the right if you prefer to use those.
local colour_conversion = {
   k = GetNormalColour (BLACK)   ,   -- 0x000000 
   r = GetNormalColour (RED)     ,   -- 0x000080 
   g = GetNormalColour (GREEN)   ,   -- 0x008000 
   y = GetNormalColour (YELLOW)  ,   -- 0x008080 
   b = GetNormalColour (BLUE)    ,   -- 0x800000 
   m = GetNormalColour (MAGENTA) ,   -- 0x800080 
   c = GetNormalColour (CYAN)    ,   -- 0x808000 
   w = GetNormalColour (WHITE)   ,   -- 0xC0C0C0 
   K = GetBoldColour   (BLACK)   ,   -- 0x808080 
   R = GetBoldColour   (RED)     ,   -- 0x0000FF 
   G = GetBoldColour   (GREEN)   ,   -- 0x00FF00 
   Y = GetBoldColour   (YELLOW)  ,   -- 0x00FFFF 
   B = GetBoldColour   (BLUE)    ,   -- 0xFF0000 
   M = GetBoldColour   (MAGENTA) ,   -- 0xFF00FF 
   C = GetBoldColour   (CYAN)    ,   -- 0xFFFF00 
   W = GetBoldColour   (WHITE)   ,   -- 0xFFFFFF 
   
   -- add custom colours here

  }  -- end conversion table


-----------
-- our code:  :)

local P, C, Ct, Cs, Cg, S, Cc = lpeg.P, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Cg, lpeg.S, lpeg.Cc

local tmpcolorkeys = {}
for k,v in pairs(colour_conversion) do tmpcolorkeys[#tmpcolorkeys+1] = k end

local Colors = P"@" * C(S( table.concat(tmpcolorkeys, "") ))
tmpcolorkeys = nil  -- Clean up on aisle tempvar!
local NotAt = P(1) - P"@"
local NotAColor = P(1) - Colors
local text = Cg(Cs( (NotAt + P"@-"/"~" + P"@@"/"@" + NotAColor )^1 ),"text") 
local color = Cg( (Colors + Cc('w')) / colour_conversion ,"textcolour") 
local res = Ct( Ct( color * text)^1) 


split_colors = function (s)
 return res:match(s)
end -- split


The above uses a table instead of a function.
It also loops through the table once, grabbing the keys instead of hard-coding them. The "-- Add custom colours here" comment accurately instructs all you'd need to do to add more colors.

The other thing to note is an optimization in the grammar for text. It would still work if you had just the "swap ~" or "swap @" or "anything that's not a color flag", but the LPEG engine's optimized to grab "not this single char". (In PCRE terms: [^@]+ is faster than .*?@?) Also, since this will be the case in most instances, why make it go through 2 failed test ops first? It's good form for LPEG coding. (I saw this in the LPEG webcast that Roberto I. did)
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #9 on Tue 23 Jun 2009 09:35 PM (UTC)
Message
Quote:

Hmm, would the table be created just once when the function is compiled?


No, because the function code says to make a new local variable "t" every time it is called. This cut-down version illustrates that:


local function colour_conversion(c)

local BLACK = 1
local RED = 2
local t = {
   k = GetNormalColour (BLACK)   ,   -- 0x000000 
   r = GetNormalColour (RED)     ,   -- 0x000080 

  -- blah blah
  }  -- end conversion table

 print ("t is", t) -- debug

 return t[c]

end -- colour_conversion


print (colour_conversion('r'))

Output (from repeated tests)

t is table: 01D6C918
128
t is table: 01E6A288
128
t is table: 01F91990
128
t is table: 00D099D8
128
t is table: 01D1BDC8
128
t is table: 01DCEDC8
128


You can see that for every call, we have a new table.

A way around that is to make the table global (probably the simplest way), rather than putting it inside the function.

Another way is to generate a function, that stores the table as an upvalue, like this:


function make_colour_conversion ()
  
  local BLACK = 1
  local RED = 2
  local t = {
   k = GetNormalColour (BLACK)   ,   -- 0x000000 
   r = GetNormalColour (RED)     ,   -- 0x000080 

  -- blah blah
  }  -- end conversion table

return function (c)

 print ("t is", t) -- debug

 return t[c]

end -- function

end -- make_colour_conversion 

colour_conversion = colour_conversion or make_colour_conversion  ()

print (colour_conversion('r'))

Output (from repeated tests)

t is table: 01D5A558
128
t is table: 01D5A558
128
t is table: 01D5A558
128
t is table: 01D5A558
128
t is table: 01D5A558
128
t is table: 01D5A558
128
t is table: 01D5A558
128


In the code above we call make_colour_conversion (once) to get a colour_conversion function that stores the table as an upvalue. Since the function-creator is called once, the table is created once. However I don't think this gets us a huge way ahead. In order to not have to call the function-creator multiple times, the resulting function has to be stored as a global variable (so it is available next time), so we may just as well have stored the colour-code conversion table as a global variable instead.

- Nick Gammon

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

Posted by Shaun Biggs   USA  (644 posts)  Bio
Date Reply #10 on Fri 26 Jun 2009 08:04 AM (UTC)
Message
I did a small series of tests two years ago dealing with repeatedly creating tables, calling if loops, etc. Some of the results can be found here:
http://www.gammon.com.au/forum/?id=7891

At any rate, if you are going to be calling a table repeatedly, it is a good idea to have it in global space rather than in the function.

It is much easier to fight for one's ideals than to live up to them.
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.


38,527 views.

Posting of new messages is disabled at present.

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.