サポンテ 勉強ノート

サポンテの勉強ノート・読書メモなどを晒します。

ティーン向けファッション誌の主題は『憧れ』

はじめに

 以下のニュースがありました。

やせて色白のモデルに傷つき…ティーン向けファッション誌は「ありのままで美しいと発信を」元愛読者らがネット署名:東京新聞 TOKYO Web

 見た目に優劣はなく、ありのままで美しいと発信することを求めます! 10代前半の女子に人気のファッション誌に宛てて、こんなメッセージを送ろうという署名運動がインターネット上で広がっている。

 確かに「色白痩身」が過度に偏重されている風潮はあり、そのこと自体はサポンテも問題であると考えます。

 しかしながら、いささかツッコミどころもあるように感じられます。

続きを読む

AppleScript の do shell script で実行されるシェル環境を調べる

 昨日のスクリプトを作っているときに気になったので。

 スクリプトエディタ.app で以下の AppleScript を実行します。

-- 使われているシェルとそのバージョン取得
set shName to do shell script "echo $SHELL"
log (do shell script shName & " --version")

-- 環境変数の取得
log (do shell script "set")

-- AppleScript のバージョン取得
log ("AppleScript version: " & version of AppleScript)

-- macOS のバージョン取得
log (do shell script "sw_vers")

Spotlight を利用して素早く新規ファイル作成【macOS】【AppleScript】

はじめに

 「Finder で『この場所に新しいテキストファイル』を作成したい」際に、クリックひとつでテキストファイルが作成できるよう、かつて AppleScript で作成したアプリケーションを、Finder ウィンドウのツールバーに登録していました。メモファイルをたくさん作るためです。

 しかし最近は、同じように .md ファイル(Markdown ファイル)を素早く作りたいケースが増えてきました。でもツールバーのボタンを、むやみに増やしたくありません。

 ツールバーのアプリケーションアイコンをクリックした際に、新規作成したファイルの候補を選択するような UI を最初に考えたのですが、それよりは Spotlight で「new_text」とか「new_md」とか、いやいっそ「nt」とか「nm」とかタイプするだけでテキストファイルや .md ファイルが作成できるようにしたい。

続きを読む

Mac の日本語 IME のユーザ辞書内容を Google 日本語入力の辞書へ移行するスクリプト

はじめに

 Mac(Catalina)の日本語 IME があんまりにもひどいので1Google 日本語入力を試してみることにしました。

 しかしインストールしてもユーザ辞書を自動的にインポートしてくれたりはしませんでした。ChromeSafari のブックマークをインポートするかどうか選べるのに。


  1. 学習しない。正確に言うと、学習内容がしばらくするとなぜか消される。ことえりより明らかに悪化しています。
続きを読む

肉の臭み・肉の味

はじめに

 少し前に「肉の臭み」について自分にはわからないという投稿がありました。

肉の臭みって何?

 これについて、サポンテの知ることを書きます。

続きを読む

PC スタンド - ペットボトルを倒したときに PC が濡れるのを防ぐ

はじめに

 社内会議の「ここ1ヶ月ほどで起きたインシデント」という話題の中で「貸与されたノート PC に飲み物をこぼしてしまった」というものがありました。

 サポンテも飲み物は常に手元に置いておくので、他人事ではありません。

PC スタンドがあればいいのではないか

 近年、ノート PC を少し高い位置にする「PC スタンド」なるものがたくさん商品化されています。かつては外付けキーボードにこだわるマニアックな人だけが買いそうなものであったのに、すっかりコモディティ化しています。ちょっと多すぎて若干意味がわかりません。

 まあしかしこれがあれば、ペットボトルを倒したとしても PC 本体にかかる可能性はかなり少なくなるのではないでしょうか。

続きを読む

TSV(Excel または他の表計算ソフト)から xUnit のテスト引数(InlineData)に変換するコードジェネレータ【C#】

はじめに

 xUnit で [Theory] を指定するテストメソッドでは [InlineData()] を使用して、複数のテストケースを記述できます。

 ですが引数が多くなってくると面倒で、楽をしたくなります。

 いつものごとく、コードジェネレータを作成します。

コードジェネレータ

 左の入力欄に、サンプルのように TSV 文字列をコピペして、convert ボタンをクリックしてください。右の入力欄に、生成した C# のコードが出力されます。

 サンプル文字列が既に入力されているので、convert ボタンをクリックするだけで動作を確認できます。

生成されるコード例

 以下のようなコードが出力されます。

[Theory()]
[InlineData(1, "Apple", 200)]
[InlineData(2, "Banana", 150)]
[InlineData(3, "Citrus", 300)]
public void TestMethod(int Id, string Name, int Price)

オプション

 オプションが二つあり、チェックボックスで有効/無効を切り替えます。

Use CamelCase

 チェックすると、メソッドの引数部分の識別子をキャメルケースにします。

Use String

 チェックすると、全ての引数を文字列としてコードを生成します。

ソースコード

 念のため、ソースコードも載っけておきます。JSFiddle がサービス終了しちゃうかもしれませんからね。

 それに、オフラインで使いたいという要件もあるかもしれません(その場合、CDN のところは修正してください)。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TSV (from Excel or other) to xUnit InlineData Definition</title>
    <style>
        .outer {
            display: flex;
            justify-content: center;
            align-items: center;
        }
        #app {
            margin: 0 auto;
            display: inline-block;
            text-align: left;
            height: 95%;
        }
        textarea {
            font-family: monospace;
        }
        @media (prefers-color-scheme: dark) {
            body {
                background-color: #333;
                color: #fff;
            }
            textarea {
                background-color: #444;
                color: #fff;
            }
        }
    </style>
</head>
<body>
    <div class="outer">
        <div id="app">
            <table>
                <tr>
                    <td rowspan="3">
                        <textarea name="" id="src" cols="30" rows="10" v-model="src" placeholder="Excel などからコピペしてください"></textarea>
                    </td>
                    <td></td>
                    <td rowspan="3">
                        <textarea name="" id="result" cols="30" rows="10" v-model="result"></textarea>
                    </td>
                </tr>
                <tr>
                    <td>
                        <input type="checkbox" id="useCamelCase" v-model="useCamelCase" />
                        <label for="useCamenCase">Use CamelCase</label>
                        <br />
                        <input type="checkbox" id="useString" v-model="useString" />
                        <label for="useString">Use String</label>
                        <br />
                    </td>
                </tr>
                <tr>
                    <td>
                        <button v-on:click="convert">convert</button><br />
                        <button v-on:click="copyResult">copy</button>
                    </td>
                </tr>
            </table>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                src: "Id\tName\tPrice\n1\tApple\t200\n2\tBanana\t150\n3\tCitrus\t300",
                result: "",
                ln: "grid",
                useCamelCase: true,
                useString: false,
            },
            methods: {
                convert: function (e) {
                    let ret = '';
                    let lines = this.getLines();
                    const useCC = this.useCamelCase;
                    const useStr = this.useString;

                    // create header
                    ret = "[Theory()]\n";
                    lines.forEach((line, row) => {
                        if (row === 0) {return;}
                        var csv = [];
                        line.forEach((col, idx) => {
                            if (useStr || isNaN(col)) {
                                csv.push('"' + col + '"');
                            } else {
                                csv.push(col);
                            }
                            
                        });
                        ret += "[InlineData(" + csv.join(', ') + ")]\n";
                    });

                    // create types
                    let types = [];
                    const isInt = function (src) {
                        const n = Number.parseFloat(src);
                        return Number(n) === n && n % 1 === 0;
                    };
                    lines[1].forEach((col, idx) => {
                        if (!this.useString && !isNaN(col)) {
                            if (isInt(col)) {
                                types.push('int');
                            } else {
                                types.push('double');
                            }
                        } else {
                            types.push('string');
                        }
                    });

                    // create method 
                    ret += 'public void TestMethod(';
                    var params = [];
                    lines[0].forEach((col, idx) => {
                        if (useCC) {col = this.camelCase(col);}
                        params.push(types[idx] + ' ' + col);
                    });
                    ret += params.join(', ');
                    ret += ")\n";
                    this.result = ret;
                },
                getLines: function () {
                    var linesSrc = this.src.split("\n");
                    var lines = [];
                    linesSrc.forEach(line => {
                        if (line.trim() ==='') {return;}
                        lines.push(line.trim().split("\t"));
                    });
                    return lines;
                },
                camelCase: function (str){
                    // http://webdesign-dackel.com/2015/05/15/js-change-case/
                    str = String(str);
                    str = str.charAt(0).toLowerCase() + str.slice(1);
                    return str.replace(/[-_](.)/g, function(match, group1) {
                        return String(group1).toUpperCase();
                    });
                },
                copyResult: function () {
                    navigator.clipboard
                        .writeText(this.result)
                        .then(() => {
                            console.log('copied!')
                        })
                        .catch(e => {
                            console.error(e)
                        });
                }
            }
        });
    </script>
</body>
</html>

最後に

 2021-11-30 バグ修正。

 なんか Edge だとコピーができない。