你能使我的终端少些无聊吗?


11

如今,终端是如此无聊。他们以前看起来像这样:

1号航站楼 2号航站楼

现在它们只是平淡无奇,黑白相间。我想让您编写一个程序,使我的终端再次丰富多彩!

描述

请看以下示例Ruby代码:

范例程式码

大多数Linux终端都支持这些转义序列\e代表转义字符),而Windows可以通过ANSICON支持它们。这是可以更改字符串的文本或背景颜色的特定转义序列的语法:

\e[{{COLOR}}m

其中\e代表转义字符(0x1B以ASCII表示),{{COLOR}}并由您要使用的颜色编号代替(稍后会有更多详细信息)。在此转义序列之后的文本将按照指示进行格式设置,值0将会重置所有格式。

您的挑战是采用一个字符串来指定一些可能包含颜色的文本,并输出彩色版本。

输入输出

普通文本的工作原理与普通文本相同,并且按字面意义打印。例如,输入waffles产生相同的输出,没有特殊的颜色。

指定颜色的语法类似于Wikipedia的语法。例如,要将句子中的“红色”这个词涂成红色This is the color red!,输入将是:

This is {{red|the color red}}!

背景色也可以。如果要在白色背景上使用黑色字母,则可以使用以下命令:

{{black|white|This text is black on white}}

要仅获得背景色,请忽略前景:

{{|red|This text has a red background}}

规格

两个大括号始终指定color伪指令的开头。两个右花括号指定结尾。括号将始终匹配;永远不会有一个{{没有相应的}},和}}其相应的前永远不会到来{{。这些颜色指令不会嵌套,并且a {{永远不会出现在颜色指令内。

在color指令中,将始终有一个或两个|符号。如果有一个,则其前的文本是前景色,而后的文本是该颜色下显示的字符串。如果有两个,则第一个之前的文本是前景色,第一个之后但第二个之前的文本是背景色,第二个之后的文本是要显示的字符串。这些垂直条可能位于color指令之外,应按字面意义进行打印。

前景色或背景色(但不是全部)可能为空,在这种情况下,应将其保留为默认值。最后的字符串(要输出的字符串)永远不会为空。

以下是输出某种颜色的文本的说明:

  • 颜色序列被“描述”一节中所定义。例如,颜色序列为42 "\e[42m"

  • 要设置颜色,请打印以下确定的数字的颜色顺序:

     Color name   | Color sequence number (foreground / background)
    --------------+----------
     black        | 30 / 40
     red          | 31 / 41
     green        | 32 / 42
     yellow       | 33 / 43
     blue         | 34 / 44
     magenta      | 35 / 45
     cyan         | 36 / 46
     lightgray    | 37 / 47
     darkgray     | 90 / 100
     lightred     | 91 / 101
     lightgreen   | 92 / 102
     lightyellow  | 93 / 103
     lightblue    | 94 / 104
     lightmagenta | 95 / 105
     lightcyan    | 96 / 106
     white        | 97 / 107
    
  • 颜色名称区分大小写,并且永远不会提供无效的颜色名称。您无需处理诸如REDlightgrey(用拼写e)之类的东西。

  • 打印颜色序列后,它将应用于其后的所有文本。要结束颜色序列(重置为默认颜色),请输出0"\e[0m")颜色序列。

测试用例

 {{|yellow|     }}
{{|yellow| }}     {{|yellow| }}
{{|yellow| }} {{red|'}} {{red|'}} {{|yellow| }}
{{|yellow| }} \_/ {{|yellow| }}
{{|yellow| }}     {{|yellow| }}
 {{|yellow|     }}

这应该会输出一张笑脸...邪恶的红眼睛。

规则

  • 您不得使用任何编程语言的库或函数来自动解析颜色。这意味着必须是确定"red"含义的人。您无法让图书馆自动为您做到这一点。

  • 这是,因此最短的代码(以字节为单位)将获胜!


实际上应该是终点站吗?还是只是彩色的文本查看器?它应该运行命令吗?
弥敦道·美林

我发现很难对此进行测试。我使用指定语法发送给STDOUT的所有内容均为纯文本格式。我的bash配置文件使用了彩色提示,因此从我尝试的内容中进行了窃取\n\[\e[32m\]\w\n\[\e[0m\]> (绿色目录名称,下一行为普通提示),但是我无法从程序中使用它(到目前为止尝试过python和Java)。有任何想法吗?
Geobits

@Geobits试试echo -e "\e[31mtest\e[0m"
门把手

4
我想你会喜欢的lolcat
Anko 2014年

1
我认为you他是用比喻的方式your program(而不是调用库函数),并且他determine的意思是figure out,而不是choose。即,应该由您的程序处理映射:String(“ red”)|-> Integer(31)。red只是31因为他这么说,所以信息需要集成到程序中。尽管可能会争论到底是什么your program-我们可以使用通用的String操纵函数吗?-不要公然作弊/滥用。
blutorange 2014年

Answers:


6

红宝石,205 189 188 186 185 182 174 170 165 161 159 154字节

将长长的颜色名称字符串放在您的代码中看起来还不够讨厌。

下降到170部分归功于rubik。现在滚动条不见了!

多亏了flex的回答,一个明显的改进和不那么明显的改进,如果没有改进,我将不会再讨论这一点!

不再了,我用#sum保存了4个字节。我没有打算,但我只是注意到此解决方案也不区分大小写。它快乐地处理{{RED|Red text}}

十六进制转储:

0000000: 7a3d 2d3e 6a7b 693d 2240 3054 2d44 1547  z=->j{i="@0T-D.G
0000010: 5155 0034 3256 2f46 1749 0b22 2e69 6e64  QU.42V/F.I.".ind
0000020: 6578 2028 415b 6a5d 2e74 6f5f 732e 7375  ex (A[j].to_s.su
0000030: 6d25 3839 292e 6368 723b 692b 3d69 3e39  m%89).chr;i+=i>9
0000040: 3f38 303a 3330 7d0a 243e 3c3c 243c 2e72  ?80:30}.$><<$<.r
0000050: 6561 642e 6773 7562 282f 7b7b 282e 2a3f  ead.gsub(/{{(.*?
0000060: 297d 7d2f 297b 413d 2431 2e73 706c 6974  )}}/){A=$1.split
0000070: 277c 273b 221b 5b25 693b 2569 6d23 7b41  '|';".[%i;%im#{A
0000080: 2e70 6f70 7d1b 5b30 6d22 255b 7a5b 305d  .pop}.[0m"%[z[0]
0000090: 2c31 302b 7a5b 315d 5d7d                 ,10+z[1]]}

您可以使用进行转换xxd -r hex.dump

程序中转义了所有不可打印的字符,以供参考:

z=->j{i="@0T-D\x15GQU\x0042V/F\x17I\v".index (A[j].to_s.sum%89).chr;i+=i>9?80:30}
$><<$<.read.gsub(/{{(.*?)}}/){A=$1.split'|';"\x1b[%i;%im#{A.pop}\x1b[0m"%[z[0],10+z[1]]}

那是一行。这样使用

ruby colors.rb -W0 < input.txt

-W0标志禁止将警告发送给stderr其他情况。但是,该程序运行正常,没有任何标志。

输出:

输出


1
啊,我有同样的想法,但是你击败了我!我认为您可以使用基数35,模数98和xor 1保存一个字符。字符串为:'1?IYU_N[(\x0c\x16&",\x1f\x01'。我的弦长是16。我看到您的年龄为18岁,因此您可能需要调整。
rubik 2014年

谢谢。那里的两个附加字节支持颜色代码39/49,该颜色代码设置默认的背景色/原色。但是,感谢您给我小费,我目前正在工作,回到家时会多加考虑。
blutorange 2014年

1
我观察到,您只能使用35和36(至少Python的int()函数不能超过36)。然后,我尝试了模数的所有组合(从2到10000,但是从理论上讲,可以将搜索范围扩大到所有 Unicode)和xor(我将其保持很小(1到9))。然后,我只考虑那些不包含重复字符的可接受结果。
rubik 2014年

是的,那差不多就是我所做的。最初,我仅限于使用可打印的字符,因为这样可以减轻您的麻烦,并且看起来更好。但是由于我已经在使用字节0x1e而不是转义序列了,所以我不妨使用更多不可打印的字符。为了实现可打印的字符,我使用了x.to_i(base)%mod+offset。然后我更换了+^,因为很好,它看起来更酷。除此之外,它是不必要的。删除,^99然后更改<<+保存以获得更多字节。谢谢你的提示,否则我不会注意到的!
blutorange 2014年

4

Ruby,329个字节。

h={};(y=0..15).each{|i|h[%w(black red green yellow blue magenta cyan lightgray darkgray lightred lightgreen lightyellow lightblue lightmagenta lightcyan white)[i]]=y.map{|j|[30,40].map{|k|k+i%8+i/8*60}}[i]}
loop{puts gets.gsub(/{{.+?}}/){|x|"\e[#{h[(g=x.scan(/[^{}|]+/))[0]][0]}m#{(g[2]? "\e[#{h[g[1]][1]}m":'')}#{g.last}\e[0m"}}

我需要运行什么版本的Ruby?我用过ruby 2.1.2p95并抛出错误:undefined method 'gsub' for nil:NilClass (NoMethodError)

嗨,@ Ray,它在2.0.0-p451中有效。我没有在2.1.2中尝试过。 在这里它可以用作脚本在irb中可以使用
2014年

当您手动输入文本时,它起作用。如果这样做ruby colors.rb < input.txt,则在读取所有输入之后,它将继续循环。然后gets返回nil,它不具有#gsub方法,从而引发错误。使用$><<$<.read代替loop{puts gets,它也更短;)
blutorange 2014年

我只是用笑脸测试了此脚本(请参阅问题和我的帖子中的图像),笑脸周围没有黄色边框?
blutorange 2014年

4

FLEX(词法分析器) - 226 197 192 182 168(或166)

要将其降至166,请将更改\33为实际的转义字符。

 int z;p(i){printf("\33[%dm",i);}
%%
"{{" z=2;
[a-z]*\| if(!z)REJECT;~-yyleng&&p("062q00t03058ns7uo0p90r4"[*(int*)&yytext[yyleng>7?4:0]%131%27]-10*z);z--;
"}}" p(z=0);

编译并运行:

$ flex -o colour.c colour.l
$ gcc -o colour colour.c -lfl
$ ./colour < input

3

Python-351

import re,sys
R=range
E=lambda n,d=0:'\033[%dm'%(T[n]+d)if n else''
def P(m):f,b,t=m.groups();return'%s%s%s\033[0m'%(E(f),E(b,10),t)
x='!red!green!yellow!blue!magenta!cyan'.replace
T=dict(zip(('black'+x('!',' ')+' lightgray darkgray'+x('!',' light')+' white').split(),R(30,38)+R(90,98)))
print re.sub(r'{{(\w+)?\|?(\w+)?\|?(.+?)}}',P,sys.stdin.read())

1

眼镜蛇-496

几乎可以是单个打印语句。

use System.Text.RegularExpressions
class P
    def main
        print Regex.replace(Console.readLine,r'\{\{('+(l=List<of String>(((m=' black red green yellow blue magenta cyan'.split).join(' ')+' lightgray darkgray'+m.join(' light')+' white').split))[1:].join('|')+r')?\|?('+l[1:].join('|')+r')?\|(.*?)\}\}',do(a as Match))
            return if(x=l.indexOf('[a.groups[1]]'),r'\e['+'[if(x>8,x+81,x+29)]m','')+if(y=l.indexOf('[a.groups[2]]'),r'\e['+'[if(y>8,y+91,y+39)]m','')+'[a.groups[3]]'+if(x+y,r'\e[0m','')

1

Python,561

从标准输入中读取要格式化的文本。

import re,sys
def p(f,b,t):
    p=''
    m='\033[%dm'
    if f!=0:p+=m%f
    if b!=0:p+=m%b
    return p+t+m%0
def c(n,b=0):
    s='black:30#red:31#green:32#yellow:33#blue:34#magenta:35#cyan:36#lightgray:37#darkgray:90#lightred:91#lightgreen:92#lightyellow:93#lightblue:94#lightmagenta:95#lightcyan:96#white:97'
    r=0
    for i in s.split('#'):
        (t,c)=i.split(':')
        if t==n:
            r=int(c)
            if b==1:r+=10
    return r
def r(m):
    i=m.groups()
    f=b=0
    if i[0]!='':f=c(i[0])
    if i[1]!=None:b=c(i[1],1)
    return p(f,b,i[2])
print re.sub('{{(\w*)\|(?:(\w*)\|)?([^}]+)}}',r,sys.stdin.read())

2
is not None在代码高尔夫球中太冗长了。!=None例如,您可以使用。

另外,在中def p(f,b,t),您的代码将抛出ZeroDivisionError。mod 0不可能是任何东西。
Beta Decay

@BetaDecay不是模量化的整数,而是要格式化的字符串。
Sammitch 2014年

我在re.sub运行此
脚本时

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.