コードプレゼンテーションフレームワークの提案と実装第1 章 はじめに...

61
コードプレゼンテーションフレームワークの提案と実装 明治大学大学院 理工学研究科 基礎理工学専攻 情報科学系 計算理論研究室 松井 2017 2 22

Upload: others

Post on 27-Jan-2021

1 views

Category:

Documents


0 download

TRANSCRIPT

  • コードプレゼンテーションフレームワークの提案と実装

    明治大学大学院 理工学研究科

    基礎理工学専攻 情報科学系

    計算理論研究室

    松井 集

    2017年 2月 22日

  • 概要

    ソースコードを含むプレゼンテーション用スライドを, 既存手法より簡単に生成可能な汎用性のある

    コードプレゼンテーションフレームワークを提案し, テキストエディタ「Atom」の拡張機能としてプログ

    ラミング言語 JavaScriptにより実装した.

    ソースコードを読むことは, プログラミングを学ぶ上でとても重要な動作であり, 実際の開発を行う上

    でも他者によって書かれたソースコードを読んで理解することが求められることは非常に多い. また, 読

    んだソースコードの内容について整理して聴衆の前で発表することは, 聴衆の理解を促すだけでなく発表

    者の理解を整理する上でも重要である.

    こうした背景からソースコードとその内容をまとめて発表する上でその内容をまとめてプレゼンテー

    ションする時に, コードの内容をスライド中に表示すべき時があるが, ソースコードを含むプレゼンテー

    ション用のスライドを作成する場合, 既存のプレゼンテーション作成ツールではコードの取り扱いに特化

    しておらず, コードの挿入に手間がかかったり, 後から変更が効きにかったりするなどの問題点がある.

    本論文では, 実装した拡張機能についての詳細と使用方法, およびその応用について述べる.

    i

  • 目次

    概要 i

    第 1章 はじめに 1

    1.1 研究背景 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

    1.2 研究目的 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

    1.3 関連する事例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

    第 2章 提案手法の概要 5

    2.1 提案手法の特徴 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

    2.2 導入方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

    2.3 Atomにおける画面各部の呼称 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

    2.4 使用にあたっての前提 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

    2.5 構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

    第 3章 使用方法 9

    3.1 ページ編集モードで実行可能な操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

    3.2 プレゼンテーションモードで実行可能な操作 . . . . . . . . . . . . . . . . . . . . . . . 12

    第 4章 プレゼンテーションに関する情報 14

    4.1 プレゼンテーションに関する情報を格納するディレクトリ . . . . . . . . . . . . . . . . 14

    4.2 プレゼンテーションデータ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

    4.3 注釈 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

    4.4 コードを背景に表示しないページ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

    第 5章 ページ編集モードとスライドのページ構成方法 19

    5.1 注釈に関連する操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

    5.2 スライドの構成方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

    第 6章 プレゼンテーションモード 24

    6.1 概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

    6.2 描画 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

    6.3 ページ遷移 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

    ii

  • 第 7章 実装 27

    7.1 パッケージの構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

    7.2 lib/codejacket.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

    7.3 lib/presentation 下のファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

    7.4 lib/annotations 下のファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

    7.5 lib/indent-tree 下のファイル . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

    第 8章 ソースコードが外部により変更された場合の注釈の移動 33

    8.1 前提 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

    8.2 パッチの取得 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

    8.3 ファイル全体の行対応情報の取得 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

    8.4 新ソースから旧ソースのマッチング . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

    8.5 注釈のコピー . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

    第 9章 実験 38

    9.1 実験の概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

    9.2 行の対応関係が自明な場合 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

    9.3 行の対応関係が自明でない場合 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

    第 10章 まとめ 52

    10.1 課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

    10.2 今後の展望 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

    付録 A 使用したオープンソースソフトウェア 54

    謝辞 55

    参考文献 56

    iii

  • 第 1章

    はじめに

    ソースコードの読解を支援するためのソフトウェアとして, ソースコードの内容をプレゼンテーション

    するための枠組みを開発した. テキストエディタ「Atom[1]」の拡張機能としてプログラムを読み込むこ

    とによって動作する.

    発表者が聴衆に向けて伝えたい付加情報をソースコード上の位置に関連付けて配置することができるの

    が特徴である.

    この拡張機能は, 大別すると下記の機能からなる.

    • テキストエディタの文字の大きさをプレゼンテーション用に拡大し, 全画面表示に切り替えた上で,付加情報をエディタ上に描画する機能.

    • テキストエディタ上で, 上記の付加情報を編集する機能.

    本稿では, 開発した拡張機能についての詳細とその使用方法について述べる.

    1.1 研究背景

    コンピュータやインターネットの普及, 情報科学や情報工学の発展により, 今日までに, 様々な

    e-learningのシステムが登場している.

    プログラミングをすることは, 読み書きが複合したプロセスからなっており, ソースコードを読むこと

    は, ソフトウェアのメンテナンスを行う上で非常に重要な動作である [2]. 例えば, ソフトウェア開発にお

    いて, ソースコードの品質を上げるために行われるコードレビューを行うには, 他者が書いたソースコー

    ドを読む動作が必要となる. また, ソースコードを読んで理解することは, システムの構成やプログラミン

    グについての洞察力を養うことにも繋がる [3].

    しかし今日まで, プログラミングの学習支援は, 読む操作より書く操作についての研究が中心に行われ

    てきた [4].

    プログラミングを学び始めてから, 基礎的なことを一通り学び終えた後に自らソフトウェアを開発した

    り, オープンソースコミュニティで活躍したりするまでには様々な訓練が必要だと思われるが, 読む動作

    と, そのプログラムの振る舞いを他者に説明するということはその中の一つであり, その中でも重要なこ

    とであると著者は推測する.

    1

  • 本研究では, 読んだソースコードや自分が書いたソースコードを他者に説明することを支援することを

    目標とする.

    1.1.1 テキストエディタ Atom

    Atom は, デスクトップ上で動作するテキストエディタである. GitHub Inc. により開発されており,

    オープンソースソフトウェアとして Web 上でソースコードが公開されている. Atom は, JavaScript,

    HTML(Hypertext Markup Language), CSS(Cascading Style Sheet)でクロスプラットフォームなアプ

    リケーションを開発可能な環境の Electron[5]上に構築されている.

    Atom の表示に関わる主な部分は, JavaScript および JavaScript にコンパイルされるプログラミング

    言語の CoffeeScript[6]で記述されている. 画面の装飾については, CSSにコンパイルされる言語の less[7]

    によって記述されている.

    パッケージと呼ばれるプログラム群を Atom に追加することにより, エディタに外部から機能を追

    加することが可能である. パッケージは, JavaScript, CoffeeScript, CSS, JSON(JavaScript Object

    Notation) 形式などのファイルからなり, Atom の機能を使用したり, 表示に関わる部分を操作したりす

    ることができる. Atom の画面は HTML の DOM( Document Object Model ) によって構築されてお

    り, また, 機能拡張のための APIが標準で用意されているためパッケージ側からこれらを操作することに

    より, 容易に機能の拡張や変更が可能である.

    本研究では, 既存のテキストエディタの資源を有効活用し, Atomに対してパッケージを追加すること

    によりソースコードを使用したプレゼンテーションツールを作成した.

    1.2 研究目的

    プログラムの仕様や実装を他者に説明することは, チーム開発や教育などの面で重要である. これらの

    場面では, 説明のためにスライド形式のプレゼンテーションツールが用いられることがある.

    しかし, Microsoft PowerPoint や Keynote などに代表される代表的なプレゼンテーションツールは,

    ソースコードの取り扱いに特化しておらず, これらのツールでソースコードを取り扱う場合, 以下のよう

    な方法でスライド中に取り込むことができるが, 工数やスタイルなどの面で必ずしも望ましいものとは言

    えない.

    • ソースコードをテキストエディタ上に表示した上で, テキストエディタの画面をキャプチャした画像を作成し, スライド上に挿入する.

    • ソースコードをテキストエディタ上に表示し, クリップボードを経由してスライドに貼り付ける.

    特に後者の場合, プレゼンテーションツールとその設定状況によっては一般の英文と認識され, 貼り付

    けられたソースコードの一部もしくは全部において,アルファベットの大文字小文字の関係, 二重引用符

    の自動変換などが自動的に行われるなどの意図しない動作が発生することがあり, コードを含むプレゼン

    テーションを作成することを難しくしている要因の一つとなっている.

    また, 近年になり, reveal.js[9]を始めとする HTMLベースのプレゼンテーションフレームワークが登

    場している. reveal.jsでは, ソースコード片を見やすく整形してスライドのページに挿入することができ

    2

  • る. しかし, ソースコードの特定の部分をさすようなメモを挿入するようには特化しておらず, そのような

    図形やテキストボックスをソースコードの上から描画しようとするとブラウザやインストールされている

    フォントなどによって表示が崩れることがある.

    いずれの既存のプレゼンテーションツールも, コードの内容が修正された場合はプレゼンテーションの

    データが保存されているファイルを直接編集する必要があり, ソースコードの読解などで用いるには手間

    がかかることがある.

    1.2.1 想定される使用例

    本研究での提案手法は, 下記のような使用例を想定している.

    • ソフトウェア開発チーム内での情報共有• ソースコードの勉強会• プログラミングに関係する授業

    ソフトウェア開発チーム内での情報共有では, ソースコード中に複数の人物が注釈を書き込むことを可能

    にすることにより, コードレビューの結果をわかりやすく保持することを可能にする.

    ソースコードの勉強会は, 主に他者によって記述されたソースコードを読解する勉強会を想定している.

    発表者が読んで理解したことを整理して表示できることを可能にする.

    プログラミングに関する授業では, 特定の言語の機能を説明したり, アルゴリズムを説明したりといっ

    た場面での使用を想定している.

    この他, ソースコードを含むスライド全般において使用されることを想定している.

    1.3 関連する事例

    本研究では, ソースコードの特定の場所もしくはその場所を参照する形で主に文章による注釈を挿入す

    る. この手法は, 他分野において多くの場面でとられており, この節ではその例を示す.

    1.3.1 ドキュメンテーションツール

    ソースコードに説明となる特殊な形式のコメントを記述し, HTML 形式などのドキュメントを生成す

    るツールが存在する. 例として, 言語 Java に対する JavaDoc[12] や, JavaScript に対する JSDoc[13] ,

    PHPに対する phpDocumentor[14] などが挙げられる.

    これらのツールは, 本論文の提案手法と, ソースコード中に注釈を残すという意味では近いが, これらの

    ツールは主にプログラムやライブラリの仕様を記述することに重点が置かれている点が異なる. また,プ

    レゼンテーションにおいてはコードの内容と聴衆への説明内容は必ずしも一致しないという点で, これら

    のコメントを用いてプレゼンテーションを作成するのは難しいと考えられる.

    また, 特定のプログラミング言語に依存するため, 新しいプログラミング言語への対応の柔軟性という

    点で課題がある.

    3

  • 1.3.2 ソースコード中にメモを残す先行研究

    ソースコードにメモを残す手段としては, 斎藤ら [8]によりソースコード閲覧システムが提案されてい

    る. このシステムでは, C言語の関数や変数などの名前の実体やコード中の領域とメモを日もつける形で

    メモを残すことができる. 作成したメモは専用の閲覧ツールから閲覧でき, 複数のユーザがメモを残すこ

    とができ, コードレビューなどにも応用が可能である.

    1.3.3 コードレビューツール

    この他、バージョン管理システムの特定のリポジトリにおける版間差分を表示して, コード中にコメン

    トを残すことができるツールやWebアプリケーションがいくつか存在する. 例えば, Gitリポジトリのホ

    スティングサービスである GitHub[10]や, コードレビューツールの Review Board [11] では, バージョ

    ン版間の差分やコードの変更の要求に対して行単位でコメントを残すことができる.

    これらのツールは, 使用目的をコードレビューに絞っていて, レビューの内容の確認や投稿は個人の端

    末で行うのが普通である. また, バージョン管理システムの使用がほぼ必須となっているため, 小規模な

    コードをレビューするためには手間がかかる.

    4

  • 第 2章

    提案手法の概要

    この章では, 提案手法の概要について述べる.

    2.1 提案手法の特徴

    本研究で作成したパッケージには, 以下のような特徴がある.

    • 発表スライドはソースコードを下地に, ソースコードに関連する説明などの文字列をその上から表示する.

    • ソースコードを下地にしないページについては, HTMLの一部のタグを使用することにより, スライド作成者が自由に編集することができる.

    • スライド作成後に発表対象のソースコードに変更が加わった場合, 前回保存時のソースコードとの版間差分を取った上で注釈の位置が変更される.

    • 発表に関わる情報は 1つのディレクトリにまとまっており, 同じソースコード群に対する情報であれば差し替えが有効である.

    2.2 導入方法

    提案手法のフレームワークは, エディタ Atom に新たにパッケージを追加することにより動作する.

    パッケージは Atomのパッケージシステムである apm*1により, Atomに導入することができる. イン

    ストールを行うには, 利用しているオペレーティングシステム*2 のシェルで, パッケージのディレクトリ

    内部に移動した後に下記のコマンドを実行する (行頭の$はプロンプトを表し, 実際のコマンドには含まれ

    ない).

    $ apm link

    $ apm install

    *1 apmは Atomのインストール時に同時にインストールされる.*2 Atom が対応しているプラットフォームは, バージョン 1.13.0 現在で, Windows, macOS, Linux(x86 64, amd64) である.

    5

  • この操作の後, Atomを起動する (既に Atomが起動している場合には再起動する)と, 当該パッケージ

    が有効となる.

    2.3 Atomにおける画面各部の呼称

    本パッケージの説明をするにあたり必要な Atom の画面各部の呼称について説明する. 図 2.1 は, 本

    パッケージを導入した状態の Atomのウィンドウである.ただし, 実行する OSやウィンドウシステムの

    環境にタイトルバーの領域のデザインは依存する. また, 他のパッケージやテーマ (ユーザが CSS,lessに

    よって変更可能なスタイル)の導入状況により配色や表示内容が異なる可能性がある.

    図 2.1 本パッケージを導入した状態の Atom (通常モード)

    2.3.1 メニューバーとワークスペース

    画面上部の「File Edit ...」といったメニューが並んでいる箇所を「メニューバー」(Menu bar)と称し,

    それ以外の部分が「ワークスペース」(Workspace)と呼ばれる領域に含まれる. ワークスペースには,後

    述する「パネル」「ペイン」「ステータスバー」が含まれる.

    2.3.2 ペインとテキストエディタ

    ワークスペース中央部に存在する大きな領域が「ペイン」(Pane)である. ペイン上部のファイル名が書

    かれている領域が「タブ」(Tab)であり, ペイン下部の領域が「テキストエディタである」. タブのクリッ

    クにより表示/編集するテキストエディタを切り替えられる他, ドラッグアンドドロップによりペインを

    6

  • 複数に分割することもできる.

    2.3.3 パネル

    パネル (Panel)は, ペインの上下左右の領域などに配置できるものである. 画面を覆うように表示させ

    る領域である「モーダル」(modal)や, ワークスペース最下部に表示される領域のフッタ (footer)などに

    もパネルを配置することができる. それぞれの領域内にパネルは 0個以上存在できる.

    パネルはその表示内容を HTML で表し, パッケージによって自由にこれを書き換えることが可能で

    ある.

    2.3.4 ステータスバー

    ワークスペースの下側の横に長い領域を「ステータスバー」(Status bar)と呼び, 現在開いているファ

    イルの情報やエディタの状態などを表示する. ステータスバーは, 標準で導入されているパッケージの

    status-bar により提供される.

    ステータスバーは, 通常パネルのフッタ領域に存在する. (図 2.1下部).

    2.3.5 ツリービューとプロジェクトフォルダ

    Atomは, 特定のディレクトリを対象に開く操作により, そのディレクトリを「プロジェクトフォルダ」

    (Project Folder) として認識する. 左側に表示されているリストは「ツリービュー」(Tree View)と呼ば

    れ, プロジェクトフォルダ以下のディレクトリとファイルの一覧を表示する. また、ファイルを開くこと

    によってペイン内にテキストエディタを開くことができる.

    ツリービューは, 通常ペインの左側のパネルに存在する. 開かれているプロジェクトフォルダが存在し

    ない場合やユーザによって非表示にされた場合は表示されない. (図 2.1左側)

    2.4 使用にあたっての前提

    本パッケージの使用にあたって, 下記の状態を前提とする.

    • Atomのバージョンは 1.13.0である.• 開かれている Atomのウィンドウの数は 1つである.• 表示されているペインとテキストエディタは, ワークスペース内にそれぞれ 1つずつである.• プロジェクトフォルダがワークスペース内に 1つだけ開かれている.

    2.5 構成

    2.5.1 モード

    このフレームワークは, 以下の 3つの状態を持つ. これらの状態のことを「モード」と称する.

    7

  • • 通常モード (表示上は Normal Mode): 通常のエディタの状態• ページ編集モード (表示上は Edit Mode): 注釈の編集が可能 (第 5章で説明). ソースコードは編集できない.

    • プレゼンテーションモード (表示上は Presentation Mode): プレゼンテーション用にスライドを表示 (第 6章で説明).

    プラグイン導入後, Atomの起動時は先述した「通常のエディタの状態」である.

    通常モードの時は「CJ::Normal」, ページ編集モードの時は赤い背景に白い文字で「CJ::Edit」」とス

    テータスバー上の領域に表示される. プレゼンテーションモードはステータスバー自体が表示されないた

    め, モードの表示はない.

    この 3つのモードは, 相互に任意の時点で遷移可能である. 次のいずれかのような手順を取ることによ

    り, モードの切り替えが可能である.

    • Atomの画面上部メニューバーから「Packages」内の「CodeJacket」から変更先のモードを選択する.

    • エディタの画面上で右クリックし, 変更先のモードを選択する.• 所定のキーボードの操作を行う. キーボードの組み合わせは, Atom側の設定で自由に変更することが可能である. (初期状態では,「Ctrl」「Alt」「Shift」の 3つのキーを押しながら, 通常モードへ

    変更する場合は「N」, ページ編集モードへ変更する場合は「E」, プレゼンテーションモードへ変

    更する場合は「P」キーをそれぞれ押すことでモード変更が可能である.)

    • ステータスバーにある「再生ボタン」(緑色の三角形)を押すとプレゼンテーションモードになる.• 再生ボタンの右側にあるモードの表示ボタンを押すと, 通常モードの時はページ編集モードに,ページ編集モードの時は通常モードに変更される. これによりページ編集モードから通常モードに

    変更される時は, スライドの情報が保存される.

    2.5.2 プロジェクトフォルダ下のディレクトリ構成

    当該パッケージは, Atomのプロジェクトフォルダ下をプレゼンテーションを行うためのディレクトリ

    として認識する. スライド中で下地になるソースコードは, すべてこのディレクトリ下に存在しなければ

    ならない.

    プレゼンテーションで使用する下地になるソースコード以外のデータはプロジェクトフォルダ直下

    に配置されるディレクトリ__CodeJacket 下に存在する必要がある. ページ注釈と前回保存時のファ

    イル内容はディレクトリ__CodeJacket 直下のディレクトリ annotations に, ソースコードを下地と

    しないページに関する情報はディレクトリ__CodeJacket 直下のディレクトリ no-code-pages にそ

    れぞれ存在する必要がある. プレゼンテーションの流れの情報は ディレクトリ__CodeJacket 直下に

    presentation.json の名前で保存する必要がある. ただし, presentation.json は自動で初期状態の

    ものが生成される.

    これらのディレクトリについては第 4章で詳しく述べる.

    8

  • 第 3章

    使用方法

    この章では, 提案手法のフレームワークの使用方法について述べる. 通常モードでの操作方法は, パッ

    ケージ導入前の Atomとほぼ変わりがないので, ページ編集モード, プレゼンテーションで実行可能な操

    作について述べる.

    3.1 ページ編集モードで実行可能な操作

    ページ編集モードでは, スライドを構成するページの内容を編集したり, コード上に注釈を追加したり

    することができる. ただし, プレゼンテーションの情報が入っているディレクトリ __CodeJacket 下の

    ファイルには注釈の追加もスライドで表示される行の指定もすることができないので注意しなければなら

    ない.

    3.1.1 ページリストパネルから可能な操作

    ページ編集モードでは, ペイン右側のパネル領域にプレゼンテーションモードで表示されるページの番

    号の一覧が表示される. コードを下地としないページは, 灰色の背景に黒い数字の番号で表され, コードを

    下地とするページは青い数字の番号で表される.

    コードを下地としないページにおいては, そのページを構成している HTMLコード片のファイルを開

    いている時に, コードを下地としているページにおいては, その下地となるソースを開いていて, なおか

    つカーソルがプレゼンテーションデータにより表示が指定されている行の 3行前から 10行後までに位置

    する場合にページ番号の背景を赤く, 番号を白く強調表示し, 現在このページにいるということを指し示

    す. 付近にプレゼンテーションで表示される行が複数存在する場合には, 複数の行が強調表示されること

    もある.

    ページ移動

    コードを下地としないページの番号を左クリックすると, そのページを構成する HTMLコード片が表

    示される. ただし, ページ編集モードではテキストの編集ができないので, 内容を編集するには一旦通常

    モードに戻す必要がある. コードを下地とするページの番号を左クリックすると, そのページで表示され

    るテキストエディタの行にカーソルと画面が移動する.

    9

  • 2つのページの交換

    ページの番号の上で右クリックし, 「Swap Pages」を選択する. 選択すると, ページのリスト全体が黄

    色く光る. この状態でそのページと交換したいページの番号をクリックすることにより 2つのページの交

    換が可能である.

    ページの削除

    ページの番号の上で右クリックし, 「Remove Page」を選択すると, 該当ページが削除される. 削除後,

    当該ページ以降のページ番号はすべて 1ずつ減少する.

    タイトルの編集

    ページの番号の上で右クリックし, 「Edit Title」を選択すると, ワークスペースを覆うように 1行の

    入力フォームと「OK」と書かれたボタンと「cancel」と書かれたボタンが表示される. フォームを編集

    し, 「OK」が押すことにより, ページのタイトルが変更される.

    ページのタイトルは, プレゼンテーションモードのヘッダ領域に表示される.

    プレゼンテーションにおけるヘッダ可視性の変更

    プレゼンテーションモードでは, 画面上部にページのタイトルを表示する領域が存在するが, 表示の有

    無をこのパネルから切り替えられる. ページ番号の上で右クリックし「Toggle Header Visivility」を

    選択すると, ヘッダが表示される設定であった場合には表示されない設定に, 表示されない設定であった

    場合には表示される設定になる.

    ヘッダが表示される設定の場合には, パネルの数字左側に黒い傍線が表示される. 表示されない場合に

    はこの線は表示されない.

    コードを下地としないページの末尾への追加

    ページ番号リスト付近の領域を右クリックし,「Append new html page to end」を選択すると, タ

    イトルの編集同様に,  1行の入力フォームと 2つのボタンが表示される. 入力フォームに下地としない

    ページのパス (プロジェクトフォルダ下__CodeJacket/no-code-pages)からの相対パスでページのファ

    イル名を入力して「OK」を入力すると該当するページがスライド末尾に追加される. 該当するファイル

    が存在しない場合には「Not found」と表示され, ページの追加は行われない.

    3.1.2 テキストエディタ領域を右クリックすることにより可能な操作

    テキストエディタ領域を右クリックすることにより可能な操作がいくつかある. これらの操作は, 主に

    エディタ上のカーソル領域に関するものである.

    10

  • スライドの保存

    テキストエディタ領域を右クリックし, 「Save Slides」を選択すると注釈情報とプレゼンテーション

    の情報の保存が行われる. 保存される注釈情報は, ページ編集モードとなってから開かれたすべてのテキ

    ストエディタに付与されている注釈情報である.

    コードへの注釈の追加

    テキストエディタ領域を右クリックし, 「Add new annotation」を選択すると, カーソルが現在存在

    する行に対して注釈の追加を行う. 追加された注釈はドラッグアンドドロップにより左右に動かすことが

    可能である.

    注釈が追加された行は水色で表示される.

    コードを下地とするページの末尾への追加

    テキストエディタ領域を右クリックし, 「Append new code page to end」を選択すると, カーソル

    位置の行を表示するページをスライド末尾に追加することができる.

    コードを下地としないページの末尾への追加

    テキストエディタ領域を右クリックし,「Append new html page to end」を選択すると, コードを下

    地としないページを追加することができる. 操作方法はページリストパネルを右クリックした場合と同様

    である.

    コードを下地とするページの指定位置への追加

    テキストエディタ領域を右クリックし, 「Insert new code page to...」を選択すると, ページリス

    トパネルが橙色に光る. この状態でページリストパネル上の任意のページ番号を選択すると, そのページ

    番号の位置にカーソル位置のコードを下地とするページを追加することが可能である. そのページより後

    のページの番号は 1つずつ増える.

    通常モードに戻る

    テキストエディタ領域を右クリックし, 「Normal mode」を選択すると通常モードに戻る. この時, 保

    存されていない注釈やページ構成は一切保存されないので注意が必要である. この他, 第 2章で述べたよ

    うにステータスバーの状態表示部分をクリックしても通常モードになるが, この場合は注釈・ページ構成

    共に保存される.

    プレゼンテーションモードに切り替える

    テキストエディタ領域を右クリックし,「Presentation mode」を選択するとプレゼンテーションモー

    ドになる. この時, 未保存の注釈やページ構成もそのまま表示される. この他, 第 2章で述べたように, ス

    テータスバーの再生ボタンを押してもプレゼンテーションが開始される.

    11

  • 3.2 プレゼンテーションモードで実行可能な操作

    3.2.1 ページ送り, ページ戻し

    キーボードの左矢印キーを押す, もしくは画面下部の左矢印ボタンを押すと 1つ前のページに戻る. 現

    在が 1ページ目の場合はページ遷移は発生しない.

    同様に, 右矢印キーや, 画面下部の右矢印ボタンを押すと 1つ先のページに進む. 最終ページの場合は

    ページ遷移は発生しない.

    3.2.2 上下方向のスクロール

    ページ編集モードのコードを下地とするページは, 各ファイルのテキストエディタ上で展開される. そ

    のため, 他モードや通常のテキストエディタと同様に上下方向のスクロールがキーボードの上下キー, マ

    ウスホイール, マウスのドラッグなどで行うことが可能である.

    3.2.3 テキストの拡大, 縮小

    Atom本体の機能ではあるが, やはりプレゼンテーションモードは通常のテキストエディタ上で動作す

    るので, Atomの標準機能であるテキストの拡大, 縮小を行うことができる. 初期状態では, 拡大が「Ctrl」

    キーを押しながら「+」キー, 縮小が「Ctrl」キーを押しながら「-」キーに割り当てられている.

    この拡大, 縮小により, ヘッダに表示されている タイトルや, コードを下地としないページの文字や, 注

    釈の文字のサイズも同時に変更される.

    3.2.4 関数やブロックなどの折りたたみ

    こちらも Atom本体の機能ではあるが, インデントの深さが深くなっている行の区間を折りたたむ機能

    がある. 区間を折りたたむとは, 区間の先頭の行のみを表示し, それ以降の区間内の行を非表示とするとい

    うことである.

    折りたたまれる区間は, その行から, その行のインデントの深さ*1を d とした時に次の行以降でインデ

    ントの深さが d 以下となる行 (e行目とする)の 1つ手前までである. また, 開いているプログラミング言

    語の種類によっては, 関数やブロックなどの末尾にある}などの特定のパターン*2を認識し, e 行目までを

    折りたたみの対象とする場合もある.

    折りたたむことができる行については, 行番号の付近にマウスカーソルを載せることにより行番号右側

    に「v」に似た記号が表示され, これをクリックすることによって折りたたむことができる. 折りたたんだ

    後は, 「v」に似た記号が存在した場所に記号「>」が表示され, 折りたたまれた状態から元に戻すことが

    できる.

    *1 ここでは行頭から連続する半角スペースの個数*2 言語別に正規表現で定義されている.

    12

  • 3.2.5 各モードへ戻る

    画面内の任意の領域を右クリックし, 「Normal mode」を選択すると通常モードに, 「Edit mode」を

    選択するとページ編集モードに変更し, プレゼンテーションを終了することができる.

    13

  • 第 4章

    プレゼンテーションに関する情報

    この章では, ソースコードに対する注釈についてと, プレゼンテーション全体の情報を管理するファイ

    ルなどプレゼンテーションを行うにあたって必要なファイルとそれらが持つ情報について述べる.

    4.1 プレゼンテーションに関する情報を格納するディレクトリ

    本パッケージにおいては, プロジェクトフォルダ直下の「__CodeJacket」という名前のディレクトリ

    にプレゼンテーションに必要な情報を格納する. ディレクトリ __CodeJacket の内容を変更することに

    より, 同じソースコード群を対象としながら全く別のプレゼンテーションを再生することも可能である.

    ディレクトリ__CodeJacketが存在しない状態で通常モードからそれ以外のモードに変更しようとする

    と, ディレクトリを作成するかどうかを「OK」「キャンセル」で回答するダイアログが開き, 「OK」を押

    すことで当該ディレクトリが生成され, その後 Atomが再起動される.

    ディレクトリ__CodeJacket下には, 下記の 4種類のファイルが存在する.

    • プレゼンテーションデータ (presentation.json)• 注釈データ (ディレクトリ annotations 下)• 前回スライド保存時のソースコード (ディレクトリ annotations 下)• ソースコードを下地にしないページで表示する HTML を含むテキストファイル (ディレクトリno-code-pages下)

    4.2 プレゼンテーションデータ

    プレゼンテーションデータはプレゼンテーション全体の設定や構成などの情報を保持するもので, ディ

    レクトリ__CodeJacketの直下に presentation.jsonの名前で一つだけ配置する. 注釈同様 JSON形

    式である.

    プレゼンテーションデータは, スライド作成者が直接読み書きできるような構成になっているが, 基本

    的には第 3章で述べたように Atom上での操作によりその変更を行うことができるようになっている.

    Atom の起動時にディレクトリ__CodeJacket の直下に presentation.json が存在しない場合は,

    14

  • ソースコードを下地にしないページを 1ページだけ含むプレゼンテーションを構成するプレゼンテーショ

    ンデータを生成する. これは, ディレクトリ__CodeJacketを新規に生成するために Atomを再起動した

    時にも実行される. また, これと同時にディレクトリ annotationsと no-code-pagesも生成される.

    プレゼンテーションデータはディレクトリに 1つ存在し, そのディレクトリ以下 (再帰的に適用)のソー

    スコードのファイルを用いたプレゼンテーションの全体の流れを保持する.

    プレゼンテーションデータの JSON ファイルは, pages という配列を値に持つプロパティ一つからな

    るオブジェクトからなる. pagesは, 配列であり, 1つ以上のオブジェクトから構成される. このオブジェ

    クト 1つにつき, 1つのページを表す. このオブジェクトは, ソースコードを下地にするページか, HTML

    ファイルの内容を下地にするページかによって内容が大きく異なる. 下記に, プレゼンテーションデータ

    を構成する JSONのプロパティについて記述する.

    4.2.1 プレゼンテーションデータのプロパティ

    • title: ページタイトル. プレゼンテーションモードにおいて, ヘッダ領域に表示する文字列 (詳細は第 5章を参照). 型: string. 必須.

    • showHeader: ヘッダを表示の有無を指定する. trueの場合表示される. 型: boolean. 必須.• backgroundSource: ソースコードを下地に表示するページにおいて, 背景のソースについての情報を指定する. 詳細は後述. 型: Object. HTML ファイルの内容を下地にするページではプロパ

    ティを指定しないか nullを指定する.

    • html: 下地にする HTML ファイルをディレクトリ no_code_pages からの相対パスで記述する.型:string. ソースコードを下地に表示するページの場合はプロパティを指定しないか nullを指

    定する.

    また, プレゼンテーションデータには含まれないが, Atom内部でこのオブジェクトを使用する際には,

    ページ番号 (最初のページが 0)を表す pageNumber と, 読み込んだコードを下地にしないページのファイ

    ルの内容を表す htmlStr の 2つのキーと値が追加される.

    backgroundSource プロパティのオブジェクトについて

    backgroundSourceプロパティには, 背景に表示するソースの情報を記述する. 下記がそのプロパティ

    である.

    • path: 背景に表示するソースコードのファイルのパスを Atomのプロジェクトフォルダからの相対パスで指定する. 型: string. backgroundSourceを指定する場合必須.

    • unique_id: プレゼンテーションの当該ページで表示したい行の unique_id を指定する. 型:string, 指定は任意.

    • topRow: プレゼンテーションの当該ページで表示したい行の番号を指定する. 一番先頭が 0行目である. 型:number, 整数でないものや負の数は無効. backgroundSourceを指定する場合必須.

    なお, unique_idと topRowが同時に存在し, 異なる行を参照する場合には, unique_idが指す行が優先

    される.

    15

  • 4.3 注釈

    注釈は, ソースコードの特定の位置を参照するもので, ソースコードの特定の行に対して文字列による

    説明を行うものである. 注釈は, 次のようなディレクトリに JSON 形式で保存される. この保存された

    ファイルを「注釈データ」と称する.

    (プロジェクトフォルダ)/__CodeJacket/annotations/{XXX}/{YYY}.json

    ただし, {XXX}と{YYY}は, それぞれ下記を意味する.

    • {XXX}: プロジェクトフォルダから当該ソースコードのあるディレクトリへの相対パス• {YYY}: 元のソースコードのファイル名 (拡張子を含む)

    また, 注釈データと同じディレクトリに前回スライド保存時のソースコードを保管する. ファイル名は

    ソースコードの名前 (先ほどの例なら{YYY})そのままである.

    4.3.1 ソースコードが変更された場合における注釈位置の維持

    注釈の位置は, ソースコードが外部で編集された場合に, その位置が変更されることがある. ページ編集

    モードおよびプレゼンテーションモード中はソースコードの編集が不可能なので, 外部のエディタなどの

    プログラムによってソースコードが変更された場合のみを考える.

    ソースコードが外部で変更された後に, 通常モードからページ編集モードもしくはプレゼンテーション

    モードに切り替えると, 前回保存時の行の位置に相当する現在のソースの行を推測し, その行に注釈を移

    す. この行番号の推測には jsdiff[15]というオープンソースのライブラリを用いて版間のパッチを作成し

    た上で行った.

    この行対応関係の推定については第 8章で詳しく述べる.

    4.3.2 インデント情報に基づくコードの擬似的な構文情報の作成

    本パッケージはあらゆるプログラミング言語に対応することを想定しているため特定のプログラミング

    言語に特化したサポートは行わないが, ソースコードのインデント情報を用いた木構造をデータとして持

    つことにより, ある行に付加された注釈がどの範囲まで意味を持ちうるかを表現している.

    行頭から続く半角スペースもしくはタブの個数を「インデントレベル」と称し, このインデントレベル

    に基づく行間の親子関係を定義する.

    4.3.3 インデントレベルによる行間の親子関係

    行間の親子関係は, 次の条件を満たすように決定される. また, 便宜上実際には存在しない「0行目」を

    示す行を仮定し, インデントレベル 0の行の親となるようにする.

    s行目より s + 1行目の方がインデントレベルが大きくなるような任意の行 s行目に対し, s行目

    16

  • の次にインデントレベルが s行目以下となる行を t行目とした時に s + 1行目から t - 1行目ま

    では s行目の子孫である. (ただし, 0 ≤ s < t < n, n行目は最終行)

    4.3.4 注釈のプロパティ

    注釈は, 次のようなプロパティからなるオブジェクトを節とする木構造を表す JSONファイルで保存さ

    れる. 1つの行が 1つのオブジェクトに相当する.

    • node_id: 行を識別する番号-1. 0 の場合, インデントレベルが 0 の行を子に持つ取り扱い上のためのダミー行を示す. それ以外は行番号-1を示す. 例えば, 3行目の場合は 2となる. 型: number.

    必須.

    • unique_id: ランダムな ASCII 文字 15 文字からなる文字列. 注釈の維持時にコピーされ, 元のソースコードの変更に関わらず同じ文字列を保ち続ける. プレゼンテーションデータなど外部

    のファイルからこの値を指定することにより, ソースコードの特定の位置を参照し続ける. 型:

    string. 必須.

    • level: インデントレベル. 行の先頭から続く半角スペースとタブの合計個数. 型: number. 必須.• children: 子になるオブジェクトの配列. 子を持たない場合は要素数 0 の配列を指定する. 型:objectの配列.

    • code: その行の内容. 型: string. 必須.• annotation: 注釈の文字列. 存在しない場合は空の文字列で示す. 型: string. 必須.

    4.4 コードを背景に表示しないページ

    本拡張機能はソースコードを読解することを支援することが主目的である. そのため, 多くの場合ソー

    スコードの上に注釈を描画する形となるが, ソースコードを下地にしないページを作成することができる.

    このページは, 一般のWebサイトなどと同じく HTMLタグを用いて構成するが, body要素の子孫に

    ついてのみを記述する必要があり, その他の要素は記述してはならない. ファイルの保存先は, 下記の通り

    である.

    (プロジェクトフォルダ)/__CodeJacket/no-code-pages/{XXX}

    ただし, {XXX}は当該ファイルのファイル名である. 拡張子は不問である.

    また, 悪意のある JavaScript コードを含む HTML を読み込むことによる意図しない動作を防ぐため,

    使用できる HTMLの要素と属性は限られている. 使用できる要素と属性については,下記の通りである.

    ただし, id属性と class 属性はすべての要素に対して指定可能である.

    • div要素• a要素: href属性は次の JavaScriptの正規表現にマッチする場合のみ利用可能: /^https?:\/\//• h1, h2, h3, h4, h5, h6各要素• ul, ol, li各要素

    17

  • • img要素: alt属性と src属性は利用可能• code要素• p要素• pre要素• table, tbody, tr各要素• th, td要素: 両要素とも colspan属性と rowspan属性は利用可能• del, rm, strong, mark各要素• br要素• dd, dl, dt各要素• blockquote要素• i, b, s各要素

    例えば, スライドのタイトル (見出しを表す要素 h1 を使用) のみを表示したい場合の HTML を含む

    ファイルは下記のみを記述すればよい.スタイリングは, パッケージ側の CSS(less)により行われる.

    タイトル

    また, このままではヘッダが表示されてしまうため, 表示させないようにするにはプレゼンテーション

    データ側で displayHeader の値を falseに指定する必要がある.

    18

  • 第 5章

    ページ編集モードとスライドのページ構成方法

    この章では, 提案手法で使用する Atomのパッケージにより提供されるモードの内, 注釈の挿入・削除,

    および注釈内容の編集などの機能を提供する「ページ編集モード」について, およびプレゼンテーション

    データを編集することにより行うことができるスライドのページ構成の方法について述べる.

    ページ編集モード中では, 開いているテキスト自体の変更は行えない. テキストの変更を行う場合には,

    通常モードに切り替える必要がある.

    5.1 注釈に関連する操作

    5.1.1 注釈の挿入

    ユーザは, 注釈を挿入したい行にカーソルを合わせ, 右クリックし, 表紙されたメニューから

    「Add new annotation」を選択する (図 5.1) ことによって, 当該行に対してテキストボックス注釈

    を挿入することができる.

    この操作の後, 当該行の画面左側にテキストボックスが表示される (図 5.2)ので, そのテキストボック

    スに対して文字列を入力することにより注釈の内容を編集することができる. 図 5.3は, 複数の注釈を生

    成して内容を編集した例である.

    5.1.2 注釈の編集, 移動

    注釈は, マウスのドラッグアンドドロップにより位置を移動することができるが, プレゼンテーション

    モードで表示される位置には反映されない.(プレゼンテーションモードの注釈もマウスで動かすことがで

    きる.)

    5.1.3 注釈の削除

    テキストボックスの内容を空にしてスライドを保存し, 注釈ファイルを再度ロードさせる (例えば, ペー

    ジ編集モードから通常モードに戻した後, 再度ページ編集モードに戻したり, Atomを再起動した後にペー

    19

  • 図 5.1 注釈を挿入したい位置で右クリックして注釈を挿入する

    図 5.2 空の注釈が生成された状態

    20

  • 図 5.3 注釈を複数生成してテキストボックスの内容を編集した例

    ジ編集モードに戻したりさせる)ことにより注釈の削除が可能である.

    5.1.4 注釈の保存

    ページ編集モード中にエディタの画面上を右クリックし, 「Save Slides」を選択することにより注釈

    を保存することが可能である. なお, これにより, ページ編集モードになってから開かれたすべてのソース

    コードに対する注釈が上書きされる.

    注釈の保存を行わずに Atomを終了したり, 通常編集モードに戻った場合には変更された注釈は保存さ

    れずに破棄される.

    5.2 スライドの構成方法

    5.2.1 コードを下地とするページの追加

    エディタを右クリックして追加する方法

    第 3章で述べたとおり, エディタ領域を右クリックしてページを追加することができる. 末尾でない任

    意のページに追加する場合には, 右クリックからメニューの選択後, 画面右側のページリストパネルから

    挿入したいページの位置を選択すればよい.

    ページを削除する時には, ページリストパネルから削除したいページを右クリックして削除する.

    21

  • プレゼンテーションデータを直接編集する方法

    第 4章で述べたとおり, スライドはプレゼンテーションデータによって構成される. プロパティ pages

    に対する配列の要素を追加することでページの追加が可能である.

    なお, プレゼンテーションデータの編集後, 変更を反映させるためには Atomの再起動もしくは, 通常

    モードにしてから再度ページ編集モードが必要である.

    コードを下地とするページは, プロパティ htmlを含まず, backgroundSourceを含むオブジェクトで

    表現される. 下記はコードを下地とするページの設定例である.

    {

    "title": "ロード処理",

    "showHeader": true,

    "backgroundSource": {

    "path": "lib/presentation/Presentation.js",

    "topRow": 34

    }

    }

    プロパティ title にはヘッダ (第 5章で解説)に表示する文字列を指定する.

    プロパティ showHeader はヘッダの表示の有無について指定する. true が与えられた場合は表

    示,‘false‘が与えられた場合は非表示となる.

    プロパティ backgroundSource には オブジェクトを指定する. このオブジェクトの プロパティ path

    には下地として表示するソースのファイル名をプロジェクトフォルダからの相対パスを文字列として与

    える. プロパティ topRow には, そのページで表示するコードの最も上の行の行番号から 1を引いたもの

    を指定する. 上記の例では, このページは Presentation.jsの 33行目を最上部に表示するページとな

    る. この数値は, ソースコードが編集された時に動的に変更されないが, プレゼンテーションデータの保存

    時に, 行の unique_idを backgroundSourceオブジェクトに持つことにより, ソース変更後もその位置

    を保ち続ける. (ただし, topRowの値は変更されない. topRowと unique_idが同時に存在する場合には

    unique_idが優先される)

    第 2章でも述べたが, プレゼンテーションデータは ディレクトリ__CodeJacket 下に存在する. ページ

    編集モードでは, プレゼンテーションデータを元に, 各ページで表示されるソースコードの行頭部分を強

    調し, スライドで表示されるページの番号をその行付近にエディタの画面上に描画する (図 5.4).

    5.2.2 コードを下地としないページの追加

    予め, ディレクトリ __CodeJacket/no-code-page にファイルを準備していることを前提とする.

    22

  • 図 5.4 プレゼンテーションモードで表示されるコードの位置のページ編集モードでの表示

    Atom上からから追加する方法

    テキストエディタ上の右クリックメニューもしくはページリストパネルの右クリックから, コードを下

    地にしないページの追加が可能である. 選択後, ファイル名を入力するが, 既に存在しているファイルでな

    ければここで追加することはできない. 任意のページに挿入するには, 末尾に追加した後ページの交換を

    行うことで可能である.

    プレゼンテーションデータを直接編集する方法

    コードを下地としないページは, プロパティ html が指定されていて backgroundSource が指定され

    ていないオブジェクトで表現される. title, showHeader各プロパティについてはコードを下地とする

    ページと同様である.

    プロパティ html には, 表示する内容の HTML が記述されているパスを ディレクトリ

    __CodeJacket/no-code-pagesからの相対パスで指定する. ファイルの拡張子は不問である.

    23

  • 第 6章

    プレゼンテーションモード

    この章では, 提案手法で使用する Atomのパッケージにより提供されるモードの内, 「ページ編集モー

    ド」で作成されたプレゼンテーションを実際に再生する「プレゼンテーションモード」について述べる.

    6.1 概要

    ページ編集モードからプレゼンテーションモードに変更すると, 画面が全画面表示となり, プレゼン

    テーションの最初のページが表示される. プレゼンテーションのページは, 現在 Atomによって開かれて

    いるディレクトリのプレゼンテーションデータのファイルによって決定される.

    6.2 描画

    プレゼンテーションの画面は, Atomの画面上に描画されるため, HTMLにより表現される.

    先述の通り, プレゼンテーションモードで表示される画面は, コードを下地に描画するページと無地の

    上に文字などの説明を描画するページがある. 前者は, Atomを全画面表示した上でフォントサイズを拡

    大, テキストエディタ上に注釈を描画することで実現, 後者はテキストエディタ上に同じ大きさの div要

    素を描画し, その下にスライド作成者によって書かれた HTML を描画することによって実現している.

    また, プレゼンテーションモードに切り替わる際に, 表示されているパネルとステータスバーはすべて非

    表示となる. プレゼンテーションモードから他モードに戻る際にパネルとステータスバーの表示状況は,

    プレゼンテーションモード開始前の状態に戻る.

    6.2.1 画面

    現在開かれているページが, コードを下地にコードの説明などを描画するページの場合は, エディタの

    画面の文字の大きさを大きくした画面を表示し, その上から説明を描画する.

    通常のプレゼンテーションのページを描画する場合は, エディタの上に HTMLの要素を上から覆うよ

    うに描画し, エディタの画面を隠した上でプレゼンテーションのページを描画する.

    いずれの場合も, ページの上部には画面上部から画面高さの 15%の位置までの位置まで, ページのタイ

    トルの文字列を内側に含む矩形が描画される. この矩形領域をヘッダと言い, この表示についてはプレゼ

    24

  • ンテーションモードの実行中に表示の有無を切り替えることができる.

    同様に, 画面の下 10%の高さの矩形領域は, 現在開いているソースのファイル名やページ番号が表示さ

    れるようになっている.この矩形領域はフッタと呼び,他に 注釈, ヘッダの表示・非表示切り替えやページ

    送りを行うボタンが表示される. 通常のページ送りでない特殊な移動 (後述)を行った場合には「戻る」ボ

    タンのみを表示する.

    図 6.1 にプレゼンテーションモードの画面の一例を示す. このページは, ヘッダが表示されるソース

    コードを下地としたページである. また, 図 6.2にソースコードを下地としないページの例を示す. この

    ページは, プレゼンテーションデータの html属性でしているファイルを次のようにしている.

    時間の計測

    種類時間 (ms)

    A0.750

    B0.935

    C1.010

    D3.141

    E2.718

    図 6.1 プレゼンテーションモード (下地にソースコードを表示するページ)

    25

  • 図 6.2 プレゼンテーションモード (下地にソースコードを表示しないページ)

    6.2.2 注釈

    表示されているコードには, 画面編集モードにより追加された注釈が描画される (プレゼンテーション

    モードで描画される種類のもののみ). 表示されている注釈は, 発表者がマウスのドラッグアンドドロップ

    の操作により自由に移動することができる. ただし, テキストボックスの内容の編集はできない.

    6.2.3 上下のスクロールとフォントサイズ変更

    プレゼンテーションモードでは, 発表者は自由に下地のソースコードのスクロールとフォントサイズの

    変更を行うことができる.

    6.3 ページ遷移

    フッタにある「戻る」ボタンを押すと 1つ前のページへ戻り, 「進む」ボタンを押すと 1つ次のページ

    へ進む. この他, キーボードの「←」キー (戻る),「→」キー (進む)にも対応する.

    26

  • 第 7章

    実装

    この章では, 提案手法の実装方法について述べる.

    7.1 パッケージの構成

    本パッケージの内, 動作に関わる部分は, 下記のディレクトリによって構成されている.

    • ディレクトリ keymaps: コマンドとキーに関する定義を記したファイル.• ディレクトリ lib: プログラム本体• ディレクトリ node_modules: 外部依存のファイル群• ディレクトリ styles: 画面の装飾を行うスタイルシートファイル群

    以下では, ディレクトリ libの内容について述べる.

    ディレクトリ lib下の多くのプログラムは, 外部依存ライブラリの React[17]を使用を容易にするため

    に JSX[18]と呼ばれる, JavaScriptの規格 ECMAScript 2015[19]の拡張構文を用いて記述した. 実際に

    実行可能な JavaScriptへは, Atom側から各種変換用のプログラムを呼び出して変換される.

    7.2 lib/codejacket.js

    lib/codejacket.jsには, 1つの大きな JavaScriptのオブジェクトがあり, 当パッケージが呼びださ

    れた時にこのオブジェクトの メソッド activateが呼び出されるようになっている.

    このオブジェクトの主な役割は次の通りである.

    • 主要インスタンスの組み立て• Atomへのコマンド登録• モードの管理• 注釈の管理・描画• 注釈ファイルの読み込み, 書き込み

    メソッド activateにおいては, 使用する各種インスタンスの組み立てや, Atomへのコマンドの登録

    27

  • を行っている. Atomのコマンド (commands)は, 指定した操作をキー入力や右クリック時のメニューな

    どから呼び出すために設定が必要なものである.

    7.2.1 モードの管理

    このオブジェクトは, 現在のモードをプロパティ state に持つ. 通常モードの場合, その値

    は"cj-normal", ページ編集モードの場合は "cj-edit", プレゼンテーションモードの場合は

    "cj-presentation" である. なお, 実際のモード変更時はそれぞれ各メソッド startNormalMode,

    startEditMode, startPresentationMode を呼び出す. これらのメソッドを呼び出すことにより,

    stateの値の変更だけではなく, 前のモードから次のモードへ移り変わるために必要な処理を行うことが

    できる.

    例えば, 通常モードからプレゼンテーションモードに遷移する場合, 次のような手順を取る.

    1. ディレクトリ__CodeJacket の有無の確認. ない場合は作成して Atomを再起動.

    2. 現在開いている全てのエディタを保存 (それまでに保存されていなかった場合は, 保存するか尋ね

    る).

    3. 現在開いている全てのエディタに対する注釈ファイルを開く. 過去に保存されているものがあれば

    注釈をコピー (後述).

    4. プレゼンテーションデータのロード (後述, クラス Presentationのインスタンスの生成, ロード

    を指示).

    5. 画面上で注釈を表すオブジェクト (後述, クラス FloatingWindow)のインスタンス生成.

    6. 定期的 (4ミリ秒)ごとに注釈の位置補正を行う関数呼び出しの開始.

    7. プレゼンテーションモードのヘッダ, フッタの表示.

    8. フォントサイズを 30pxに変更.

    9. ページを 1ページ目にセットする.

    10. 開かれている上下左右のパネルの表示状況を記憶する (通常モードやページ編集モードになったと

    きに復元するため).

    11. 開かれている上下左右のパネルを隠す.

    12. 画面をフルスクリーンにする.

    7.2.2 注釈の管理・描画

    Atomのテキストエディタを表す TextEditorクラスには, それを一意に識別するための整数値のプロ

    パティ id が存在する. これを利用し, エディタごとに描画されている注釈を管理している.

    このオブジェクトには, 注釈の管理に関連する次のような配列 (連想配列として使用)が存在する.

    • trees: キーをエディタの ID, 値を注釈データの根 (左から続くインデントの個数が 0のオブジェクトを子に持つダミーの行ノード) とする連想配列

    • annotationRenderState: キーをエディタの ID, 値を true(注釈設定済), undefined(未設定) と

    28

  • する連想配列

    • annotationObjects: キーをエディタの ID, 値を注釈の枠 (クラス FloatingWindowのインスタンス)への参照とする連想配列

    • pageVisualizers: キーをエディタの ID, 値をページ番号表示用の文字列を含むオブジェクト (クラス PageVisualizerのインスタンス)への参照とする連想配列

    • annotationMarkers: キーをエディタの ID, 値を注釈描画のためのマーカー (Marker)*1への参照とする連想配列

    メソッド renderCjAnnotations は, 各テキストエディタに対して annotationObjects および

    pageVisualizers に必要な注釈枠やページ番号表示文字列を設定する. また, それらを描画すべき行に

    マーカーを設定する.

    メソッド setTimerToJustifyAllAnnotationsPosition は, マーカーの画面内の表示座標をもとに,

    それら注釈枠などの描画座標を決定して描画する関数を 4ミリ秒ごとに呼び出すように設定する. これは

    エディタのスクロールによって, 注釈枠などの描画座標が変更されるのを防ぐためである. 注釈枠なども

    HTMLにおける DOM(Document Object Model)の要素からなるので, マーカーの画面座標が求まれば

    その付近に注釈枠などを描画することができる.

    メソッド destroyAllTreesAndAnnotations は表示中の全エディタにある釈枠やページ番号表示文

    字列, マーカーを削除し, annotationObjectsや pageVisualizersからも削除する. このメソッドは,

    主にページ編集モードやプレゼンテーションから通常モードに戻る時に呼ばれる. エディタが閉じられた

    後にも呼ばれるが, エディタが閉じられた場合には, 既に該当の DOM要素が消滅しているため, 参照の削

    除のみを行うようになっている.

    注釈ファイルの読み込み, 書き込み

    メソッド initTreeは, エディタ中のテキストの内容を読み, 注釈データの木構造を生成する. このメ

    ソッドは, 主に通常モードからページ編集モードやプレゼンテーションに遷移された時に呼び出され, 過

    去の注釈データが存在する場合には, 過去の注釈データとこれにより生成した注釈データを比較し, 注釈

    を新しい木にコピーし, 存在しない場合には新しく生成されたものをそのまま使用する.

    注釈のコピーについては, TreeDiffUtil クラスが行っているため, 後述する.

    メソッド saveSlide は, 編集されたスライドのデータ (編集モードに入ってから開かれた全ての注釈

    データ, それに対応する保存時現在のテキストの内容, プレゼンテーションデータ) を保存する. それぞれ

    のファイルは保存する順序は問わないため,保存作業を並列処理で進める. 保存が完了すると, saved!と

    書かれたダイアログが表示される.

    7.3 lib/presentation 下のファイル

    ディレクトリ lib/presentation/下には, 下記のファイルが存在する.

    • Presentation.js: プレゼンテーション本体

    *1 編集中のエディタ内の任意の連続する範囲を表す Atom側のクラス

    29

  • • PresentationHeader.js: プレゼンテーションモードのヘッダ部の描画内容を決めるクラス• PresentationMain.js: コードを下地としないページにおいてコードを覆い隠すように上に描画される内容を決めるクラス

    • PresentationUtil.js: プレゼンテーションデータに関する各種関数群からなるクラス• PageSelector.coffee: ページリストパネルの表示内容の定義クラス

    ここでは,特に重要な機能を持つ Presentation.js, PresentationMain.js, PageSelector.coffee

    について詳しく説明する.

    7.3.1 Presentation.js

    lib/presentation/Presentation.js はひとつのクラス Presentation から成る. 主にプレゼン

    テーションデータの管理とプレゼンテーションモードにおける各種描画を担当する. (実際には, 内部的

    な呼び出しによって, ヘッダの描画は PresentationHeader.jsが担当している. コードを下地としない

    ページにおける HTMLの描画は PresentationMain.jsが行っている.)

    このクラスは, パッケージ起動時にインスタンスが生成され, lib/codejacket.js の大きなオブジェ

    クトにおけるプロパティ presentationにセットされるが, この時点ではプレゼンテーションデータを保

    持していない.

    lib/codejacket.jsによって Presentationクラスのインスタンスのメソッド loadが呼び出される

    時に, プレゼンテーションデータを読み込む.

    読み込んだプレゼンテーションデータは, presentation.json から読み取ったほぼそのままのオブ

    ジェクトの形で保持し続けるが, 内部的なアクセスのしやすさを考慮し, 配列 pages の添字を記憶する

    pageNumber というプロパティと, コードを下地にしないページで表示する HTMLを各ファイルから読

    んだ内容の htmlStr というプロパティを全体のロードと合わせて設定する. なお, pageNumber はペー

    ジの順序が変わった時点で振り直され, htmlStr は, コードを下地にしないページの新たに設定したり,

    ファイルの参照先を変えたりした時点で必要な部分だけ再度ロードされる.

    メソッド load とは逆に, lib/codejacket.js によって通常モードに戻る時には, unload というメ

    ソッドが呼びだされ, プレゼンテーションデータが廃棄される.

    7.3.2 PageSelector.coffee

    編集モード時に右側のパネルに表示されるページリストパネルは, 「PageSelector.coffee」により

    定義される. このファイルも 1つのクラス PageSelectorからなっている. このクラスは, Atom側で提

    供されるクラス Viewを継承しており, そのままパネル上で描画できるようになっている. その関係上, こ

    のファイルは記述のしやすさなどの観点から JavaScriptにコンパイルされる言語である CoffeeScript

    を使用して記述している*2.

    *2 元々, Atom のほとんどの機能は CoffeeScript で記述されていることもあり, Atom 側で自動で CoffeeScript のコードはJavaScriptに変換され実行される.

    30

  • PageSelector.coffee と Presentation.js

    PageSelector は, ページの情報を受けてそのページ番号のスタイルを変更するための情報を更新し

    なければならないため, クラス Presentation のインスタンス変数 pageSelector に参照を持つ. ただ

    し, lib/codejacket.js から表示・非表示の変更の要求をすることもあるため, クラス Presentation

    のインスタンスを経由して PageSelector のインスタンスを表示切り替えを行うためのメソッド

    showPageSelector(ページリストパネルを表示), hidePageSelector(ページリストパネルを非表示)が

    クラス Presentationに実装されている.

    ページリストパネルも, lib/codejacket.js における注釈位置補正と同様に, 状態の変更を常に更新

    しなければならないため, Presentationクラスのメソッド updatePageSelectorを 4ミリ秒ごとに呼

    び出すことにより, ページリストパネルを最新の状態に保つ. この監視は Presentationクラスのメソッ

    ド startWarchPageSelectorにより開始され, stopWatchPageSelectorにより終了する.

    7.3.3 PresentationMain.js

    コードを下地にしないページでは, コードを見せないためにコードの上からコードを覆うように白い長

    方形を描画する. この白い長方形は HTMLの div要素で構成されている. プレゼンテーションデータと

    no-code-pagesで定義した HTMLコード片を組み立て, この div要素の子要素とすることで目的の表

    示を実現する.

    この div要素の描画を担っているのが PresentationMain.jsのクラス PresentationMain である.

    また, 使用してよい HTMLの要素, 属性の一覧もこのクラス内で定義して, 組み立てる際に利用している.

    7.4 lib/annotations 下のファイル

    ディレクトリ lib/annotations 下には, lib/codejacket.js の 注釈枠描画の機能によって描画さ

    れうる DOM 要素を提供する FloatingWindow.js (注釈枠描画) と SlidePageVisualizer.js (ペー

    ジ番号の指定位置描画) の 2つのファイルがある.

    この 2つのファイルの役割は, 先に述べたように, 注釈枠等の描画である. 外部から画面内の Y座標を

    与えることにより, 描画する行を決めることができる. 具体的には, マーカーの付近にこれら注釈枠等を配

    置することが目的である.

    7.4.1 FloatingWindow.js

    FloatingWindow.js の枠は, このファイル内のクラス FloatingFrameによって管理されている. 枠

    内でマウスのボタンが押された時点から, マウスが枠内から外れるかマウスのボタンが押されていない状

    態になるまでマウスが動くたびに, 押された時点の画面内のマウス座標から, 現在の画面内のマウス座標

    の差分を計算し, 初期に設定された style属性で決められた座標値に加算することにより, ドラッグアン

    ドドロップでの枠の移動をサポートする.

    FloatingFrame.js のテキストボックスは, クラス FloatingWindow 内からクラス AnnotationBox

    31

  • を使用することで実現している. クラス AnnotationBox は textarea要素を管理し, 編集モードもしく

    はプレゼンテーションモードにおいて画面に表示されている注釈の値を保持する. しかし, この textarea

    要素は, ただ設置しただけでは入力ができない. これは Atom側によりキーイベントが上書きされている

    ためであり, これを防ぐために, textarea要素に対し, イベントの上位伝播を防ぐようにした.

    具体的には, keydown, keyup, keypress, click の各イベントが発生した時に発生したイベントに対

    して stopPropagation関数を呼び出すことでイベント伝播を防止している. clickに対しても行った理

    由は, これの上位伝播を許してしまうことにより, FloatingFrameの注釈枠移動としてクリックが認識さ

    れてしまうことを防止する目的がある.

    7.5 lib/indent-tree 下のファイル

    ディレクトリ lib/indent-tree 下には, 注釈ファイルの生成および注釈ファイルの比較のための各種

    機能を含むファイルが存在する.

    lib/indent-tree/TreeDiffUtil.jsにおいては, ソースコードが外部により変更された時における

    変更差分より注釈の対応関係を求める関連の操作が記述されている. 詳しくは第 8章で解説する.

    lib/indent-tree/IndentTreeGenerator.jsには, 第 5章で述べた注釈の生成に使用する注釈デー

    タのインデント構造の JSON化を行うクラス IndentTreeGeneratorが定義されている.

    32

  • 第 8章

    ソースコードが外部により変更された場合の注釈の移動

    この章では, ソースコードが外部のテキストエディタにより書き換えられたり, ソースコードに変更が

    あった時に注釈の行がどのように変更されるかについて述べる.

    下記については, lib/indent-tree/TreeDiffUtil のファイル内の関数について述べる

    大まかに, 注釈の移動は次のように行われる.

    • 関数 getDiffPatch による パッチの取得• 関数 generateDiffFromPatch によるコード中全範囲の行対応状況取得• 関数 getMatches による 対応行, 削除行, 追加行の取得• 関数 mergeTree による対応関係に基づく注釈の移動

    8.1 前提

    文字列に対する「編集距離」とは 2つの文字列が与えられた時に, 片方の文字列に対して操作 (文字の

    追加,削除,置換)を行うことでもう片方の文字列に必要な最小の操作回数のことを言う.

    この章で述べる処理では, 外部ライブラリの jsdiff[15]の複数の関数を使用し, ファイルの差分を調べた

    り, 2つの文字列の違いを調べたりするが, そのために行や単語に対する編集処理が使用される. これらの

    編集距離は, 行や単語を 1つの文字とみなし, 相異なる二つの行や単語がそれぞれ別の文字として処理し

    て求られる.

    jsdiffの機能は, 論文 [16]のアルゴリズムを元に実装されている.

    8.2 パッチの取得

    関数 getDiffPatch は変更前のファイルのパス, 変更前の文字列, 変更後のファイルのパス, 変更後の

    文字列を受け取り, 外部ライブラリの jsdiff[15] の関数 structedPatchによって 変更前と現在のファイ

    ルの間の変更差分を求め, 下記の形式で返す.

    33

  • {

    content: ,

    oldRowNum: 変更前のファイルの行数,

    newRowNum: 変更後のファイルの行数

    }

    関数 structedPatch で得られるオブジェクトは, 本来旧ソースを新ソースへ変更する差分をまとめ

    た「パッチ」(patch)と呼ばれるデータ構造を JavaScriptのオブジェクトで表現したものである. パッチ

    は, ソフトウェアのソースコードの変更差分を適用したり取得したりするために広く世の中で使用されて

    いる.

    8.2.1 structedPatchの構造

    関数 structuredPatch によって得られるオブジェクトの内, プロパティ hunks のみを使用する.

    hunks はオブジェクトの配列であり, 下記のような構造をしている. 以下, hunks の一つの要素を hunk

    と呼ぶ.

    {

    hunks: [{

    oldStart: , oldLines: ,

    newStart: , newLines: ,

    lines: [ ],

    },{

    ...

    }, {

    ...

    }]

    }

    hunk は, 旧ソースを新ソースに変更する際の変更箇所の行周辺を表したものである. oldStart は

    旧ソースの開始行, oldLines は旧ソース側における hunk の行数, newStart は新ソースの開始行,

    newLinesは新ソース側における hunkの行数である.

    lines には, 旧ソースを新ソースに変更する際の行の追加, 削除, 変更なしを示す文字列の配列が与え

    られる. 旧ソースに対して, oldSart 行目から lines.length 要素分の差分の情報を順次適用すると新

    ソースの newStart 行目から newStart + newLines - 1 行目までのものと一致する.

    ここで, linesの処理とは, 次のようなものである. linesの各要素を lines[i] とする.

    • lines[i]の最初の文字が ’+’ の場合, 旧ソースのこれまでに処理した行と次の行の間に lines各要素の 2文字目以降からなる文字列を挿入する.

    • 文字が’-’ の場合, 次の行 (内容は lines各要素 2文字目以降の文字列)を削除する.

    34

  • • 文字が’ ’(半角スペース)の場合は何もせずに次の行へ進む.

    以降, この line[i]の最初の文字のことを, その hunkの line[i]における符号と呼ぶ.

    8.3 ファイル全体の行対応情報の取得

    関数 getDiffPatch で受け取ったファイルの差分情報をもとに, 次は関数 generateDiffFromPatch

    により, ファイル全体の行対応状況を調べる.

    この関数では, 実際に対応状況を求める処理の前に, jsdiffの差分情報における行番号は 1から開始し

    ているため, oldStart と newStart からそれぞれ 1 を減らし, Atom や当該パッケージの内部で表現し

    ている行番号 0からの開始に変更する. また, 順番に処理が可能なように, hunksにおける hunkの並び

    を, oldStartの昇順に整列する. ただし, oldStartが同じ要素については, newStartの昇順とする.

    以下, 次のようにして, 旧ソースと新ソースの行番号の対応を求める.

    8.3.1 旧ソースと新ソースの行番号対応の求め方

    変数 oldRow, newRowの初期値を 0とする. それぞれのソースの行数を超えた時点で終了する. 旧ソー

    スと新ソースの対応の記録を時系列順に取る. 記録時の oldRow, newRow の値と記録時に与えられた符

    号, パッチに記述されたコード (符号除く) の四つ組を記録する.

    hunk内の処理

    1. 処理中の hunk の現在の line の符号を sign とする.

    2. oldRow と newRow の対応を 符号 sign で記録.

    3. sign が空白なら, oldRow と newRow をそれぞれ 1ずつ増やす.

    4. sign が ’-’なら, hunkの次の行の符号が ’+’ でなければ oldRow を 1増やす.

    5. sign が ’+’なら, newRow を 1増やす. さらに, hunkの前の行の符号が ’-’ であれば, oldRow を 1

    増やす.

    6. 処理中の hunk の line を次に進める. 次の lineがなければ 現在の処理中の hunkを処理済とし,

    hunk外の処理の最初に移る.

    hunk外の処理

    1. oldRow と newRow の対応を 符号空白で記録

    2. oldRow と newRow をそれぞれ 1ずつ増やす

    3. oldRow が 未処理の中で最も oldStart が最小で, その中でも newStart が最小の hunk の

    oldStartと同じなら, その hunkの処理を開始する (hunk 内の処理の最初へ移る).

    この処理が終わった時点での記録結果を対応結果とする. 最初に求めたパッチの定義より, 符号が空白

    の oldRowと newRowは, 「ソースの変化によって変化しなかった行」と言え, 両者の行番号は対応する.

    それ以外の行については, 次に呼び出す関数の getMatches により対応関係を導く.

    35

  • 8.4 新ソースから旧ソースのマッチング

    関数 getMatchesでは, 先ほど求めた行の対応関係を次の 4種に分類する.

    1. 符号が空白の対応関係: この対応関係は自明である.

    2. 符号が +である対応関係で, この対応関係が含まれる 1つ以上連続する +の対応関係に隣接する-

    の対応関係がないもの: この対応関係にあるものは新ソースから新たに加わった行と判定する.

    3. 符号が-である対応関係で, この対応関係が含まれる 1つ以上連続する-の対応関係に隣接する +の

    対応関係がないもの: この対応関係にあるものは新ソースにおいて削除された行と判定する.

    4. 符号が +または-の対応関係で, その対応関係が前後で +の場合は-の, -の場合には +の対応関係

    が隣接するもの: 対応関係が自明ではないので, 詳細に調べる.

    ただし, 2, 3番目のケースに関わらず, 1つ以上連続する符号が +の対応関係と, 1つ以上連続する符号が-

    の対応関係が 1つずつしか存在しない場合には, 4番目のケースと同様にそれぞれについて詳細に調べる.

    4番目のケースは, 連続する複数行のコードが変更された場合などに多く発生する. このような場合に

    は, 変更後のコードの行から見て編集距離�