Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【AngularJS】AngularJS1.6の$httpでは、success()/error()の代わりにthen()/catch()を使う

少し嵌ったのでメモ。
AngularJS1.6の$httpでは、HTTPレスポンスが返ってきたときに走る処理を記述するsuccess()error()が非推奨、もとい使用不可な状態となっていました。

Due to b54a39, $http's deprecated custom callback methods - success() and error() - have been removed. You can use the standard > then()/catch() promise methods instead, but note that the method signatures and return values are different. success(fn) can be replaced with then(fn), and error(fn) can be replaced with either then(null, fn) or catch(fn).

then()とcatch()で置き換えられると書かれています。
どうやら$http()の返戻値自体、promiseライクなオブジェクトに置き換えられた模様。

const url = 'https://hoge.com';

const success = function(response){
  // on success
};

const error = function(response){
  // on error
};

/*
 * before
 */

// syntax error
$http({
  method: 'GET',
  url: url
})
.success(success)
.error(error);

/*
 * before
 */

// OK!
$http({
  method: 'GET',
  url: url
})
.then(success)
.catch(error);

// またはthenの第一引数にsuccess,第二引数にerror時の処理を渡す
$http({
  method: 'GET',
  url: url
})
.then(success)
.catch(error);

AngularJSとしてはメジャーアップデートなのかもしれませんが、単純な非推奨ではなく使用自体できなくなるのは厄介ですね。 (Swiftほどではありませんが)

【SQL】定数列を出力する

SELECT文でRDBMSに対する問い合わせを行う際、結果テーブルの各行に対して定数列を設けることができます。
あまり使い所はないかもしれませんが、知らなかったのでメモ。

-------------------------
-- DBMSはPostgreSQL --
-------------------------

-- テーブル
 select * from shohin;
 shohin_id |   shohin_mei   | shohin_bunrui | hanbai_tanka | shiire_tanka |  torokubi  
-----------+----------------+---------------+--------------+--------------+------------
 0001      | Tシャツ        | 衣服          |         1000 |          500 | 2009-09-20
 0002      | 穴あけパンチ   | 事務用品      |          500 |          320 | 2009-09-11
 0003      | カッターシャツ | 衣服          |         4000 |         2800 | 
 0004      | 包丁           | キッチン用品  |         3000 |         2800 | 2009-09-20
 0005      | 圧力鍋         | キッチン用品  |         6800 |         5000 | 2009-01-15
 0006      | フォーク       | キッチン用品  |          500 |              | 2009-09-20
 0007      | おろしがね     | キッチン用品  |          880 |          790 | 2008-04-28
 0008      | ボールペン     | 事務用品      |          100 |              | 2009-11-11
(8 rows)

-- 文字列、数値、日付の定数列を挿入できる
# select '商品' as mojiretsu, 38 as kazu, '2009-02-24' as hizuke , shohin_id, shohin_mei from shohin;
 mojiretsu | kazu |   hizuke   | shohin_id |   shohin_mei   
-----------+------+------------+-----------+----------------
 商品      |   38 | 2009-02-24 | 0001      | Tシャツ
 商品      |   38 | 2009-02-24 | 0002      | 穴あけパンチ
 商品      |   38 | 2009-02-24 | 0003      | カッターシャツ
 商品      |   38 | 2009-02-24 | 0004      | 包丁
 商品      |   38 | 2009-02-24 | 0005      | 圧力鍋
 商品      |   38 | 2009-02-24 | 0006      | フォーク
 商品      |   38 | 2009-02-24 | 0007      | おろしがね
 商品      |   38 | 2009-02-24 | 0008      | ボールペン
(8 rows)

-- AS 句なしだと、デフォルトのカラム名が挿入される
shop=# select '商品' , 38, '2009-02-24' , shohin_id, shohin_mei from shohin;
 ?column? | ?column? |  ?column?  | shohin_id |   shohin_mei   
----------+----------+------------+-----------+----------------
 商品     |       38 | 2009-02-24 | 0001      | Tシャツ
 商品     |       38 | 2009-02-24 | 0002      | 穴あけパンチ
 商品     |       38 | 2009-02-24 | 0003      | カッターシャツ
 商品     |       38 | 2009-02-24 | 0004      | 包丁
 商品     |       38 | 2009-02-24 | 0005      | 圧力鍋
 商品     |       38 | 2009-02-24 | 0006      | フォーク
 商品     |       38 | 2009-02-24 | 0007      | おろしがね
 商品     |       38 | 2009-02-24 | 0008      | ボールペン
(8 rows)

参考文献

第2版 ゼロからはじめるデータベース操作

【git】git blameでファイルの修正履歴を追う

git blame

git blameコマンドにgitリポジトリで管理されたファイルのパスを渡すことで、
そのファイルをいつ、誰が編集したのか見ることができます。

GitHubなどのリモートリポジトリサービスでも「誰がやったか」の情報を見ることができますが、
ローカルのCLIで手軽に編集者を見たい場合に便利なコマンドです。

# ファイルの中身
$ cat hoge.txt 
hoge
fuga
piyo

# ファイル編集履歴
# リビジョンのハッシュ値、編集者、編集日時、編集文言が記録されている
$ git blame hoge.txt
ebc2e989 (hoge 2018-03-02 00:02:44 +0900 1) hoge
7ddeaaf0 (hoge 2018-03-02 22:54:08 +0900 2) fuga
e9c8aed2 (hoge 2018-03-04 23:06:46 +0900 3) piyo

# 空白無視
$ git blame hoge.txt -w

【git】git reflogでgitの履歴に対する過去の操作を管理する

git reflog

git reflogは過去に更新したブランチの履歴などを参照ログとして閲覧できる機能です。
下の例では、あるリポジトリに対して淡々とコミットした履歴を一覧表示しています。

$ git reflog
# commitやresetした履歴
80634e3 HEAD@{0}: reset: moving to HEAD~
d3f2ad5 HEAD@{0}: commit: add .gitignore
80634e3 HEAD@{1}: commit: modify CDNをローカルファイル参照に置き換え
6bfe118 HEAD@{2}: commit: move qiita.jsを src/js/service/util フォルダに移動
2e08059 HEAD@{3}: commit: move html/css/jsフォルダをsrcフォルダに移動
c9d4a29 HEAD@{4}: commit: modify js/qiita.js : qiitaServiceにgetItems()を追加
...

git reflogの使い所

git reflogで出現したHEAD@{1}のようなシンボルは、リビジョンのハッシュ値のように使うことができる。 すなわち、git diffで参照ログ間の差分を見ることができたり、git resetで操作そのものの取り消しを行うことができます。

参照ログ間のgit diff

# 操作前後でのファイル差分
$ git diff HEAD@{1} HEAD@{2}

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 5509140..0000000
--- a/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.DS_Store

参照ログの取り消しgit reset

 
# 最初の履歴
$ git log
commit 80634e31281831f83fe7cfb2c8b541718bb2ef0b
Author: hoge <hogehoge@gmail.com>
Date:   Mon Mar 5 21:58:59 2018 +0900

    modify CDNをローカルファイル参照に置き換え

...

# 操作取り消し
$ git reset HEAD@{1}
d3f2ad5 HEAD@{0}: reset: moving to HEAD@{1}
80634e3 HEAD@{1}: reset: moving to HEAD~
d3f2ad5 HEAD@{2}: commit: add .gitignore
80634e3 HEAD@{3}: commit: modify CDNをローカルファイル参照に置き換え
6bfe118 HEAD@{4}: commit: move qiita.jsを src/js/service/util フォルダに移動
2e08059 HEAD@{5}: commit: move html/css/jsフォルダをsrcフォルダに移動
...

# 履歴がもとに戻る
commit d3f2ad5e07097a2127c25502878d57a9e4ffed6d
Author: hoge <hogehoge@gmail.com>
Date:   Mon Mar 5 23:47:47 2018 +0900

    add .gitignore

commit 80634e31281831f83fe7cfb2c8b541718bb2ef0b
Author: hoge <hogehoge@gmail.com>
Date:   Mon Mar 5 21:58:59 2018 +0900

    modify CDNをローカルファイル参照に置き換え

特に後者の操作に関しては、誤ったgit reset操作の取り消しなどを修正するのに使えるのでとても便利です。

【AngularJS】Jasmine+KarmaでAngularJS用テスト環境を構築する

AngularJSはフルスタックなフレームワークで有名ですが、テストもサポートします。
AngularJSではテスティングフレームワークとテストランナーと呼ばれるツールを用いて、ユニットテストとE2Eテストを実行します。

テスティングフレームワーク

ソフトウェアテストの自動化を支援するフレームワーク
テストコードの自動実行プログラム作成・テスト通過判定・カバレッジ集計などをやってくれます。
今回はテスティングフレームワークJasmineを使用します。

テストランナー

テストを実際に自動実行するツール。
今回はJavaScriptテストランナーであるKarmaを使用します。

ユニットテスト環境を構築する

構築環境は Mac OS X El Capitan

Node.jsをインストール

後述するパッケージ管理ツールnpm使用のため、Node.jsをインストールします。
Macであればhomebrewでインストール可能。

$ brew install node

npm をインストール

nodeがインストールできたら、npmをインストールします。

$ brew install npm

Jasmineをインストール

テスティングフレームワークJasmineをインストールします。

$ npm install jasmine-core --save-dev

Karmaをインストール

テストランナーKarmaをインストールします。
Karmaのインストールはテストを実行したいアプリケーションプロジェクトのディレクトリに移動してから行います。
便利のため、KarmaのCLIツールであるKarma-CLIもインストール。

# プロジェクトディレクトリに移動
$ cd [プロジェクトディレクトリ]

$ npm install karma
$ npm install -g karma-cli

以下のファイルが展開されていたら成功。

node_modules/
package-lock.json

CDNをローカルファイルに落とす

karmaがCDN上のライブラリを読み込めないので、
<script><link>CDNをローカル参照に切り替えます。

今回はサンプルテストプログラムを実行するので依存ファイルはありませんが、
実際のアプリケーションコードをテストする際には対応する必要があります。

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>

<script src="../../lib/js/angular.min.js"></script>
.
├── css
│   └── mui.min.css
└── js
    ├── angular.min.js
    └── mui-angular.min.js

Karma初期化

次にKarmaを初期化します。
karma initコマンドを打つと下のように対話的に入力ができるようになるので、
各項目を順番に設定していきます。

# プロジェクトディレクトリに移動
$ cd [プロジェクトディレクトリ]
$ karma init

# テストランナーの指定(デフォルトでjasmineと入力されているので、そのままEnter)
Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> jasmine

# Require.js(JSファイルを非同期に読み込むライブラリ)を使うかどうか(noでEnter)
Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no

# テストランナーがブラウザに何を使うか(デフォルトでChromeと入力されているので、そのままEnter)
Do you want to capture any browsers automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> Chrome
> 

# ソース・ファイルとテストファイルのディレクトリ(空白でEnter)
What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> 

# テスト対象外とするファイル(空白でEnter)
Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
> 

# Karma起動中、ファイル変更時にテストを自動実行するか(yesでEnter)
Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes

# Configファイル完成
Config file generated at "/Users/kanairen/Projects/js/Geeky/karma.conf.js".

初期化終了後、node_modules/配下のライブラリが増えていることが確認できます。
また、karma.conf.jskarma init実行時のディレクトリ生成されます。
Karmaの設定はこのファイルを経由して行うことになります。

テストを作成する

いよいよテストを作成していきます。
プロジェクト直下にディレクトtestを作成し、その下にサンプルテストコードtest_spec.jsを作成します。

test
└── test_spec.js
# test_spec.js
describe('Hello, Jasmine', function(){
    beforeEach(function(){
            // 初期化処理、JUnitでいうsetUp()
    });

    it('test start', function(){
        // テストケース実行
        expect(1 + 2 + 3 + 4 + 5).toEqual(15); 
    });:;
});

さらに、さきほどkarma initで作成したkarma.conf.jsを編集します。
テスト対象ファイルへのパスと、必要とするソースコード/ライブラリへのパスをfile:リストに追加します。
ファイルパスには正規表現が利用可能です。

    // list of files / patterns to load in the browser
    files: [
        'lib/js/angular.min.js',
        'lib/js/mui-angular.min.js',
        'lib/css/mui.min.css',
        'src/js/*.js',
        'test/*_spec.js'  // テストファイルへのパス
    ],

テストを実行する

作成したテストを実行してみます。
karma.conf.jsに指定したブラウザが表示され、テストが実行されます。

$ karma start karma.conf.js          
05 03 2018 22:57:21.867:WARN [karma]: No captured browser, open http://localhost:9876/
05 03 2018 22:57:21.876:INFO [karma]: Front-end scripts not present. Compiling...
05 03 2018 22:57:22.564:INFO [karma]: Karma v2.0.0 server started at http://0.0.0.0:9876/
05 03 2018 22:57:22.564:INFO [launcher]: Launching browser Chrome with unlimited concurrency
05 03 2018 22:57:22.581:INFO [launcher]: Starting browser Chrome
05 03 2018 22:57:25.828:INFO [Chrome 64.0.3282 (Mac OS X 10.11.5)]: Connected on socket wOBo_tCUqrACSe3HAAAA with id 54719492
Chrome 64.0.3282 (Mac OS X 10.11.5): Executed 1 of 1 SUCCESS (0.123 secs / 0 secs)

f:id:rennnosukesann:20180305230031p:plain

無事テストに成功しました!

まとめ

これでAngularJS上でユニットテストを行えるようになりました。
次回のAngularJSテスト環境構築では、E2EテストやCIツールを使ったテスト自動化をやってみようと思います。

参考文献

AngularJS アプリケーションプログラミング

【git】git tagで特定のリビジョンにタグを打つ

git tag

git tag コマンドを使うことで、特定のリビジョンに対してタグを付加することができます。
リビジョンに付加したタグはリビジョンのエイリアスとして使うことができます。

Usage

git tag [タグ名]だけで、HEADが指すリビジョンにタグを付けることができます。

# branchの状態
$ git branch
* branch1
  branch2
  master

# 現在のリビジョンにタグをつける
$ git tag testtag

# タグ一覧
$ git tag
test1.0
testtag

タグを付けたリビジョンに対して、git diffgit checkout等を使うことができます。

# ex1. タグをつけたリビジョンとの差分
$ git diff master testtag

diff --git a/hoge1.txt b/hoge1.txt
index 6339dc3..0ef7e93 100644
--- a/hoge1.txt
+++ b/hoge1.txt
@@ -1,10 +1 @@
-fuga
-
-hoge
-hoge
 piyo
-foo
-hogehoge
-fugafuga
-
-fugafuga
diff --git a/hoge2.txt b/hoge2.txt
deleted file mode 100644
index 1a57997..0000000
--- a/hoge2.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-hoge
-fuga
-piyo

# ex2. タグをつけたリビジョンへのcheckout
$ git checkout testtag
Note: checking out 'testtag'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at df7c41a... modify hoge1.txt

タグを利用した削除後ブランチの追跡

タグ付けられたリビジョンを持つブランチを削除しても、タグ自体は削除されません。
そのためgit checkout [タグ名]に削除されたブランチ上のリビジョンへのタグを指定することで、 既に削除されてしまったブランチの履歴を追跡することができます。

# 'testtag'タグを作成したブランチを削除
$ git branch -D branch1
Deleted branch branch1 (was df7c41a).

# チェックアウト可能
$ git checkout testtag 
Note: checking out 'testtag'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at df7c41a... modify hoge1.txt

ブランチは残したくはないがある時点でのリポジトリ履歴を残しておきたい場合や、
ブランチのバックアップを残しておきたい場合などにこの機能を使うと便利です。

【git】git add をインタラクティブに操作する

git add

git addコマンドはコミット対象となるファイルを指定するためのコマンドです。
もっと厳密に言うと、直前のコミット履歴(リビジョン)から現在のファイルの状態(ワーキングツリー)との差分のうち、どの部分を次のコミット履歴の対象とするか(ステージングと呼ぶ)を指定することができます。

通常は以下のようにgit addを利用し、ファイルやディレクトリを指定してステージング行います。

#カレントディレクトリ配下のファイル全てをステージング(.gitignoreで定義されたファイル除く)
$ git add .

# ファイルを指定してステージング
$ git add hoge.txt

インタラクティブにステージング操作を行う

git add -iコマンドを使うことで、以下のようなインタラクティブ操作に切り替わります。

# インタラクティブモード
# stagedはステージングされた変更、unstaged がステージングされていない変更を表す
$ git add -i
           staged     unstaged path
  1:    unchanged        +0/-1 hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 1 または s(status)を入力してEnterを押すと、上の出力が再度出る
What now> 1
           staged     unstaged path
  1:    unchanged        +0/-1 hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

ファイルを指定してステージングを行う

2: updateを指定すると、ファイルをステージングできるモードに入ります。

# 2 または u(update)を入力してEnterを押すと、ステージングしたいファイルを選択できる
What now>2
           staged     unstaged path
  1:    unchanged        +0/-1 hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

# ステージングしたいファイルの番号を指定すると、左側に米印がつく
# 米印が付いたファイルは、ステージング対象となる
Update>>1
           staged     unstaged path
* 1:    unchanged        +0/-1 hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

# Enterで確定
Update>>
updated one path

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 終了
What now> q

#ステージング済み
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   hoge1.txt

アンステージングする

3:revertを指定すると、ステージングされたファイルをアンステージすることができます。

$ git add -i
           staged     unstaged path
  1:        +0/-1      nothing hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# revertを選択
What now> 3   
           staged     unstaged path
  1:        +0/-1      nothing hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

# アンステージしたいファイルを選択
Revert>> 1
           staged     unstaged path
* 1:        +0/-1      nothing hoge1.txt
  2:    unchanged        +1/-0 hoge2.txt

# Enterで確定
Revert>> 
reverted one path

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 終了
What now> q
Bye.

# アンステージされている
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   hoge1.txt

no changes added to commit (use "git add" and/or "git commit -a")

ラッキングされていないファイルをaddする

4:add untrackedで新規作成したファイルなどの未トラッキング状態のファイルをaddできます。

# 新規作成
$ touch new.txt    

$ git add -i
           staged     unstaged path
  1:    unchanged        +0/-1 hoge1.txt

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 4: add untrackedを選択
# 未トラッキング状態のファイル一覧が表示される
What now> 4
  1: new.txt

# ファイル指定
Add untracked>> 1
* 1: new.txt

# Enterで確定
Add untracked>> 
added one path

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help
What now> q
Bye.

# ステージングされている
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   new.txt

変更箇所を確認しながらaddする

5:patch2:updateと同じようにファイルのステージングを行います。
異なるのは、ハンクと呼ばれる一定行の単位で変更箇所を表示し、各ハンクについてステージングするかどうか訪ねてくる点です。

$ git add -i
           staged     unstaged path
  1:    unchanged        +6/-0 hoge1.txt

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 5:patchを指定
What now> 5
           staged     unstaged path
  1:    unchanged        +6/-0 hoge1.txt

# ファイルを指定
Patch update>> 1
           staged     unstaged path
* 1:    unchanged        +6/-0 hoge1.txt

# Enterで確定
# 確定すると、ハンクをステージングするか訪ねてくる
Patch update>> 
diff --git a/hoge1.txt b/hoge1.txt
index 84ec994..6339dc3 100644
--- a/hoge1.txt
+++ b/hoge1.txt
@@ -1,4 +1,10 @@
+fuga
+
 hoge
 hoge
 piyo
 foo
+hogehoge
+fugafuga
+
+fugafuga

# y でステージング
Stage this hunk [y,n,q,a,d,/,s,e,?]? y

*** Commands ***
  1: status    2: update      3: revert      4: add untracked
  5: patch   6: diff    7: quit    8: help

# 終了
What now> q
Bye.

# ステージング済み
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   hoge1.txt

ちなみにこのハンクごとのaddは、git add -pでも行うことができます。
ファイルの部分的なステージングをしたいときにとても重宝します。

$ git add -p
diff --git a/hoge1.txt b/hoge1.txt
index 84ec994..6339dc3 100644
--- a/hoge1.txt
+++ b/hoge1.txt
@@ -1,4 +1,10 @@
+fuga
+
 hoge
 hoge
 piyo
 foo
+hogehoge
+fugafuga
+
+fugafuga
Stage this hunk [y,n,q,a,d,/,s,e,?]? 

ハンクステージング時の操作

ハンクをステージングするときの操作は以下のとおりです。

  • y:表示されたハンクをステージングし、次のハンクへ移る。
  • n:表示されたハンクをステージングせず、次のハンクへ移る。
  • q:終了。まだチェックしていないハンクはすべてアンステージングとなる。
  • a:表示されたハンクをステージングし、同じファイル内の残りのハンクも全部ステージング。
  • d:表示されたハンクをステージングせず、同じファイル内の残りのハンクも全部ステージングしない。
  • g:別のハンクを指定して移動。
  • /:ハンク検索。正規表現もサポート。
  • j:ステージング保留。今のハンクより次にある保留状態のハンクに移動。
  • J:ステージング保留。今のハンクより次にあるハンクに移動。
  • k :ステージング保留。今のハンクより前にある保留状態のハンクに移動。
  • K:ステージング保留。今のハンクより前にあるハンクに移動。
  • s:表示されたハンクをさらに分割したハンクにする。
  • e:エディットモード。表示されたハンクのステージング範囲をエディタで指定する。
  • ?:ヘルプ。