私の端末の退屈さを軽減できますか?


11

最近の端末は退屈です。以前は次のようでした。

ターミナル1 ターミナル2

今、彼らはただ当たり障りのない鈍い、白黒です。私の端末を再びカラフルにするプログラムを書いてほしい!

説明

このRubyコードの例をご覧ください。

サンプルコード

ほとんどのLinux端末はこれらのエスケープシーケンス(\eエスケープ文字の略)をサポートし、WindowsはANSICONでこれらをサポートできます。文字列のテキストまたは背景色を変更できる特定のエスケープシーケンスの構文は次のとおりです。

\e[{{COLOR}}m

ここ\eで、エスケープ文字(0x1BASCII)を表し、{{COLOR}}使用する色の番号に置き換えられます(これについては後で詳しく説明します)。このエスケープシーケンスの後に来るテキストは指示どおりにフォーマットされ、値が0すべてのフォーマットをリセットします。

あなたの課題は、色を含む可能性のあるテキストを指定する文字列を取得し、そのカラフルなバージョンを出力することです。

入出力

通常のテキストは通常​​と同様に機能し、文字通り印刷されます。たとえば、入力wafflesは同じ出力を生成し、特別な色はありません。

色を指定するための構文は、Wikipediaの構文に似ています。たとえば、文の赤の単語「the color red」に色を付けるには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}}

仕様

2つの開いた中括弧は、常にカラーディレクティブの始まりを指定します。2つの閉じ中括弧で終了を指定します。ブラケットは常に一致します。{{対応することなくa が決してなく、対応する前に}}a }}が決して来ないでしょう{{。これらのカラーディレクティブはネストされず、a {{はカラーディレクティブ内に表示されません。

カラーディレクティブ内には、常に1つまたは2つの|シンボルがあります。ある場合、前のテキストは前景色であり、後のテキストはその色で表示する文字列です。2つある場合、最初のテキストの前のテキストが前景色であり、最初のテキストの後2番目のテキストが背景色であり、2番目の後のテキストが表示する文字列です。これらの垂直バーは、カラーディレクティブの外側に存在する場合があり、文字どおりに印刷する必要があります。

前景色または背景色(両方ではない)が空の場合があります。その場合は、デフォルトのままにしておく必要があります。最終的な文字列(出力する文字列)が空になることはありません。

特定の色のテキストを出力する方法は次のとおりです。

  • 色配列は、「説明」セクションで定義されています。たとえば、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
    
  • 色名では大文字と小文字が区別され、無効な色名が指定されることはありません。あなたは、のようなものを扱う必要はありませんREDかlightgrey(と綴らe)。

  • カラーシーケンスを印刷すると、それに続くすべてのテキストに適用されます。色シーケンスを終了するには(デフォルトの色にリセット)、色シーケンス0("\e[0m")を出力します。

テストケース

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

これは、悪の赤い目をしたスマイリーフェイスを出力するはずです。

ルール

  • プログラミング言語のライブラリまたは関数を使用して、色を自動的に解析することはできません。これは、あなたが何を"red"意味するかを決定するためにあなたでなければならないことを意味します。ライブラリが自動的にそれを行うことはできません。

  • これはなので、バイト単位の最短コードが勝ちます!


それは実際に端末になるはずですか?それとも、カラフルなテキストビューアですか?コマンドを実行することになっていますか?
— ネイサンメリル14

これをテストするのは難しいと思っています。指定した構文を使用してSTDOUTに送信するものはすべてプレーンテキストです。私のbashプロファイルは色付きのプロンプトを使用しているので、私が試したものから盗みます\n\[\e[32m\]\w\n\[\e[0m\]> (緑色のディレクトリ名、次の行のプレーンプロンプト)が、プログラムから動作させることができません(これまでにPythonとJavaを試しました)。何か案は?
— ジオビット14

@Geobits試してみてくださいecho -e "\e[31mtest\e[0m"。
— ドアノブ

4
楽しんでいただけると思いますlolcat。
— アンコ14

1
you彼は比your programlibrary的に(ライブラリ関数の呼び出しとは対照的に)をdetermine意味し、のようにでfigure outはなく、という意味で解釈すると思いますchoose。つまり、マッピングを処理するのはプログラムです:String( "red")|-> Integer(31)。redだけで31、彼はそう言うので、その情報がプログラムに統合する必要があります。カウントされるものと正確に議論されるかもしれませんがyour program、汎用の文字列操作関数を使用できますか?-露骨にチート/乱用しないでください。
— blutorange

回答:


6

ルビー、205 189 188 186 185 182 174 170 165 161 159 154バイト

コードに色名の長い文字列を入れても、オタクにはならないようです。

おかげで部分的に170までrubik。スクロールバーはなくなりました!

明らかな改善とそれほど明白ではない改善の1つは、フレックスの答えのおかげで、改善がなければ、これを再訪することはなかっただろう!

もはや、#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]]}

これが1行です。このように使用します

ruby colors.rb -W0 < input.txt

この-W0フラグは、stderrそうでなければ送信される警告を抑制します。ただし、プログラムはフラグなしで正常に動作します。

出力:

出力


1
ああ、私は同じ考えを持っていたが、あなたはそれに私を打ち負かした!base 35、modulus 98、およびxor 1のcharを保存できると思います'1?IYU_N[(\x0c\x16&",\x1f\x01'。文字列は次のようになります。私の文字列の長さは16です。私はあなたが18歳だと思うので、おそらく調整する必要があります。
— ルビック14

ありがとう。追加の2バイトは、デフォルトの背景/前景色を設定するカラーコード39/49をサポートするためにあります。しかし、先端のおかげで、私は現在仕事をしているので、家に帰ってからもう少し考えてみます。
— ブルトレンジ14

1
使用できるベースは35と36だけです(少なくともPythonのint()機能は36を超えることはできません)。次に、モジュラス(2から10000ですが、理論的にはすべてのUnicodeに検索範囲を広げることができます)とxorのすべての組み合わせ(1から9)を試しました。次に、重複する文字を含まない結果のみを許容可能な結果と見なしました。
— ルービック

はい、それは多かれ少なかれ私もやったことです。もともと、私は自分自身を印刷可能なキャラクターに限定していました。それは、頭痛が少なくなり、見栄えが良くなるからです。しかし、私はすでにエスケープシーケンスの代わりにバイト0x1eを使用しているため、より多くの非印刷文字を使用することもできます。印刷可能な文字を実現するために、を使用しましたx.to_i(base)%mod+offset。私はその後、交換し+て^も、それはクーラーが見えるので、。それ以外は、不要です。をドロップして^99、より多くのバイト<<を+保存するように変更します。ヒントをありがとう、そうでなければ気付かなかったでしょう!
— blutorange

4

ルビー、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) 。
— レイ14

こんにちは@ Ray、2.0.0-p451で動作します。2.1.2では試しませんでした。 ここでは、スクリプトとして動作し、ここではIRBで動作します。
— アレックスデヴァ14

テキストを手動で入力するときに機能します。実行するとruby colors.rb < input.txt、すべての入力が読み取られた後もループを続けます。次に、メソッドを持たないをgets返すため、エラーが発生します。の代わりに使用し、それも短くなります。)nil#gsub$><<$<.readloop{puts gets
— blutorange 14

このスクリプトをスマイリーフェイスでテストしました(質問と私の投稿の画像を参照)。スマイリーの周りに黄色い境界線はありませんか?
— blutorange

4

フレックス(レクサー) - 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

パイソン-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

パイソン、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 Nonecodegolfに入れるのは冗長すぎます。!=Noneたとえば、使用できます。
— レイ14

また、ではdef p(f,b,t)、コードはをスローしZeroDivisionErrorます。mod 0は何も不可能です。
— ベータ崩壊14

@BetaDecayは、モジュレートされている整数ではなく、フォーマットされている文字列です。
— サミッチ14

私はで無効な構文エラーを取得していますre.sub。この実行している
— ArtOfCode

(後期コメント)この499バイトのコードは機能しますか?
— エリックアウトゴルファー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.