y2x: YAMLフォーマットの文献リストを任意のviewで出力する

by Yoshihiro Nagano

y2xというツールを作った。

各種申請書シーズンな訳ですが、往々にして申請書ごとに文献の並び順であったり書き方が異なるわけです。怠惰であることを第一義とするエンジニアの皆様におかれましてはこの状況は大変つらみがある。bibtexを使って頑張るのも一つの選択肢ではあるが、せっかくならウェブサイトに載せる情報も含めてwrite onceで実現しようと思うとJavaScriptあたりの技術で実現したくなる。

実際のところは、申請書やウェブサイト、bibtexフォーマットなど、個々の書類ごとにデータは同一で表示形式のみ切り替えらるようなツールが欲しいという依頼を最近受けて、ちょうどUniversal JavaScriptで一つパッケージを書いてみたいと思っていたところだったのでちょうどよかったというきもちがある。

というわけで。

Installation

npm scriptで実装した。現時点ではまだnpmに登録していないので、GitHubリポジトリを落としてきてインストールする。

$ git clone git@github.com:ganow/y2x.git
$ cd y2x
$ npm install -g

Usage

  Usage: y2x <file> [options]

  Options:

    -h, --help         output usage information
    -V, --version      output the version number
    --view <text>      format string for each record
    --viewfile <file>  file name of format string for each record
    --author <text>    filter records with specific author
    --type <text>      record type
    --sort-by <text>   entry which is used by sort
    --reverse          flag for reverse sort
    --reverse-index    flag for reverse index
    --offset <n>       offset for index

現時点では、

  • YAMLフォーマットで読み込んだ文献一覧を任意のviewに変換する
  • 特定の著者が含まれる文献のみフィルタリングする
  • 国際会議、国内会議、論文などの文献のタイプごとにフィルタリングする
  • 出版年や文献のタイプで一覧をソートする

あたりの機能がある。

コマンドラインインターフェースとパッケージとしての利用の2つを想定していて、例えば

-
  type: conference
  title: Auto-encoding Variational Bayes
  authors:
    - Diederik Kingma
    - Max Welling
  year: 2013
  conference: ICLR
-
  type: conference
  title: Deep Boltzmann Machines
  authors:
    - Ruslan Salakhutdinov
    - Geoffrey Hinton
  year: 2009
  conference: AISTATS
-
  type: paper
  title: Reducing the dimensionality of data with neural networks
  authors:
    - Geoffrey Hinton
    - Ruslan Salakhutdinov
  year: 2006
  journal: Science

のようなデータセットdata.ymlを管理しているとする。 このデータに対して y2x コマンドを使用して様々な形式の出力に変換していく。

viewフォーマットを使用したテキストの変換

上記のデータに対して、出版年でソートして通し番号. (出版年) タイトルと表示したい場合は

y2x data.yml --view '{id}. ({year}) {title}' --sort-by year

というコマンドを実行することで出力

1. (2006) Reducing the dimensionality of data with neural networks
2. (2009) Deep Boltzmann Machines
3. (2013) Auto-encoding Variational Bayes

が得られる。

指定著者のみのフィルタリング

y2x data.yml --view '{id}. {title}, {authors}' --author 'Geoffrey Hinton'

とすればHintonが著者に含まれる文献のみが抽出できて、

1. Deep Boltzmann Machines, Ruslan Salakhutdinov, Geoffrey Hinton
2. Reducing the dimensionality of data with neural networks, Geoffrey Hinton, Ruslan Salakhutdinov

というような出力が得られる。

特定の文献の種類でフィルタリング

y2x data.yml --view '[{type}]: {title}' --type conference

とすれば文献の種類がconferenceのもののみを抽出できて

[conference]: Auto-encoding Variational Bayes
[conference]: Deep Boltzmann Machines

という出力が得られる。

viewフォーマット解説

コマンドラインオプション--viewに渡す文字列の中に{entry}という文字列を含めることでentry: ***と記載されたデータを取得できる。{id}は特別なエントリーで1つめの要素から順番に与えられる通し番号である。通し番号を逆順にしたい場合は--reverse-indexオプションを与える。

パッケージインターフェース

ここまでCLIの使い方を説明してきたが、一方でより複雑なオプションを指定したい需要もあり得る。例えば、国際会議と論文ではそれぞれconferencejournalという別々のエントリーを保持していて、文献の種類によってそれらの表示を切り替えたいことがある。こういった需要から、y2xではパッケージとしてJavaScriptのコード内で呼ぶインターフェースを用意している。

はじめに示した「出版年でソートして通し番号. (出版年) タイトルと表示する」ケースは

const loadRecords = require('y2x').loadRecords

const records = loadRecords('data.yml')
const texts = records
  .view('{id}. ({year}) {title}')
  .sortBy('year')
  .render()
texts.map((el) => console.log(el))

というコードで等価な結果を得ることができる。

国際会議と論文で表示形式を切り替えたい場合には

const loadRecords = require('y2x').loadRecords

const records = loadRecords('data.yml')
const texts = records
  .view({
  	paper: '{id}. ({year}) {title}, {journal}',
  	conference: '{id}. ({year}) {title}, {conference}'
  })
  .sortBy('year')
  .render()
texts.map((el) => console.log(el))

というコードで出力

1. (2006) Reducing the dimensionality of data with neural networks, Science
2. (2009) Deep Boltzmann Machines, AISTATS
3. (2013) Auto-encoding Variational Bayes, ICLR

が得られる。

TODO

全体的に急ぎで作ったので、異常系の処理をカバーしきれてない。 このへんは気が向いたときにまとめて実装したい。 またインターフェース考えながら実装しながらでやってるから、使い方についても今後大きく変わる可能性もある。

おきもち

最初のモチベーションとしては文献リストに限らないもっと一般的なデータの変換ツールにしようと思って作り始めたが、結局インターフェース考えるうちに--authorオプションに代表されるようにデータ構造をある程度仮定したものになった/なってしまった。y2xよりもいいネーミングがありそうな気がするけど発想力が貧困すぎて思いつかなかった(募集中)。