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
➜ ANSI to Style Table
It is now over 60 days since the last post. This thread is closed.
Refresh page
| Posted by
| Falanyx
(4 posts) Bio
|
| Date
| Wed 06 Jan 2016 04:12 AM (UTC) |
| Message
| Hello,
I'm currently receiving a string over Telnet subnegotiation that includes ANSI colour codes. While I doubt it the more I look, I was wondering if there was any way to take such a string and convert it to a style table (as received by Lua functions as arg#4 when called by a trigger).
Thank you,
Falanyx. | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #1 on Wed 06 Jan 2016 04:53 AM (UTC) |
| Message
| | Can you give an example of such a string? Anything is possible, that doesn't sound too hard. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Falanyx
(4 posts) Bio
|
| Date
| Reply #2 on Wed 06 Jan 2016 07:42 AM (UTC) |
| Message
| Here's an example string (which is surrounded by a reasonable amount of JSON in reality):
"\u001b[0;1;33mYou tell Drunken Master Kalas Malarious, Kitten Avenger, \"// Test string.\"\u001b[0;37m"
I've given a bit more thought on how to do it, and I know it's possible to Simulate the string and use a trigger, but I'm trying to avoid the use of a trigger altogether (in what is, frankly, probably a misguided attempt to be lazy or clever depending on point of view). | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #3 on Wed 06 Jan 2016 10:15 AM (UTC) |
| Message
| |
| Posted by
| Falanyx
(4 posts) Bio
|
| Date
| Reply #4 on Wed 06 Jan 2016 04:03 PM (UTC) |
| Message
| | I probably should have been about 20 times more clear with what I was trying to do, so my apologies for that. I'm actually needing the style table for insertion into a chat miniwindow (based off the one posted here back in 2010/2011 by... I think it was Fiendish, but I could be 100% wrong). | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #5 on Wed 06 Jan 2016 08:40 PM (UTC) Amended on Thu 07 Jan 2016 08:59 PM (UTC) by Nick Gammon
|
| Message
| You can use regexps to break up the string into ANSI sequences, along these lines:
test = "\027[0;1;33mYou tell foo, \"// Test string.\"\027[0;37mbar"
for sequence, text in string.gmatch (test, "\027%[([0-9;]+)m([^\027]+)") do
for ansi in string.gmatch (sequence, "%d+") do
print ("ANSI code: ", ansi)
end -- for
print ("Text: ", text)
end -- for
Output:
ANSI code: 0
ANSI code: 1
ANSI code: 33
Text: You tell foo, "// Test string."
ANSI code: 0
ANSI code: 37
Text: bar
I seem to recall doing this a while back but don't remember where.
You can now take those sequences and do something meaningful with them, to apply to those parts of text.
From the MUSHclient source, these are what the codes do:
// ANSI Colour Codes
#define ANSI_RESET 0
#define ANSI_BOLD 1
#define ANSI_BLINK 3
#define ANSI_UNDERLINE 4
#define ANSI_SLOW_BLINK 5
#define ANSI_FAST_BLINK 6
#define ANSI_INVERSE 7
#define ANSI_CANCEL_BOLD 22
#define ANSI_CANCEL_BLINK 23
#define ANSI_CANCEL_UNDERLINE 24
#define ANSI_CANCEL_SLOW_BLINK 25
#define ANSI_CANCEL_INVERSE 27
#define ANSI_TEXT_BLACK 30
#define ANSI_TEXT_RED 31
#define ANSI_TEXT_GREEN 32
#define ANSI_TEXT_YELLOW 33
#define ANSI_TEXT_BLUE 34
#define ANSI_TEXT_MAGENTA 35
#define ANSI_TEXT_CYAN 36
#define ANSI_TEXT_WHITE 37
#define ANSI_TEXT_256_COLOUR 38
#define ANSI_SET_FOREGROUND_DEFAULT 39
#define ANSI_BACK_BLACK 40
#define ANSI_BACK_RED 41
#define ANSI_BACK_GREEN 42
#define ANSI_BACK_YELLOW 43
#define ANSI_BACK_BLUE 44
#define ANSI_BACK_MAGENTA 45
#define ANSI_BACK_CYAN 46
#define ANSI_BACK_WHITE 47
#define ANSI_BACK_256_COLOUR 48
#define ANSI_SET_BACKGROUND_DEFAULT 49
So in other words, my first test sequence does:
- 0 - reset to standard (ie. not bold, not underline, etc.)
- 1 - set bold text
- 33 - text to yellow (foreground colour)
The second sequence does:
- 0 - reset to standard (ie. not bold, not underline, etc.)
- 37 - text to white (foreground colour)
My first regexp looks for ESC [ <some numbers or ";"> m. Thus it would fail to find the very first words on the line (if any) if they are not preceded by an escape sequence. You could inject a dummy one (eg. ESC[0m ) or handle that as a special case of a style run that does not change colours from the previous one.
This should give you enough information to get started.
[EDIT] Bear in mind the second regexp in my example returns strings. You need to use tonumber on them if you want to compare them directly to numbers. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Fiendish
USA (2,558 posts) Bio
Global Moderator |
| Date
| Reply #6 on Fri 17 Jun 2016 07:28 AM (UTC) Amended on Fri 17 Jun 2016 05:17 PM (UTC) by Fiendish
|
| Message
| I just did something similar.
Not to styles, to Aardwolf color codes, but the process should be basically the same.
Anyway I came up with this:
-- Aardwolf bold colors
local ansi_digit_to_bold_atcode = {
[30] = "@D",
[31] = "@R",
[32] = "@G",
[33] = "@Y",
[34] = "@B",
[35] = "@M",
[36] = "@C",
[37] = "@W"
}
-- Tries to convert ANSI sequences to Aardwolf color codes
function AnsiToColours(ansi, default_foreground_code)
if not default_foreground_code then
default_foreground_code = "@w"
end
local ansi_capture = "\027%[([%d;]+)m"
-- this stuff goes outside because ANSI is a state machine (lolsigh)
local bold = false
local color = ""
local xstage = 0
ansi = ansi:gsub("@","@@"):gsub(ansi_capture, function(a)
for c in a:gmatch("%d+") do
local nc = tonumber(c)
if nc == 38 then
xstage = 1
elseif nc == 5 and xstage == 1 then
xstage = 2
elseif xstage == 2 then -- xterm 256 color
if bold and ansi_digit_to_bold_atcode[nc+30] then
color = ansi_digit_to_bold_atcode[nc+30]
else
color = string.format("@x%03d", nc)
end
xstage = 0
elseif nc == 1 then
bold = true
xstage = 0
elseif nc == 0 then
bold = false
-- not actually sure if we should set color here or not
color = default_foreground_code
elseif nc <= 37 and nc >= 30 then -- regular color
if bold and ansi_digit_to_bold_atcode[nc] then
color = ansi_digit_to_bold_atcode[nc]
else
color = string.format("@x%03d", nc-30)
end
xstage = 0
end
end
return color
end)
return ansi
end
Aardwolf supports 256 xterm colors, so I use those preferentially for anything that isn't explicitly bold. |
https://github.com/fiendish/aardwolfclientpackage | | Top |
|
| Posted by
| Fiendish
USA (2,558 posts) Bio
Global Moderator |
| Date
| Reply #7 on Fri 17 Jun 2016 08:25 AM (UTC) |
| Message
| I then have my own Colors to Styles function written a long time ago.
It relies on having defined a table called atcode_to_color_value which, as the name suggests, translates Aardwolf's color codes into MUSHclient color numbers.
-- Converts text with Aardwolf normal and xterm 256 color codes into MUSHclient style runs
function ColorsToStyles (Text, default_foreground_code, default_background_code)
if not default_foreground_code then
default_foreground_code = "@w"
end
default_foreground = atcode_to_color_value[default_foreground_code]
if not default_background_code then
default_background_code = "@k"
end
default_background = atcode_to_color_value[default_background_code]
if Text:match ("@") then
astyles = {}
-- make sure we start with a color
if Text:sub(1, 1) ~= "@" then
Text = default_foreground_code .. Text
end -- if
Text = Text:gsub ("@%-", "~") -- fix tildes
Text = Text:gsub ("@@", "\0") -- change @@ to 0x00
Text = Text:gsub ("@x([^%d])","%1") -- strip invalid xterm codes (non-number)
Text = Text:gsub ("@x[3-9]%d%d","") -- strip invalid xterm codes (300+)
Text = Text:gsub ("@x2[6-9]%d","") -- strip invalid xterm codes (260+)
Text = Text:gsub ("@x25[6-9]","") -- strip invalid xterm codes (256+)
Text = Text:gsub ("@[^xrgybmcwDRGYBMCWd]", "") -- strip hidden garbage
for color, text in Text:gmatch ("@(%a)([^@]+)") do
text = text:gsub ("%z", "@") -- put any @ characters back
if color == "x" then -- xterm 256 colors
code,text = text:match("(%d%d?%d?)(.*)")
color = color..code
end
if #text > 0 then
table.insert (astyles, { text = text,
bold = (color == color:upper()),
length = #text,
textcolour = atcode_to_color_value[color] or default_foreground,
backcolour = default_background })
end -- if some text
end -- for each color run.
return astyles
end -- if any color codes at all
-- No color codes, create a single style.
return { { text = Text,
length = #Text,
textcolour = default_foreground,
backcolour = default_background } }
end -- function ColorsToStyles
If you want to go from ANSI to Styles, you could chain these two functions together. |
https://github.com/fiendish/aardwolfclientpackage | | 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,023 views.
It is now over 60 days since the last post. This thread is closed.
Refresh page
top