ごんれのラボ

iOS、Android、Adobe系ソフトの自動化スクリプトのことを書き連ねています。

DTPerのスクリプトもくもく会 #2 を開催しました

前説

DTPerのスクリプトもくもく会 #2 を開催しました。

dtpmkmk.connpass.com

参加者は私を含め11名でした。
今回は電子書籍に詳しい方、文字化けに詳しい方が参加されていました。
また、初心者枠を3名に増員し、メンター枠を設けました。

当日の雰囲気

みなさん熱心にもくもくされていて、特に初心者枠の方々は各自やりたいことを自分で決めて進めていらっしゃったので、他の参加者にも良い刺激になったのではないかしら。
少なくとも私は「これはすぐ追い抜かれそうだ…」とワクワクしていました。
CEPに興味を持たれている方もいらっしゃったので、西の御方を召喚する会もやりたいですねー。

Tweetのまとめ

Togetter でまとめました。
togetter.com

今後の予定

次回は9/9(土)に開催します。
参加者、絶賛募集中! dtpmkmk.connpass.com

bootstrap-select のプルダウンの矢印を文字(▼)にする方法

概要

bootstrap-select を使ってて、プルダウン横の矢印が小さすぎるので、自分でサイズを指定したい、できたら font-size 指定したいなーと思ったので、やってみた。

環境

項目名 バージョン
bootstrap-select.js v1.2.2
Chrome v59.0.3071.115

やりかた

CSSをいじるだけ。
dropup は使ってないので、無視しています。

/* デフォルトの矢印を非表示にする */
.bootstrap-select.btn-group .dropdown-toggle .caret {
    display: none;
}
/* プルダウンの右端に▼を挿入する */
.bootstrap-select.btn-group .btn .filter-option:after {
    content: '▼';
    float: right;
    font-size: 20px;
}

before/after

https://jsfiddle.net/c26zc1f3/2/

before
f:id:macneko-ayu:20170727153000p:plain

after
f:id:macneko-ayu:20170727153005p:plain

昔書いたスクリプトを見直すときに留意しておくこと

概要

DTPerのスクリプトもくもく会 #2 で参加者の方にお話しした内容の抜粋版。
これぐらいの気持ちでリファクタリングするのが心理的負担も少なくていいと思う。

本題

  • typoを直す
    • 変数名、メソッド名、コメントのtypoを直す
  • 同じ処理を二度書かない
    • 複数回書いている処理を抽出してメソッドに書き直す
    • プロパティは変数にいれておく
  • コメントを見直す
    • 読み直して意味がわからないものは書き直す
  • メソッドに概要、パラメーター、戻り値などのコメントをつける
  • 処理をシンプルなものに書き直せないか見直す
    • if文、for文のネストを減らす

追加でやるなら

  • 変数名、メソッド名が処理に沿っているか見直す
    • imageなのにtextFrameって命名するのはダメ etc.
  • どのスクリプトでも共通して書いているような処理はincludeで読み込むようにする
    • 自分用のライブラリを作る
  • 頻繁に使わないものを優先して見直す
    • 使わないものは忘れるのも早い

諦めることも必要

rbenv global で ruby のバージョンが切り替えられなくて困った

概要

久しぶりに自宅 Mac の rbenv で ruby のバージョンを切り替える必要があり、

$ rbenv global system

とコマンドを叩いてみたが、rbenv でインストールしたバージョンから変わらなかった。
困った。

環境

Macbook Air Mid 2012
macOS Sierra 10.12.4

結論

/Users/(user_name)/.ruby_version というファイルのせいで、rbenv で選択している ruby のバージョンが更新されていなかった模様。
/Users/(user_name)/.ruby_version の名前を、/Users/(user_name)/.ruby_version.bak に変更して、様子見をすることにした。

試行錯誤

.bashrc を確認

ちゃんと設定されていた。

eval "$(rbenv init -)"

$PATH を確認

いろいろ入ってるけど、/usr/bin より先に /Users/(user_name)/.rbenv/shims が出力されているので、問題ないはず。

$ echo $PATH
/Users/(user_name)/.pyenv/shims:/Users/(user_name)/.rbenv/shims:/Users/(user_name)/.nodebrew/current/bin:/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/eclipse/android/platform-tools:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/share/dotnet:/Library/Frameworks/Mono.framework/Versions/Current/Commands

ruby のパスを確認

あってた。

$ which ruby
/Users/(user_name)/.rbenv/shims/ruby

rbenv を一度アンインストールして、再インストール

アンインストール。

$ brew uninstall rbenv

削除されたことを確認。

$ which rbenv

出力されないので削除成功。
再度、インストール。

$ brew install rbenv

インストールされたことを確認。

$ which rbenv
/usr/local/bin/rbenv
$ rbenv -v
rbenv 1.1.1

インストール成功。

バージョンが切り替えられるようになったか確認したが、症状は改善せず。

新たに v.2.4.1 の ruby をインストール

rbenv install 2.4.1

成功。

rbenv でインストール済みのバージョンを削除

$ rbenv uninstall 2.3.0

削除した結果、

$ rbenv global 2.4.1

ってコマンド叩くと、rbenv から「2.3.0 なんてバージョン見つからない」って怒られるようになったw
ですよねー。
知ってた。

とあるファイルの存在に気づいた

$ rbenv versions
  system
* 2.4.1 (set by /Users/(user_name)/.ruby_version)

.ruby_version is なに?
調べたらこのファイルで ruby の current version を管理している模様。
そして、

/Users/(user_name)/.rbenv/version

というファイルの存在にも気づく。

$ rbenv global (ruby_version)

というコマンドを叩いたときに更新されていたのは、

/Users/(user_name)/.rbenv/version

だった。

更新されていないファイルが悪さしている?

リネームして読み込まれないようにしてみる。

$ mv /Users/(user_name)/.ruby_version /Users/(user_name)/.ruby_version.bak

試してみる。

$ rbenv versions
  system
* 2.4.1 (set by /Users/(user_name)/.ruby_version)
$ rbenv global system
$ rbenv versions
* system
 2.4.1 (set by /Users/(user_name)/.ruby_version)

直った!!!

まとめ

強引に対処してしまったので、これでいいのか自信がないので、「こんなことのある」程度で読んでくださいまし。

DTPerのスクリプトもくもく会 #2 を開催します

申し込みページ

dtpmkmk.connpass.com

前回からの変更点

  • 今回は会場が変わるので、猫社員はおりません
  • メンター枠を新設しました(主催が事前にメンター役を依頼しています)
  • 開催時間を30分早めました

メンターについて

前回の反省点として当日その場でメンターをお願いしてしまったので、引き受けてくれた方の都合を考慮しない形になってしまっていました。
ただ、これから始めようとする人にはメンターは必要だと思いますし、私一人でそれを担うことも難しいので、メンターとして事前にお願いすることにしました。
まあ、事前に言われるか、当日に言われるかの違いしかないじゃないかと言われたらその通りなんですが、ゆくゆくは会替わりでメンター募集するという形にしていきたいと考えています。

最後に

ご参加お待ちしております!

DTPerのスクリプトもくもく会 #1 を開催しました

前説

DTPerのスクリプトもくもく会 #1 を開催しました。

dtpmkmk.connpass.com

参加者は私を含め10名でした。
会を設立した当初は5人も集まればいいと思っていて、身内でわいわいって感じになりそうだなーと考えていたのですが、初めてお会いする方も何名かきてくださって、嬉しかったです。

当日の内容

  • 私からイベントの趣旨を説明した
  • 参加者のみなさんから自己紹介がてら当日やることを発表した
  • 初心者枠の方が気軽に質問できるようにメンター役を決めた
  • 各自集中しつつ、息抜きに雑談しながら時間までもくもくした
  • どこまで進んだか発表していただく予定が、時間が足りずできなかった

Tweetのまとめ

Togetter でまとめました。
togetter.com

個人的に嬉しかったこと

自分が読んで勉強していた書籍に関わった人が参加してくださったことにとても驚き、そして嬉しかったです。
初心者枠で参加された方が、自分なりに調べたり質問したりしてくださったのも、主催してよかったなーと思いました。 なにより参加してくださった方々が一様に楽しそうだったんですよね。
みなさんの笑顔を見て、続けていきたいなーと強く思いました。

反省点

急遽、メンターをお願いすることになってしまったので、メンター役の方がもくもくする時間が短くなってしまいました。
私としては、みんなで教えあいながら理解を深めていけるような場にしたく、メンター役自体はお願いしていきたいので、次回はメンター枠を設けようか検討中です。
教えることで学ぶことってとても多いので、双方にいい影響がでるような進め方をしていきたいです。

お礼

メンター役を買って出てくださった方々、ありがとうございました。
会場を使わせてくれた弊社、および休日にもかかわらず営業しようとしてた弊社猫営業部員にも感謝しております。

今後の予定

隔月ぐらいのペースで開催していきたいと思います。
次回は7月の後半を予定しています。

おまけ

情報交換や資料配布のために、Slackのチームを作りました(作っていただいた)。
connpass のもくもく会グループページに登録のための URL を載せていますので、もくもく会グループ参加ついでに、Slack にも参加していただけると嬉しいです。

InDesignでサムネイル一覧的なものを作るCEP Extensions

概要

昔、記事として JavaScript で書いたものをアップしていたのですが、いろいろ気になってるところがあって、書き直し。
InDesign でサムネイル一覧的な画像一覧を生成するためのもの。
その昔、千点以上ある素材の一覧を毎週出力するという苦行があり、あまりにも辛くて書いたんだっけ。
ついでに CEP Extensions にしてみた。

使い方

  1. サムネイル一覧出力したい画像をフォルダに集めておく
  2. パネルのプルダウンでドキュメントサイズを選択
  3. 横と縦の分割数を入力(初期値は 3 × 3)
  4. 実行ボタンを押す
  5. 選択ダイアログが表示されるので、1 のフォルダを選択
  6. 自動的に InDesign ドキュメントが生成されて、画像とファイル名が配置される
  7. 「処理が完了しました」というアラートが表示されたら、処理完了

実行結果 f:id:macneko-ayu:20170504150227p:plain

Extensions ダウンロード

下記からどうぞ。
ThumbnailList.zxp - Google ドライブ

証明書を信頼するかどうかの確認が出てしまうと思うけど、ご判断はお任せします。

ソースコード

Github にあげた。 github.com

必要そうなところだけ、一部抜粋。

index.html

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/styles.css"/>
<link id="hostStyle" rel="stylesheet" href="css/theme.css"/>
    <title>Create thumbnail list with Indesign.</title>
</head>
<body>
    <p class="base">
        <select name="page-size" id="select-page-size" required>
            <option value="">★ドキュメントサイズを選択してください★</option>
            <option value="A4Portrait">A4タテ</option>
            <option value="A4Landscape">A4ヨコ</option>
            <option value="B4Portrait">B4タテ</option>
            <option value="B4Landscape">B4ヨコ</option>
            <option value="A3Portrait">A3タテ</option>
            <option value="A3Landscape">A3ヨコ</option>
        </select>
    </p>
    <p class="base">
        <span class="label">横の分割数: </span><input type="text" id="horizontal-division" placeholder="3"><br />
        <span class="label">縦の分割数: </span><input type="text" id="vertical-division" placeholder="3">
    </p>
    <p class="base">
        <button id="button">実行</button>
    </p>
<script src="js/libs/CSInterface-4.0.0.js"></script>
<script src="js/libs/jquery-2.0.2.min.js"></script>
<script src="js/themeManager.js"></script>
<script src="js/main.js"></script>
</body>
</html>

main.js

(function () {
    'use strict';
    var csInterface = new CSInterface();
    function init() {
        themeManager.init();
        $("#button").click(function () {
            var selectedPageSize = $("#select-page-size").val();
            var horizontalDivision = $("horizontal-division").text();
            var verticalDivision = $("vertical-division").text();
            var params = "" + selectedPageSize + "\t" + horizontalDivision + "\t" + verticalDivision;
            csInterface.evalScript('makeThumbnailList("' + params + '")');
        });
    }
    init();
}());

hostscript.jsx

var CR = String.fromCharCode(13);

function makeThumbnailList(paramsStr) {
    var params = paramsStr.split("\t");
    var selectedPageSize = params[0];
    var horizontalDivision = params[1];
    var verticalDivision = params[2];

    // ページサイズを選択していない場合は処理を停止
    if (selectedPageSize.length === 0) {
        alert("ドキュメントサイズを選択してください");
        return;
    }

    // 分割数が未入力の場合は初期値を入れる
    if (horizontalDivision.length === 0) {
        horizontalDivision = 3;
    }
    if (verticalDivision.length === 0) {
        verticalDivision = 3;
    }

    var marginValue = 10; // マージン
    var myLabelWidth = 100; // ラベルの横幅
    var myControlWidth = 60; // コントロールの横幅

    //ページサイズ
    var pageA4 = ["210","297"];
    var pageB4 = ["257","364"];
    var pageA3 = ["297","420"];

    //配列を作成
    var pictureList = new Array();
    var fileListEPS = new Array();
    var fileListAI = new Array();
    var fileListPSD = new Array();
    var fileListJPEG = new Array();
    var fileListTIFF = new Array();

    var folderObj = Folder.selectDialog("一覧にしたい画像のあるフォルダを選択してください");
    var fileListEPS = folderObj.getFiles("*.eps");//EPSファイルを配列化(小文字・大文字無視)
    var fileListAI = folderObj.getFiles("*.ai");//AIファイルを配列化(小文字・大文字無視)
    var fileListPSD = folderObj.getFiles("*.psd");//PSDファイルを配列化(小文字・大文字無視)
    var fileListJPEG = folderObj.getFiles("*.jpg");//JPEGファイルを配列化(小文字・大文字無視)
    if (folderObj.getFiles("*.jpeg").length != 0) {
        fileListJPEG = fileListJPEG.concat(folderObj.getFiles("*.jpeg"));//拡張子がjpegの場合を考慮。concatは配列の結合
    }
    var fileListTIFF = folderObj.getFiles("*.tiff");//tiffファイルを配列化(小文字・大文字無視)
    if (folderObj.getFiles("*.tif").length != 0) {
        fileListTIFF = fileListTIFF.concat(folderObj.getFiles("*.tif"));//拡張子がtifの場合を考慮。concatは配列の結合
    }

    var pipictureList = [];
    //配置画像の配列をひとつに
    if (fileListEPS.length != 0) {
        pictureList = pictureList.concat(fileListEPS);
    }
    if (fileListAI.length != 0) {
        pictureList = pictureList.concat(fileListAI);
    }
    if (fileListPSD.length != 0) {
        pictureList = pictureList.concat(fileListPSD);
    }
    if (fileListJPEG.length != 0) {
        pictureList = pictureList.concat(fileListJPEG);
    }
    if (fileListTIFF.length != 0) {
        pictureList = pictureList.concat(fileListTIFF);
    }

    //配置画像の数
    var pictureListLength = pictureList.length;

    //台紙を作成
    var docObj = app.documents.add();
    docObj.documentPreferences.facingPages = false;

    //サイズを変更
    if (selectedPageSize === "A4Portrait") {
        docObj.documentPreferences.pageWidth = pageA4[0];
        docObj.documentPreferences.pageHeight = pageA4[1];
    } else if (selectedPageSize === "A4Landscape") {
        docObj.documentPreferences.pageWidth = pageA4[1];
        docObj.documentPreferences.pageHeight = pageA4[0];
    } else if (selectedPageSize === "B4Portrait") {
        docObj.documentPreferences.pageWidth = pageB4[0];
        docObj.documentPreferences.pageHeight = pageB4[1];
    } else if (selectedPageSize === "B4Landscape") {
        docObj.documentPreferences.pageWidth = pageB4[1];
        docObj.documentPreferences.pageHeight = pageB4[0];
    } else if (selectedPageSize === "A3Portrait") {
        docObj.documentPreferences.pageWidth = pageA3[0];
        docObj.documentPreferences.pageHeight = pageA3[1];
    } else {
        docObj.documentPreferences.pageWidth = pageA3[1];
        docObj.documentPreferences.pageHeight = pageA3[0];
    }

    //マスターのマージンを決めてページに適用
    var myMaster = docObj.masterSpreads[0]; //適用するマスターを変数に
    for (var i = 0, pagesLength = myMaster.pages.length; i < pagesLength; i++) {
        myMaster.pages[i].marginPreferences.top = marginValue;//天
        myMaster.pages[i].marginPreferences.left = marginValue;//左
        myMaster.pages[i].marginPreferences.right = marginValue;//右
        myMaster.pages[i].marginPreferences.bottom = marginValue;//地
    }

    docObj.pages[0].appliedMaster = myMaster;//適用

    //ドキュメントの幅・高さ
    var pageWidth = docObj.documentPreferences.pageWidth;
    var pageHeight = docObj.documentPreferences.pageHeight;

    //1ページ当たりの配置数
    var maxHorizontalDivision = horizontalDivision * verticalDivision;

    //総ページ数
    var allPage = Math.ceil(pictureListLength / maxHorizontalDivision); // 小数点以下切り上げ

    //キャプの高さ
    var capHeight = 3;

    //1フレームの幅・高さ
    var frameWidth = (pageWidth - (marginValue * (horizontalDivision - 1)) - (marginValue * 2)) / horizontalDivision;
    var frameHeight = (pageHeight - (marginValue * (verticalDivision - 1)) - (verticalDivision * capHeight) - (marginValue * 2)) / verticalDivision;

    //フレームカウント用
    var lineCount = 0;

    //ページ数を増やす
    for (i = 0; i < (allPage - 1); i++) {
        docObj.pages.add();
    }

    //配置するフレーム作成
    for (var i = 0, pagesLength = docObj.pages.length; i < pagesLength; i++) {
        var pageObj = docObj.pages[i];
        for (var y = 0; y < verticalDivision; y++){
            for (var x = 0; x < horizontalDivision; x ++) {
                //画像フレーム作成
                var pictFrame = pageObj.textFrames.add();
                pictFrame.visibleBounds = [marginValue + (y * marginValue) + (frameHeight * y) + (capHeight * y),
                                           marginValue + (x * marginValue) + (frameWidth * x),
                                           marginValue + (y * marginValue) + (frameHeight * (y + 1)) + (capHeight * y),
                                           marginValue + (x * marginValue) + (frameWidth * (x + 1))];
                pictFrame.contentType = ContentType.graphicType;
                pictFrame.name = "pict" + lineCount.toString();

                //キャプションフレーム作成
                var capFrame = pageObj.textFrames.add();
                capFrame.visibleBounds = [marginValue + (y * marginValue) + (frameHeight * (y + 1)) + (capHeight * y),
                                          marginValue + (x * marginValue) + (frameWidth * x),
                                          marginValue + (y * marginValue) + (frameHeight * (y + 1)) + (capHeight * (y + 1)),
                                          marginValue + (x * marginValue) + (frameWidth * (x + 1))];
                capFrame.contentType = ContentType.textType;
                capFrame.name = "cap" + lineCount.toString();
                capFrame.textFramePreferences.verticalJustification = VerticalJustification.bottomAlign

                lineCount ++;
            }
        }
    }

    for (var p = 0; p < pictureListLength; p++){
        //画像配置
        docObj.pageItems.itemByName("pict" + p).select();
        var pictFrameSel = app.selection[0];

        var selFile = new File(pictureList[p]);
        pictFrameSel.place(selFile);
        pictFrameSel.fit(FitOptions.proportionally);

        //キャプ流し込み
        docObj.pageItems.itemByName("cap" + p).select();
        var capFrameSel = app.selection[0];

        var capKakou = pictureList[p].name;
        capContents = File.decode(capKakou) + CR;

        capFrameSel.contents = capContents;
        capFrameSel.paragraphs[0].pointSize = "10Q";

        if (capFrameSel.overflows) {
            var w = 100;
            while ((capFrameSel.overflows) && (w > 10)) {
                w--;
                capFrameSel.paragraphs[0].horizontalScale = w;
            }
        }
    }
    alert("処理が完了しました");
}

諦めたところ

プルダウンに CSS を適用するのがわりとめんどくさい感じだったので、諦めた。
あとフォント周りは CSS が適用されなかったので、themeManager.js に直接書いている。
いけてないね!

もっと詳しく

質問、要望があれば、Twitter にて。