htsign's blog

ノンジャンルで書くつもりだけど技術系が多いんじゃないかと思います

Linux版Steam の Portal 2 を日本語環境でプレイする

Pop!_OS 20.10 にて。
日本語でプレイしようとしたら文字が全く表示されない現象に出くわしたため、その解決手順をメモ。

1. fontconfig 用の設定ファイルを作成します。

$ mkdir -p ~/.config/fontconfig
$ vim ~/.config/fontconfig/portal2.conf

2. なんか書きます。

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <match target="pattern">
        <test name="family" qual="any">
            <string>Helvetica</string>
        </test>
        <edit name="family" mode="assign" binding="same">
            <string>Noto Sans CJK JP</string> <!-- ここはお好みで -->
            <string>sans-serif</string>
        </edit>
    </match>
    <dir>/usr/share/fonts</dir>
</fontconfig>

3. Portal 2 の起動オプションに作ったファイルを紐付けます。

FONTCONFIG_FILE=~/.config/fontconfig/portal2.conf %command%

f:id:htsign:20201231050756p:plain

いろいろやったけれども ~/.config/fontconfig/fonts.conf に書く、という方法では上手く動きませんでした。
とりあえず上の手順で表示はされるようになるけれども、 Noto Sans は Helvetica と書体が異なるので、スッキリしない人は似た書体のフォントを探してシステムにインストールし適用すればよいかと思います。

参考:

ノートPCをポチりました

12月からフルリモートとなることが決まりました。
自宅ではどうせ集中できないだろうと思うので、出先で仕事ができるようにとノートPCを買うことにしました。

なので、昨日1は外でも使える *nix がプリインされてるノートPCを物色していたわけです。

初めは Chromebook も有力な選択肢としていました。最近は Linux としても普通に使えるらしいですからね。
が、こいつはOSの特性上メモリがっつり積んでいるモデルが無かったため除外することにしました。

次、 Macbook Pro は性能的には問題ないものの、正直言って Apple は嫌いだし2Macbook Air (2015) 持ってるからいいや、となりました。
触ってて面白くないしね。

となると初めから Linux ディストリビューションが入ったノートが選択肢として上がります。
別にハイエンドな Windows ノートでもいいんですが、 Linux として運用すると考えている以上は Windows のライセンス分無駄なお金を払うことになるし、最初から Linux が入っているって、なんか良くないですか。

で、探してみるんですが、やっぱりまだ世間一般的にはあまりメジャーではないため種類が限られるんですよね。
ないわけではないんですが、少なくとも次の仕事では Docker インスタンスをもりもり立てることが分かっているのでメモリには余裕を持っておきたい。別途 SO-DIMM を購入するのもありだったのかもしれませんが、このときは意識の外でした。

ハイエンドの Linux プリインノートに絞って調べていたら米国コロラド州にある System76 という会社の Lemur Pro というノートを紹介しているブログ記事が目に入りました。
なるほど、これはいい!と記事にあるリンク先に飛んでみたのですが、どうやら Lemur Pro はちょうどCPUの世代交代が近いからなのか買えない様子。
仕方ないから他のを探すか…となったのですが、やっぱり数が少なくてなかなか琴線に触れるのがないんですよね。

立ち戻って System76 のサイトを見返してみると、考えてみたら当然なのですが、ラインナップは Lemur Pro だけではないんですよね。
ラップトップに限っても結構種類があるようです。上から順に見ていったのですが、どれもこれもスペックは十分。
特に WS3 の名を冠するコンピューティングガチ勢もにっこりの3機種はヤベーです。デスクトップ用CPU積んでたりしますし。

私としては、ビルドも走らせるのである程度CPUも強いと嬉しいのですが、一番の重視ポイントはメモリであることを鑑み、性能とコストのバランスから Gazelle を選択しました。

f:id:htsign:20201104001931p:plain

このスペックで18万円弱(送料込み)です。割とお買い得かなと思います。
日本への発送にも対応していますが、無論海外からの通販であるのでハードウェア故障等のサポートが必要な場面ではちょっと面倒になるというリスクはあります。
ただ、情報によるとユーザーによるカスタマイズがしやすいよう、ガワは簡単に開けられるような作りのようです。パーツもある程度は自分で交換できる模様。

Pop!_OS は Ubuntu系列の派生ディストリビューションだそうです。
デスクトップのベースは GNOME とのことで、開発者向けに使いやすいようチューンしてあるんだそうな。

ゲフォ積んでありますが、たぶんあまりゲームには使わないと思います。家にいると集中できない理由の一つがゲームだし、だったら家で仕事しても一緒でしょってなって、ノートの意味とは…みたいな感じになるので。

まだ Placed 状態で組み立てに入っておらず、しばらくは待つ感じになりますが期待しています。


  1. もう日付が変わってしまったので…。

  2. ちなみに Google も割と嫌いです。

  3. WorkStation の略と思われます。

Wandbox のエディタ設定を言語ごとに保存して自動で切り替えする UserScript

表題の通り。
Wandbox さん非常に便利なんですが、言語を切り替えてもエディタ設定は切り替わらないんですよね。

例えば F# はタブ文字をインデントに使えませんが、Go はタブ文字でのインデントを推奨しています。
これら言語を切り替えるときに設定も都度触るのが非常に億劫だと常々思っていました。

というわけで、そのちょっとした不満を解消するために書きました。
設計は「まぁ Proxy 使えば未定義のプロパティも初期化できるやろ」くらいのかなり適当なノリでやってしまったので、メンテが非常につらい感じになっています。
変数の命名も適当です。適当に書いてたら名前が被りそうだったので、普段はオブジェクトをバインドした定数に UPPER_SNAKE_CASE は使わないんですが、他に考えるのも面倒だったので苦し紛れに使っています。

gist.github.com

InoReader 向けに、はてブ integration を追加する UserScript

こんな感じになります。

f:id:htsign:20200511130635p:plain

「動けばいい」をモットーにクソ雑実装。
暇すぎて他にすることなくなったらリファクタリングする可能性が微粒子レベルで存在します。

gist.github.com

Vim script で flatmap

しょーもない話ですが最近になって Vim script を書き始めたので。

全く知らなかったのですが、 Vim 7.0 あたりから map 関数や filter 関数が実装されていた模様。
また、 Vim 8.0 からはラムダ式が、 8.2 からは UFCS っぽいもの1が導入されたそうです。

mapfilter があるなら flatmap もあっていいだろうと。
※ なお、 map filter は新しくリストや辞書を作るのではなく、与えられたオブジェクトそのものを変化させるので、他の言語のノリで使うとハマります。 copy を予め使うといい感じです。2

さて、実装はこんな感じです。

function! FlatMap(obj, body) abort
    let l:privates = {}
    function l:privates.for_list() abort closure
        let l:new_list = []
        for l:x in a:obj
            let l:new_list += a:body(l:x)
        endfor
        return l:new_list
    endfunction
    function l:privates.for_dict() abort closure
        let l:new_dict = {}
        for l:item in values(a:obj)
            for [l:key, l:val] in items(l:item)
                let l:new_dict[l:key] = a:body(l:val)
            endfor
        endfor
        return l:new_dict
    endfunction

    return get({
        \ v:t_list: l:privates.for_list,
        \ v:t_dict: l:privates.for_dict,
    \ }, type(a:obj), { -> v:null })()
endfunction

これで…

" [1, 1, 2, 2, 3, 3]
echo [1, 2, 3]->FlatMap({ x -> [x, x] })

" [1, 2, 3, 2, 4, 6, 3, 6, 9]
echo [
    \ { 'inner': [1, 2, 3] },
    \ { 'inner': [2, 4, 6] },
    \ { 'inner': [3, 6, 9] },
\ ]->FlatMap({ x -> x.inner })

" {'1': '(10)', '2', '(20)', 'bbb': '(BBB)', 'aaa': '(AAA)'}
echo { 'a': { 'aaa': 'AAA', 'bbb': 'BBB' }, '1': { '1': 10, '2': 20 } }
    \ ->FlatMap({ x -> printf('(%s)', x) })

" v:null
echo (100)->FlatMap({ x -> [x, x] })

てな感じで、ほぼほぼ想定通りに動きました。

mapfilter が辞書を引数に取り得るので、今回はそれに倣い辞書の場合も想定してみました。
ただし、特にメリットが分からないので map filter とは違い新たにオブジェクトを作り直しています。

ローカルスコープの関数を定義することができないので、ローカルレベルで辞書を作成して中身に関数を定義することで疑似的にローカル関数を定義するハックを利用しています。


  1. Unified Function Call Syntax の略。 func(arg1, arg2, arg3)arg1->func(arg2, arg3) のように、関数の第一引数のメソッドであるかのように関数呼び出しを書けます。これによってメソッドチェーンの如く数珠繋ぎにフローを書くことができ、可読性が高まります。 Dlang での名称。 Wikipedia(en) には記事がありますが、その他の言語では UFCS が正式な名称ではなさそうなので「っぽいもの」としました。

  2. このことは Vim のマニュアルにも書かれています