Corredor

ウェブ、プログラミングの勉強メモ。

Columnify を使って Node.js スクリプトのコンソール出力をテーブルっぽく整形する

Node.js スクリプトでコンソール出力を整形する際、最も手軽なのは console.table() だろう。

$ node -e "console.table([ { id: 1, name: 'testA' }, { id: 2, name: 'testB' } ]);"

┌─────────┬────┬─────────┐
│ (index) │ id │  name   │
├─────────┼────┼─────────┤
│    01'testA' │
│    12'testB' │
└─────────┴────┴─────────┘

(コンソールからコピペしただけなので、閲覧環境によっては横棒の罫線が長く見えているかもしれない。コンソール上では綺麗に見えている)

console.table() は組み込み済なので手軽ではあるが、細かな出力仕様の調整が効かないので、他にコンソール出力をテーブルっぽく整形してくれるライブラリがないか探した。すると、Columnify という npm パッケージが使いやすかったので、コレを試してみた。

インストール

いつもどおり。

$ npm install --save columnify

基礎1 : 単にオブジェクトを渡してみる

  • columnify.js … 以下のようなサンプルコードを書いてみる
const columnify = require('columnify');

console.log(columnify({
  hoge: 'HOGE value',
  fugafuga: 'FUGA value'
}));

コレを実行してみると、以下のようになる。

$ node columnify.js

KEY      VALUE
hoge     HOGE value
fugafuga FUGA value

オブジェクトを渡せば、KEYVALUE という列名で上手く表示してくれる。

基礎2 : 複数オブジェクトを持つ配列を渡してみる

次に、サンプルコードを以下のように修正してみる。

console.log(columnify([
  { id: 1, name: 'テスト 太郎', gender: 'Male' },
  { id: 99, name: 'Test', gender: 'Feale', flag: 'Administrator' }
]));

配列に、2つのオブジェクトが格納されている。idnamegender プロパティは同じだが、flag プロパティは2つ目の要素しか持っていない。このようなデータはどう表示されるかというと…。

$ node columnify.js

ID NAME        GENDER FLAG
1  テスト 太郎 Male
99 Test        Feale  Administrator

注目すべきは、テスト 太郎 のように全角文字を含んでいても列の整形が上手くできている点だ。また、flag プロパティのように一部の要素しか持っていないプロパティも上手く表示できた。

カスタマイズ色々

Columnify は出力形式を色々とカスタマイズできるので、いくつか試してみる。

列ごとの区切り線を入れてみる

列ごとの区切り線を入れるには、columnSplitter プロパティを使う。

console.log(columnify([
  { id: 1, name: 'テスト 太郎', gender: 'Male' },
  { id: 99, name: 'Test', gender: 'Feale', flag: 'Administrator' }
], {
  columnSplitter: ' | '  // ← こんな風に縦線を入れてもらう
}));
$ node columnify.js

ID | NAME        | GENDER | FLAG
1  | テスト 太郎 | Male   |
99 | Test        | Feale  | Administrator

このとおり。

値を中央揃えや右揃えにしてみる

CSS でいう text-align のように、値を中央揃えや右揃えにできる。config プロパティは列名ごとに個別の指定ができるモノ。

console.log(columnify([
  { id: 1, name: 'テスト 太郎', gender: 'Male' },
  { id: 99, name: 'Test', gender: 'Feale', flag: 'Administrator' }
], {
  columnSplitter: ' | ',
  config: {
    id: {
      align: 'right'
    },
    name: {
      align: 'center'
    }
  }
}));

ココでは id 列を右揃え、name 列を中央揃えにした。

$ node columnify.js

ID |    NAME     | GENDER | FLAG
 1 | テスト 太郎 | Male   |
99 |    Test     | Feale  | Administrator

上手く文字揃えが設定されている。

列の見出し文言を変える

列の見出しは、プロパティを大文字にしたモノが使われる。コレに固定されるのは嫌なので、見出しを自由に変えてみる。

console.log(columnify([
  { id: 1, name: 'テスト 太郎', gender: 'Male' },
  { id: 99, name: 'Test', gender: 'Feale', flag: 'Administrator' }
], {
  columnSplitter: ' | ',
  config: {
    id: {
      headingTransform: (heading) => `ユーザ ${heading.toUpperCase()}`,
      align: 'right'
    },
    name: {
      headingTransform: (heading) => '氏名',
      align: 'center'
    }
  }
}));

列ごとの設定 (config) にて、headingTransform というプロパティを定義し、そこに文字列を返す関数を用意する。仮引数 heading には、大文字に変換される前のプロパティがそのまま入っている。

{
  config: {
    id: {
      // アロー関数を省略せず書くとこのとおり
      headingTransform: (heading) => {
        return `ユーザ ${heading.toUpperCase()}`;
      }
    }
  }
}

name プロパティの方は、仮引数 heading を使わず、問答無用で '氏名' という見出しにするようにした。

結果は以下のとおり。

$ node columnify.js
ユーザ ID |    氏名     | GENDER | FLAG
        1 | テスト 太郎 | Male   |
       99 |    Test     | Feale  | Administrator

IDNAME となっていた見出し文言が ユーザ ID氏名 に変わっているのが分かるだろう。

以上

割と柔軟にカスタマイズできるので、あとは公式の README を見ながら自由にコンソール出力を整形してみよう。


「ターミナル」コンソール…… ← ダジャレ

Xcode で Storyboard を使っていたら出てきた Auto Layout 警告の直し方

Xcode で Storyboard を使っていたら、以下のような警告が出てきた。

Views without any layout constraints may clip their content or overlap other views.

エラー文言でググったけどイマイチ分からない。でも何やらとりあえず Auto Layout、自動的に配置を整列した要素に問題がある予感らしい。しかし、作っていても特に問題を感じないんだよな…。

…と思っていたら、以下の文献を発見。

For me what worked was the reposition the elements: Drag them again into position and drag their height and width to the desired size again. Then click on "Resolve Auto Layout Issues" and click on "Reset to Suggested Constraints".

Storyboard の編集ペインの右下に、5つのアイコンが並んでいる。このうちの右端、

├△┤

こんな感じのアイコンがあると思う。コレが「Resolve Auto Layout Issues」ボタンというのだが、コレをクリックして、「Selected Views」内の「Reset to Suggested Constraints」項目をクリックすることで、何やらうまいこと配置が自動調整されるようで、ワーニングが消えた。

しかしこの後編集していても度々発生して、そのくせ動作には別に問題ないように見えるので、なんだかよー分からん警告だけど無視したろ、の精神で以後無視している。w

たった2日でマスターできるiPhoneアプリ開発集中講座 Xcode 10 Swift 4.2対応

たった2日でマスターできるiPhoneアプリ開発集中講座 Xcode 10 Swift 4.2対応

MacOS Finder で開いているディレクトリにターミナル上で移動する Bash 関数

MacOS のターミナルで、カレントディレクトリを Finder で開きたい時は、$ open . と叩けば良い。

その逆で、「Finder で開いているディレクトリに、ターミナル上で移動したい」時のコマンドを用意する。

Finder 上からそのディレクトリのターミナルを開く際は、ディレクトリを右クリックして「フォルダに新規ターミナルタブ」を選べばよいが、新規ターミナルタブも開くことなく、cd する感覚で遷移する。

function cdf() {
  local target=`osascript -e 'tell application "Finder" to if (count of Finder windows) > 0 then get POSIX path of (target of front Finder window as text)'`
  if [ "$target" != "" ]; then
    cd "$target" && pwd  # お好みで「&& ls」まで入れても良いかも
  else
    echo 'No Finder window found' >&2
  fi
}

コレを ~/.bashrc にでも書いておいて source しておく。

Finder で適当なディレクトリを開いておき、その状態でターミナルにて cdf と叩けば、そのディレクトリに cd してくれる。

osascript とかいうコマンドが Finder のパスを拾っているのだが、コレは AppleScript が叩けるコマンドらしい。

新・AppleScriptでゼンマイびゅんびゅん!! (Mac power books)

新・AppleScriptでゼンマイびゅんびゅん!! (Mac power books)

複数行のテキストを CSS だけで省略表示する -webkit-line-clamp を試してみた

Webkit 系 (Chrome や Safari) でのみしか使えない CSS プロパティだが、-webkit-line-clamp というプロパティを使うと、複数行に折り返されたテキストでも省略表示ができることが分かったので、使ってみた。

text-overflow: ellipsis は1行テキストにしか対応していない

CSS だけで実現するテキストの省略表示というと、text-overflow: ellipsis プロパティがあるが、こちらはテキストが1行の時しか省略表示してくれない。

.ellipsis-box {
  text-overflow: ellipsis;  /* 省略表示する */
  white-space: nowrap;      /* テキストを折り返しさせないために必要 */
  overflow: hidden;         /* ボックスからはみ出たテキストを隠し text-overflow を適用するために必要 */
  width: 300px;             /* overflow を効かせるために適当なボックス幅を設定しないといけない */
}

一緒に書かないといけないスタイルもコレだけあって、理屈は分かるんだけど、なんというかこう、直感的ではない。

複数行に折り返し、最終行の行末で省略表示するような挙動をさせたい場合は、色々なハックを突っ込んだり、結局 JavaScript を併用したりするしかなかった。

-webkit-line-clamp を使ってみる

そこで登場したのが -webkit-line-clamp というプロパティ。以下のように使う。

.line-clamp-box {
  display: -webkit-box;          /* line-clamp を有効にするために指定する */
  -webkit-box-orient: vertical;  /* line-clamp を有効にするために指定する */
  -webkit-line-clamp: 3;         /* コレで折り返し表示する行数を指定する・ココでは3行分表示させる */
  overflow: hidden;              /* ボックスからはみ出た分を非表示にする */
  width: 300px;                  /* 必ずしも必須ではないが overflow を効かせるために設定する */
}

display: -webkit-box; というプロパティでボックスのタイプを変える。-webkit-box-orient: vertical; というのはフレキシブルボックス内の子要素の配置方向を指定するモノなのだが、書かないと -webkit-line-clamp が有効にならないので書いておく。

お目当ての -webkit-line-clamp は、値に行数を整数値で取る。上述の例では 3 と指定したので、3行分表示される。このプロパティによって、ボックスに max-height 相当の高さ制限が作られる。中のテキストが1・2行の時はその行数を表示できるだけの高さになる。4行を超える時は、3行分を表示したところで広がらなくなる。

overflow: hidden; は、設定しなくても省略表示の ... は表示されるが、ボックスからはみ出たテキストが表示されてしまうため、設定しておく。width は折り返しを効かせるために適当に設定。width を指定せず、ウィンドウ幅に任せても作用はする。

-webkit-line-clamp を適用したコンテンツは、自然な折り返しだけでなく、br 要素による強制改行にも対応している。ただし、子要素にブロック要素を配置した場合は、「行数」とはみなされない。

<div class="line-clamp-box">
  <div>子要素1</div>
  <div>子要素2</div>
  <div>子要素3</div>
  <div>子要素4</div>
  テキスト1行目<br>
  テキスト2行目<br>
  テキスト3行目<br>
  テキスト4行目
</div>

つまり、このような HTML にした時は、

子要素1
子要素2
子要素3
子要素4
テキスト1行目
テキスト2行目
テキスト3行目...

と表示される。

-webkit-line-clamp 未対応のブラウザ向けの対応

冒頭に書いたとおり、このプロパティは WebKit 系のブラウザでしか有効にならないので、Firefox 等では上手く動作しない。未対応のブラウザ向けには、max-height を指定して overflow: hidden による非表示機能でしのぐしかないだろう。

.line-clamp-box {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  width: 300px;
  max-height: 3.5rem;  /* ← 追加 : テキスト3行が表示できる程度の高さ */
}

f:id:neos21:20181208133638p:plain

↑ 左が -webkit-line-clamp が適用できているボックスで、右がフォールバック表示しているボックス。

未対応のブラウザでは、省略表示の ... が表示されないことになるが、ココらへんのクロスブラウザ対応は厳しいので、まだまだ使う際には妥協が必要か。

HTML5 & CSS3 デザインレシピ集

HTML5 & CSS3 デザインレシピ集