プログラムdeタマゴ

nodamushiの著作物は、文章、画像、プログラムにかかわらず全てUnlicenseです

MSYSで標準出力をクリップボードにコピー

 MSYS2で標準出力をクリップボードにコピーしたい。要するに「pbcopy」が使いたい。え?WSL?ギリギリまでWindows 7だよ。

 で、「pacman -S pbcopy」ってやっても、「pacman -S xsel」ってやっても、なもんねぇと言われた。マジかー。

 と思ってたんだけど、なんと、Windowsには標準で「C:/Windows/System32/clip.exe」というpbcopyがあったらしい。ということは、これにpbcopyのaliasを貼ればpbcopyが使えるジャマイカ!

 というわけで、~/.bash_profileに以下を追加記述。ちなみに、MSYS2のbashはログイン時に.bashrcを読み込まない設定になっている。

alias pbcopy="/c/Windows/System32/clip.exe"

 

 これで、pbcopyが使える様になった訳なので、早速試してみます。

echo "コピー出来てますか?" | pbcopy

ペースト。↓
繧ウ繝斐・蜃コ譚・縺ヲ縺セ縺吶°・・

 

 ………オーマイガ。そうか、文字コードか。MSYSの文字コードはUTF-8だもんな。Shift_JIS滅びねぇかな。

MSYSの文字コードを変更するべきか否か

 MSYSの文字コードは変更すること可能です。本当に変更するかどうかは、しっかり考察した方がいいですが。

 変更するには、ウィンドウのタイトルバーを右クリックして、ポップアップするメニューからOptionを選択し、以下の様に設定し、save。

f:id:nodamushi:20180112190722p:plain

 これでもう一度先ほどのコマンドを実行して、ペースとしてみると↓
コピー出来てますか?

 おぉ。コピー出来た。

 

 だけど、問題もある。以下のC++ファイルをコンパイルしてみる。

#include <iostream>
int main(int argc, char *argv[]){
  std::cout << "これは日本語です。" << std::endl;
}
g++ main.cpp

 で、a.exeを実行すると………
縺薙l縺ッ譌・譛ャ隱槭〒縺吶▒

 ………Shift_JIS滅びねぇかな。

 

 一応、以下のオプションを付加することで、この問題は回避出来る。

g++ main.cpp -fexec-charset=CP932

 んー。

 

結論 iconvを通す

 結局私はあれこれ考えた結果、MSYSのデフォルトに戻しました。だってSJIS嫌いだし。文字コード変更してどうなるか分からないからね。

 文字化けせずにクリップボードに転送するには、iconvを通してUTF-8をCP932に変換すれば良い。

echo "あいうえお" | iconv -f UTF-8 -t CP932 | pbcopy

 ペースト↓
あいうえお

 また、実は今回はechoではなく、catで読み出した内容をクリップボードに貼り付けたいという要求から調べだしたこと。私は基本的にテキストファイルではUTF-8しか使わないので、catの出力もUTF-8になる。(catの文字コードはファイル依存)
 なので、結局aliasを次の様にしました。

alias clip='/c/Windows/System32/clip.exe'
alias pbcopy='iconv -f UTF-8 -t CP932 | /c/Windows/System32/clip.exe'

 Windows標準のclipはCP932を受け取り、pbcopyはUTF-8を受け取るという感じにしておけば、だいたいの状況は使い分けられるんじゃないかな。うん。

 とりあえず、これでいいかなぁ。

Windowsでフォルダ内のファイルの改行コードを一括変換

 ディレクトリ内のファイルがメモ帳で改行が表示されない形式(LFかCR)だからCR+LFのWindows形式に一括変換したい。しかし、sedはおろか、shell環境も、エディタもない。メモ帳程度。ハゲそう。
 そんなときでもPowerShellさえあれば、一括変換出来るので、メモメモ。

Windows形式(CR+LF)に変換

 以下を実行すると、全てのファイルやディレクトリに対して処理するので注意。特定のファイルだけにしたい場合は後述のfilterを使う。

ls | foreach{ (cat $_) -join "`r`n" | set-content $_ }

 なお、文字コードは元のファイルが何であれ、Shift-JIS(正確にはパソコン環境依存)になる模様。UTF8で保存したい場合は、Set-Contentのオプション「-encoding UTF8」を利用する。

Unix形式(LF)に変換

ls | foreach{ (cat $_) -join "`n" | set-content $_ }

Mac形式(CR)に変換

ls | foreach{ (cat $_) -join "`r" | set-content $_ }

特定の拡張子のファイルのみ変換したい場合

 grepとかなくても、ls(Get-ChildItem)のオプションにfilterがあるので、それで簡単なgrepできる。

例:拡張子が.txtだけを変換したい場合

ls -filter *.txt | foreach{ (cat $_ ) -join "`r`n" | set-content $_ }

サブディレクトリも再帰的に変換する場合

 lsコマンドがちょっと長くなる。

ls -r -n -file | foreach{ (cat $_ ) -join "`r`n" | set-content $_ }

 -r(-Recurse)で再帰化して、-n(-Name)で名前だけ出力させて、-fileでファイルだけをforeachに渡す。-filterの併用も可。

 cat(Get-Content)ってSystem.IO.FileSystemInfoをそのまま喰えないんだねぇ。

小学校では距離の単位は時速らしい

 この時期になると必ずでてくる風物詩の小学校かけ算順序問題。4個ずつ5人に配るというのは

4×5 = 20

であり、

5×4 = 20

は間違いだと言うことだ。これは

4[個]×5[人] = 20[個]
5[人]×4[個] = 20[人]

となるからだそうだ。非常に面白いと思う。
 ここで重要なのは、被乗数では個や人が単位として認められているのに、乗数の単位は認められないという点だ。もしくは、被乗数の単位は自動的に乗数の単位で割られた単位が設定されるとも定義出来る。つまり、

4[個]×5[時間] = 20[個]
4[個]×5[/個] = 20[個]

これが正解だ。それが小学校教育の定義なのだから、それはそれで問題ない。そういう系なのだ。
 すなわち、小学校では時速20kmで2時間走る距離は

20[km/h] × 2[h] = 40[km/h]

だ。時速20kmで2時間かかる距離は時速40kmだ。
 それが、間違いだのどうのこうのではなく、そういう定義の系なのだから、そうなのだ。行列は何故可換ではないのか?そうなる乗算の定義の系だからだ。「1+1=0」は何故なのか?0,1の集合が和に関して群の系だからだ。それに従えと言うだけだ。

 

問題の本質は何なのか?

 この問題を批判する方、擁護する方、ともに大きな勘違いをしている、いや、前提とすべき事を見ようとしていない気がするのだ。

 まず、学校教育は何の為にあるのか?これは紛うことなく、未来の日本人の育成である。では、未来の日本人とはどのような人物が求められているのか?
 誰も口にしようとしないが、日本教育において、「目上(先生)に従順な奴隷」が求められる人物像であろう。個性などはいらないし、極端に優秀な人材もいらない。村八分。日本社会はそういう社会だ。
 最低限の国語と英語が出来れば、後は従順な奴隷であればあるほどよい。何も考えない無能な人間であればある程、素晴らしい。逆に支配層の人間は自分たちで教育を施せるから、学校教育に頼る必要はない。従って、それを問題にする必要がない。残念なことに、それが日本教育だと思う。

 私も小学生の頃、「1-2はどうなるか?」と当てられて「-1」と答えたら、「何言ってんだ?」と返された。答えは計算出来ないであった。記憶力の悪い私が未だに覚えている小学校1年生の頃の記憶だ。非常に不満に思ったのを覚えている。
 だが、大人になった今は、教師が正しかったと分かる。

 数学的に言えば、「1-2」が「-1」になるには、少なくとも対象とする系において、-1が定義されていないといけない。自然数の世界だけの話ならば、「-1」は存在しない。あの時、問題は自然数の範囲だけだという前置きがあったかどうかの記憶は無いが、小学校において、自然数と0ぐらいの世界しか存在しないという前提があるのならば、数学的に私が間違っている。
 そして、何よりも最大の間違いは、「教師がその答えを求めていなかった」点だ。教師が求めていないことを答えれば、当然それは間違いだ。教師が赤を黄色と言えば、その教師の前では赤を黄色と答えるのが正しいのだ。

 

 かけ算順序の問題も、教師がそのように書かなければいけないと思っているのならば、そういう系で教えているのならば、当たり前だが、それに従わなければ間違いだ。
 落ちこぼれる生徒も、浮きこぼれる生徒も、問題は学力ではなく、教師の思惑の外に出るから駄目なのだ。

 さて、問題の本質はかけ算の順序なのだろうか。

初心者がプログラムの設計を出来ない理由を考えてみた

 初心者がプログラムを書く上で、何をすれば良いのか全く分からない、全部分からない。分からないことが分からない。

 幸か不幸か、そういう感覚が私にはさっぱり分かりません。「何をすれば良いのか分からない」というところで詰まった記憶が特にありません。
 無論、数々分からん事にぶつかり、中には結局全く分からなくて諦めた物も多々あります。「分からないことがある」ということが分からない訳ではありません。

 

 だが、私のぶつかってきた「全く分からない」とどうも違う。彼らの「全部分からない」が分からない。
 彼らが何故躓き、堂々巡りしているのか共感をしてあげられない。寧ろ、全部答えを教えろと、ただ口を開けて待っている様にしか見えなくて、腹が立ってしまいます。
 

 共感することが出来ないなら、解析するしかない。というわけで、色々と考えてみたことを書いてみようかと。

 

初心者とは

 単に初心者といっても幅は広いですね。
 プログラムのプの字も知らない、スマホは知ってるけどPCは触ったことがない、他の言語を知ってるけどこの言語やライブラリは知らない、etc………

 ここでは、最低限の学習は終えたレベルの初心者とします。

  • アセンブリは書ける
  • ifなどの制御構文は使える
  • 変数、配列は分かる
  • 関数は怪しいけど、使える
  • 構造体、ポインタなどは使えない。オブジェクト指向?何それ美味しいの

 

 具体的にはFizzBuzzなどの簡単な物なら自力で作れるし、数百行程度のプログラムなら詳細な実装仕様を与えれば、動く物が作れるが、機能仕様だけでは途端に手足が出ない。

 すなわち、プログラムは書けるが、プログラムの設計が出来ない人を、この記事では初心者と呼びます。

 

分からない4つの理由

 あれこれ考えた結果、私が最終的に辿り着いた「分からない理由」は以下の4つです。

  1. 考える気が無い 考察が甘い
  2. 「上手く書けない=出来ない」と思っている
  3. 処理を分割し、まとめ、再構築することが出来ない
  4. 教える人間の人格問題

 順を追って解析していきましょう。

 

考える気が無い 考察が甘い

 殆どの場合、考える気が無いんじゃないかと思います。

 プログラムに限らず、詳細な手順書、つまりマニュアルさえあれば、殆どの部分はただの単純作業になります。特に初心者の頃に作る物なんて、完全に単純作業。
 故に「プログラミング」=「何も考えなくても良い」と思っているんじゃないかと。とにかく、流れで手を動かせば、何とかなる。

 でも、設計部分では頭を使わないといけない点に、ギャップを感じているのではないでしょうか。

 しかし、非常に残念なことに、設計をするには、目的とする物を「理解」し、「分解」し、抽象的にまとめる「再構築」という、思考を経なければならない。設計とは錬金術だ。

 理解をするには、必ず自分で勉強をする必要があります。勉強というのは主に以下の4つの行程からなります。

  1. 対象の基礎知識を身につける
  2. 資料を探す
  3. 資料を読む
  4. 調べたことを試す

 以上のことをしていない場合、理解する気が無いか、理解する方法を知らないかのどちらかだと思います。特に読むのを嫌がる、試すのを嫌がる、後回しにしようとする場合、理解する気が無いと断定して良いと思います。

 理解を後回しにして分解、再構築など出来ません。にもかかわらず、後回ししているのなら、本人的には考えてるつもりでも、結果的に何も考えていない様にしか見えないでしょう。

 

基礎知識の身につけ方を知らない可能性

 理解における「基礎知識を身につける」が一番重要で、一番疎かにしたくなります。だって面倒くさいからね。

 とやかく言う私も、本日、理解する気が無かったから失敗したばっかですし。アプリケーションのほんの一部だけ使いたいんだけどってノリで何も基礎知識なくやったら、大失敗したぜぇ。
 いやー、危うく環境ぶっ壊すところだったお( ^ω^)

 

 一方で、私の様に明確に悪意があってサボっている訳ではない場合、基礎知識の会得手段を知らない可能性があります。具体的に言うと、全体を把握する前に詳細を把握しようとする。小事に拘って、大事を見ていないという奴です。

 日本語の文章を読む書く、英語、歴史の勉強、数学の勉強、何でもそうですが、最初にざっと全体の概要を把握するという事が一番重要です。それがなければ、ただひたすら荒野の中を進む様な物です。
 全体像が分からないから、一つ分からないと、自分が何処の位置で蹴躓いたのかも分からない。分からないことが分からない。そうなるのではないかと。

 

 学校の教育論になってしまいますが、日本の教育は全体を把握する教育に非常に弱い気がします。国語とか英語とか、馬鹿みてぇに文章をみんなで一行一行声に出して読ませて、数学は阿呆みてぇに一行一行式を追って。
 そのくせ、昔塾講やってた時の経験ですが、文盲ではないけど日本語がまともに読めない子、式を一行一行展開出来ない子を量産してるんですよねぇ。不思議だ。

 

 ただ、全体をざっと把握するのに、かなりの量の基礎知識が必要である課題を与えていないかどうかには、注意しなければならないでしょう。そもそも、全体をざっと把握する為の良い資料が、どこにもない場合もあります。
 そんな課題を放り投げている場合は、少し時期尚早かも知れません。

  

Google力が足りない

 BingでもYahoo!でも百度でも何でも構いませんが、基礎知識を身につける、調べる際、検索力が低い所為で進捗が遅い可能性があります。

 検索力が低い理由は主に以下の二つがあげられるでしょう。

  • 読解力が低い
  • 検索(Google)力が低い

 

 単に読解力が低いと言っても、文盲でないのに文章が正しく理解出来ないレベルの人は、もう、ほっとくしかないです。
 塾講でもこういう子は一番苦労しました。何度言っても、何度声に出して読ませても、自力で問題の文章を読むことが出来ず、トンチンカンなことをし始めます。しかも、本人は読めてるつもりなので、本当にどうしようもないです。
 あなたが教師でもないのなら、放棄するのが一番です。

 

 文章は読めるが、情報を抜き出す力(情報リテラシー)が弱い場合、ページに答えが書いてあっても、彼らが求める状況や答えと100%一致していないなら、求める答えではないと判断するようです。
 100%一致する答えが出てくる可能性は低いことを理解させ、出てきた情報から重要な情報を抜き出す力、抜き出した単語から更に検索をかけていく力などを養う必要があるでしょう。

 

 検索能力が低い場合は、Googleセンセーの動きを理解させる必要があります。単語じゃなくて、文章で検索してたりしたら、ヤバいですね。他には、

  • 「-」を付加して検索するとどうなるか
  • 「site:」を付加して検索するとどうなるか
  • ここ一年以内の情報を得たい場合はどうするか
  • 絶対に含めたいキーワードがある場合はどうするか

この位を聞いてみて、答えられない様なら、Google力が足りません。まずはGoogleについてGoogleさせるところから始めましょう。

 

上手くないことが出来ないことだと思っている

 これは、結構な人が陥るパターンじゃないかなーと思います。私も時々陥ります。

 基本的に何事も上手くこなすというのは、スキルです。スキルはどうやっても一朝一夕には手に入らない。なのに、上手く出来ないことが全部が出来ないことだと思い込んでしまうと、手が止まってしまいます。

 

 例えばテニスなら、上達するには、実際に体を動かし、上手い人を参考にして何度も何度も糞なボールを打ち、何故自分が糞なのか考え、糞な部分を修正しつつ練習するしかありません。ボールを真っ直ぐ打てる様になるまで、ラケットは握らないという人が居るでしょうか?(…結構居る気もする。)

 プログラムも同じで、上手い人のコードを参考にして(コピペではない)、何度も糞コードを生産させ、糞コードなのかを考えさせ、リファクタリングを実際にさせてみる。それを理解させてあげることが重要なのかも知れません。

 というか、世に上手いプログラムを書ける人なんて一握りしか居ないので、上手くない事なんて、気にする必要もない事です。
 常に、上手くあろうとする努力が重要なのです。

 私?便所以下のゲロ臭いコードを量産してますが何か?ヽ( ・∀・)ノ

 
 

処理を分割し、まとめ、再構築することが出来ない

 設計をするには、理解、分解、再構築が必要ですが、分解と再構築には、それぞれまた別な力が必要です。スカーは分解で錬金術を止めていましたが、私は才能が無いので、構造を理解している水の分解すら出来ませんし。再構築なんて論外ですね。

 プログラムを作る、設計する際、何から手を出せば良いのか分からないと言う場合、錬金術の才能が無い私と同様に、分解の段階で躓いている可能性が大きいです。

 

 先にも述べてますが、今回対象としている初心者は最低限のプログラミングを記述する能力はあるとしています。なので、FizzBuzz等は書けるのに、ちょっと複雑になったり、規模が大きくなると途端に何して良いか分からなくなる。
 なら、書けると思うまで、適当な大きさに処理を分割しろ、と言ってみても、首を捻るばかりで、何もリアクションはない。

 当初は「応用力」の低さなのかと考えていましたが、以下が足りないという結論に辿り着きました。

  • 観察力
  • 考察力
  • 説明力
  • 「データ」の概念

 

 例として、「電話をすると、ピザが来る」システムについて考察するとしましょう。
 このシステムは最低限 「電話を受け取り、注文を受ける」、「ピザを焼く」、「ピザを届ける」という処理ぐらいには分割出来ると思います。しかし、彼らはそれをしない。

 彼らにとっては、「電話をすると、ピザが来る」がアトミックな処理であり、最小の処理単位なのです。従って、「電話をする」という行動から「ピザが来る」という結果までが、一意に、一発で、一つの関数で書けなければならない。
 だが、現実問題として、電話からピザが来るまでに多くの工程があるし、タイミングによって細かい条件が異なったり、エラーが起こることだってある訳です。電話をするという場面から、ピザが来るまで、一つ一つの処理を、一つ一つ確実に実装していくなんてあまりに遠すぎます。始めに何をすれば良いかすら、確かに分からないでしょう。ゴールも分からないでしょう。

 

 そして、分からない理由を彼らはプログラミング能力に転嫁します。しかし、初心者に任せてもいい程度の課題なんて、FizzBuzz書けて関数が書ければほぼ十分です。

 

 設計に必要なのはプログラミングに関する深い知識ではなく、対象を観察し、それを考察して説明する能力です。日本語と図が書ければそれでいいのです。
 (もちろん、深い知識があればより良い設計が作れるし、言語機能やライブラリに設計が依存する場合があることは否定しませんが)

 

データという概念の欠落

 観察、考察、説明をさせる前に注意したい点として、彼らには「データ」という概念がない可能性があります。
 ピザの例に戻しましょう。電話をしてからピザが手元に届くには、「注文(音声)」→「受注票(紙)」→「ピザと宅配先住所」→「ピザのみ」という風にデータが変化していく流れがあります。
 こういった、データが変化する場所は処理の大きな区切りになります。

 

 しかし、彼らは「手順」しか観察していません。「手順」しかない為、明確に処理を区切る場所の判断基準が少なくなります。ピザの例の様に具体的な事象ならまだしも、抽象的な処理の手順だけから、区切りを見つけるのは難しいでしょう。

 

 では、何故データを観察しないのか?
 無論、データを観察するという事を知らないからというのが大部分の理由でしょう。

 しかし、もう一つ、無駄なデータが存在することが悪であると思っている可能性は無視出来ません。
 例えば、「受注票」は最終的な「ピザ」には存在しない、中間的なデータだと言えます。「ピザ」に「受注票」は存在しないのだから、そんなデータは無駄、悪だとなります。

 むろん、ピザの例は非常に具体的なので、彼らもすんなりと受け入れることでしょう。しかし、少し抽象的な内容になったらどうでしょうか?抽象的なデータの中間データを定義してみろというと、おそらく、「それはいらないのでは?」とか、「何の為に?」なんて聞いてくると思います。

 

 そういう場合は、そういう中間的なデータは普通に存在し、無駄ではない、悪ではないと言うことを理解させてあげる必要があると思います。

 

教える人間が人間落第

 この可能性は十分あります。てか、これが一番かも。
 世の中、相手が悪いと思った時、常に悪いのは自分です。騙された?騙された自分が悪い。覚えが悪い?教える自分が悪い。基本そうですよね。

 というわけで、クソニートなもんで、すんまそん。
 

終わりに

 あくまで、一切共感出来ない私が、私の経験や違和感、他人の記事を読んだ内容を統合し、解析した物です。
 解析したから、次どうするのよって話は、私も知りません。どうすりゃいいんでしょうね。
 

 てか、理解しようと努めてみましたが、結局本人ではないので、本当に何に躓いているのかなんてぶっちゃけ分かりません。本人も分からないなら、問題は完全に闇の中。
 プログラミングには向き不向きがあるから、能力よりも、根本的な思考パターン依存かもしれないし。

 

 いや、中々難しいね。と言うことで、以上です。(^^)/

JavaScript嫌いのES6入門~環境構築編~

この記事を書いてる人のレベル

 諸君 私はJavaScriptが嫌いだ
 諸君 私はJavaScriptが嫌いだ
 諸君 私はJavaScriptが大嫌いだ

 varが嫌いだ
 オーバーロードが無いのが嫌いだ
 prototypeが嫌いだ
 thisが嫌いだ
 整数型がないのが嫌いだ
 定数がないのが嫌いだ
 ファイルスコープがないのが嫌いだ
 ブロックスコープがないのが嫌いだ

 Chromeで IEで
 Firefoxで Opera最強伝説で
 Vivaldiで Edgeで

 この世界で行われるありとあらゆるJavaScriptが大嫌いだ

 以下略

 

 というわけで、私はかつてはJavaScriptが死ぬ程嫌い、いや、憎い頃もありました。
 しかし、海外勢の美しいソースコードに感化され、今では立派にJavaScriptが大嫌いです。

var value = "value";
var flag = false;
hoge();

function hoge(){
  if(flag){// ← flagはfalseなのでこのif文は無効
    var value = "hoge";
    console.log(value);
  }
  console.log(value);// ← 問題はここ
}

 これを実行して"value"と表示させるつもりが、"undefined"と表示されてファッΣ(゚Д゚;)とかなるレベルの人間です。


 これ、変数の巻き上げとか言うエラソーな名前付いてるらしいけど、ぶっちゃけ一番最初にインタプリタ作った人が、変数保持するハッシュマップをブロックレベルで管理するの面倒くさかっただけだろ。その怠慢な実装が仕様として現代まで残ってしまったと。Verilogのwireやregと同レベルの怠慢と思っています。C88以下だぞ。真実かどうかは知らないけども。

ES6では色々解決されたらしい

 ES2015やらなんやら呼び方が色々あるのか、何がES6なのかワカリマセンが(C++1xとかC++2xみたいなもの?)、letやconstが導入され、モジュールが追加されたことでファイルスコープも出来る様です。classだって作れるらしい。

 今までJavaScriptを使うこともなかったので、JavaScriptの知識はCoffeeScriptが出始めた頃で停止している。そんな人間の屑がちょっと個人的な理由でJavaScriptを触らないといけなくなったので、ついでにES6に入門してみました。


環境構築の段階で心折れそう

 さて、何はともあれ、環境構築からかな。JavaScriptなんて簡単簡単………

f:id:nodamushi:20170924190105p:plain


 あ゛ぁ゛ん゛!?


 え、何これ、今JavaScript界隈ってこんな面倒くさいことになってるの?これが素晴らしい!みたいな雰囲気だけど、みんな本気で言ってるの?JavaScriptってもっと、こう、お手軽で簡単な物じゃなかった?

 環境構築が面倒と言われるC++より酷い。ていうか、C++なんかVisualStudio入れれば動くし、アンチVisualStudioな場合でもMinGWとMakeとCMake入れりゃ十分だというのに。ていうか、MSYS2の上でだいたい全部すむのに。一昔前のTeXの環境構築を彷彿とさせるカオス。しかも、1年単位で言ってることがコロコロ変わってる。

 CoffeeScriptの時代より悪化してる様な気が………

 何かもう頭が痛くなってきましたが、ここで脱落してしまえばいつまで経ってもCoffeeScript良いよねっていう老害に終始してしまいます。一個ずつ紐解き、耐えねば。

 CoffeeScript2が出てたぞ!!私は老害じゃなかった!わはははは!

Node.jsとnpm

 どうも、Node.jsからは逃げることは不可能らしいです。正直、Webと関わりが無い私は、こやつが一体何者かもよく分かっていません。なので、コレがなんなのかもついでに学習してみました。

 JavaScript環境だとかサーバーがとか、IOがとか、あちこちでよーわからん説明がされていますが、個人的には

  • Node.js≒MSYS
  • npm  ≒pacman

という理解で決着しました。
 要するに、JavaScriptで作られ、JavaScriptが動くシェルみたいな環境。Emacsのeshellみたいな。正確には違うのでしょうが、個人的にはコレで納得出来たので良しとします。マサカリ飛んで来そう?ははは。全部避けてやる。

 Windows上でC++開発するならMSYSが必須(異論は認める)な様に、現代のJavaScriptを開発するなら、Node.jsという環境が必要なようです。

 元からCoffeeScriptのために入っていましたが、ついでなので最新版に更新しました。

package.json

 package.jsonがあるディレクトリから下が、プロジェクト管理下に置かれるらしい。つまりは、Eclipseの.projectファイルとか、CMakeLists.txtみたいなものかな。

 とりあえず、以下の様な内容を書いておきゃいいらしい。

{
  "name":"プロジェクト名",
  "version":"1.0.0",
  "scripts": {
     "run":"node main.jsとか、実際に実行させる際のコマンド"
      //ここにビルドコマンドとか、実行コマンドとか書くと、npm run ***でそのコマンドが実行される
  }
}

コンパイラ

 ES6を試したいのですが、現状はES6が完全に動く環境は存在しないらしい。なので、ES6のコードを現在の環境でも動く様に変換してくれるコンパイラが必要となる。それがbabelという物らしい。ただ、babelはexport、importの解析まではしないので、ブラウザでexport,importを使うことが出来ない。
 そこで、browserifyが登場する。これを使うと、export、importの関係を解析し、一つのファイルにまとめてくれるとのこと。

Name Description
babel-cli ES6を今のブラウザで動作する様に変換する
babel-preset-**** ES2015とかES2016とか、言語仕様が違うのか知らないけど、それに対応する為のライブラリっぽい?
.babelrc どのpresetを使用するのかとか、babel-cliの動作を設定するファイルらしい。package.jsonに書いてもいいらしい。
browserify import,exportを解析し、一つのファイルにする。最近はwebpack?
babelify browserifyとbabelの橋渡し機能

 つまり、C++でいうところ、babelがコンパイラで、browserifyがリンカーで、babelifyはパイプという理解でよろしいでしょうか。

 なんか、最近はbrowserifyは死亡してwebpackだとか、何だかもう知らねぇよ。理解したら書き換えるかも。

 調べていると、これらのパッケージはグローバルにインストール(npm install -g)しちゃいけないと書かれている場合もある。バージョンごとによって挙動が違うから、プロジェクトごとに管理した方が良いとのことらしい。面倒くさいな、おい。

 babel-preset-***をインストールすることで、ES2015やES2016といったバージョンに対応できるようになる。それらが何の違いがあるのかは知らない。C++の-std=c++1xとか、-std=c++2xみたいなものだろう。私は面倒くさいからenvを使うことにした。各ブラウザのバージョンに対応したコードを出力出来るらしい。
 どのpresetを使うのかというのをbabelに知らせる為に、.babelrcに情報を記述するらしい。
 

npm install --save-dev babel-cli babel-preset-env browserify babelify


".babelrc"

{
  "presets": ["env"]
}

 --save-devで、前述のpackage.jsonにインストールしたパッケージの情報が書き込まれる。Eclipseのビルドパスとかの情報と同等かな?

 はー、これだけでもおなかいっぱいです。他にも圧縮だとか色々話題があるけど、にわかの私はここまでで良いです。

package.jsonにビルドコマンド追加

 前述した様に、scriptsにビルドコマンドなどを登録しておくと、npm run buildなどで実行できるようになるらしいので、ビルドコマンドを書いておきます。

 とりあえず、srcフォルダにJavaScriptを配置し、binに吐き出すことにします。

{
  "name": "hoge",
  "version": "1.0.0",
  "scripts": {
    "build": "browserify src/main.js -o bin/main.js -t babelify"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-preset-env": "^1.6.0"
    "babelify": "^7.3.0",
    "browserify": "^14.4.0"
  }
}

 (devDependenciesはnpm install --save-devで勝手に追加された物です。)

 main.js以外にもhoge.jsなどが追加されたとしても、main.jsからそのhoge.jsがimportされている限り、browserifyがその関係を解析して勝手にコンパイルしてくれるみたいなので、基準ファイル一つを指定しておけば良いみたいです。


テスト環境

 ブラウザでしか動かない物はブラウザで試す必要があるけど、全部ブラウザで試すのは辛たん。JUnitテストとか、GoogleTestみたいなことがしたいです。
 というわけで、テスト環境について調べてみると、mochaというNode.js上で動くテスト環境がある様だ。mocha単体にはアサーション機能が無いので、chaiとか、別な物を利用するらしい。面倒くさいな。

npm install -g mocha 
npm install -g chai

 これはglobalなインストールで良いのだろうか? さっきまでの話の理解だと、-gを付けちゃ駄目な気がするのだが。………まぁ、いいや。

 で、globalなインストールをした場合は環境変数NODE_PATHにそのパスを通しておかないと、require出来ないらしい。
 というわけで、PowerShellで以下を実行。

$node_module = npm root -g
[Environment]::SetEnvironmentVariable("NODE_PATH", $node_module, [EnvironmentVariableTarget]::User)

 これで、mochaを実行すると、プロジェクトのtestディレクトリにあるJavaScriptファイルが実行されるっぽい。というわけで、pacakge.jsonにtestコマンドを追加した。Node.jsだとexportとimport構文にはまだ対応してないので、browserifyを同じように通している。これだとエラーが起こった時に、何処が原因なのかわかりにくいのが難点。いや、別に、Node.js標準のrequireで書いてもいいんだけどさ………ES6の勉強してるのに何か、負けた気分じゃん………。
 ※mochaでコンパイラが指定出来るらしい。Babel6でMochaとChaiを使ったテストを書く - Qiita
 babel-coreをインストールしておく。

npm install --save-dev babel-core 
{
  "name": "hoge",
  "version": "1.0.0",
  "scripts": {
    "build": "browserify src/main.js -o bin/main.js -t babelify",
     "test": "mocha --compilers js:babel-register"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.0",
    "babel-preset-env": "^1.6.0"
    "babelify": "^7.3.0",
    "browserify": "^14.4.0"
  }
}

Gulp.js

 どうやらMakeとかCMakeとかの様な物らしい。スクリプト的に書けるから、Gradleが近いかな。

 にわかの私はpackage.jsonのscriptsで十分なので放置

Emacsの環境設定

package-installで以下をインストールして、init.elに設定追加。

  • js2-mode : 神Add-on Keysnailの作者id:mooz様が作ったJavaScriptモード。そろそろ神が死にそう。
  • js-doc : JavaScript用JavaDocを簡単に書く為のid:mooz様が作ったパッケージ
  • tern : company-ternで使う。
  • company-tern : JavaScript用のcompany backend。auto-completeな人は知らない。
(use-package tern)
(use-package company-tern
  :init
  (add-to-list 'company-backends'(company-tern :with company-dabbrev-code :with company-yasnippet)))

(use-package js2-mode
  :init
  (add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
  (add-hook 'js2-mode-hook 'tern-mode))

(use-package js-doc
  :init
  (setq js-doc-author "nodamushi")
  (add-hook 'js2-mode-hook
            #'(lambda ()
                (define-key js2-mode-map (kbd "C-x i d") 'js-doc-insert-function-doc)
                (define-key js2-mode-map "@" 'js-doc-insert-tag))))

 ternを動かすには、Node.js上で動くJavaScript解析サーバーを別途インストールする必要がある。

npm install -g tern

テストを動かしてみる

 あぁ、パトラッシュ、僕はもう疲れたよ。もうゴールしてもいいよね?

 というわけで、ひとまず、テストを実行出来るのか試してみる。

"src/main.js"

/**
 * 二乗するだけ。
 * @param {number} x 
 * @returns {number} x*x
 */
export function test(x){
  return x*x;
}

"test/allTest.js"

const chai = require("chai");
const assert = chai.assert;

import {test} from '../src/main';

describe('src/main.js',()=>{
  describe('test',()=>{
    it('(0)',()=>{
      assert.strictEqual(0,test(0));
    });
    it('(10)',()=>{
      assert.strictEqual(100,test(10));
    });
    it('(-10)',()=>{
      assert.strictEqual(100,test(-10));
    });
  });
});

 で、以下を実行。

mkdir test
npm run test

f:id:nodamushi:20170924210857p:plain
npm run testの実行結果

感想

 はー、疲れた。今回はここまでです。………あれ、私まだ何も入門してなくない?

 なんというか、狂った異常な言語から、普通の言語にやっとES6でなったという感じなのに、その普通になる為にこんだけ苦労しないといけないのか………。
 やっぱ、JavaScriptが嫌いです。

直前の英字文字列をIMEで再変換するAIUEO Eclipse Plugin作った

 いよぅ!IME圏でEclipseを使っているみんな!nodamushiからのナイスクリームなプラグインをプレゼントだ!

 ………すいませんでした。現在深夜………というか明朝の5時、妙なテンションになりました。気がついたら徹夜だよ。


 さて、前回の記事でAtokの入力済みのローマ字を再変換する機能について触れました。
 ポップアップも消せるようになりましたし、とてもいい機能なんですが、最悪の欠点が2つあります。

  1. 本当に直前に入力した文字しか変換できない
  2. 変換確定後IMEがONになっている

 最初のはまだしも、2番目がプログラミングをする上でこの上なくウザい。画面割りたくなる。

 プログラミングで日本語(笑 とか言ってる意識高い(笑 人は放っておいて、基本的には日本語って以下の状況で使うと思います。

  1. コメント
  2. JavaDocなどのドキュメント
  3. テストメソッド名

 コメント書いてるときはまだいいんですが、JavaDocを書いてるときは@paramとか{@link ****}とか出てきて英語と日本語のチャンポンなのでIME切り替えが面倒くさい。テストメソッド名も、その後必ず()を書くわけで、IMEの切り替えが面倒くさい。

 というわけで、そんな不満を解消するためにAIUEOという名前のプラグイン作りました。名前が酷い。

 もし、既に似たようなのが存在してたら泣く。
 

インストール

利用可のなのはWindowsだけです。

Eclipseの新規ソフトウェアのインストールで「https://nodamushi.github.io/AIUEO」からインストール。

手動インストールが良い人はReleases · nodamushi/AIUEO · GitHubからzipをダウンロードし、dropinに展開する。


使ってはダメな人

 英数字、日本語の入力切り替えをIMEのON/OFF(半角/全角キー)ではなく、無変換・変換キーで行う人はインストールしないでください。仕組み上、対応できません。

機能と仕組み

あいうえおkakikukeko|sasisuseso

 oとsの間の|はカーソル位置だと思ってください。

1. カーソル位置から前方(もしくは後方)に区切り文字を探し、書き換え範囲を見つける。(設定で区切り文字は変えられます)
  1. oを読み取る。(区切り文字ではない) 
  2. kを読み取る。(区切り文字ではない)
    ………
  3. おを読み取る。区切り文字なので、その一つ前のkまでを 書き換え範囲とする
2. kakikukekoを削除する
3. IMEをオンにする
4. kakikukekoをキーボード入力する
5. スペースを入力する
6. IMEの変換が終了するまでイベント待機
7. IMEの変換終了イベントを受け取ると、IMEをoffにする

 つまり、完全にアナログなやり方を模倣してるだけです。もっといいやり方あるんだろうけど、いんだよ、出来りゃ。

使い方

 キーバインドはデフォルトではCtrl+;に「ローマ字を再変換する(前方)」を割り当てています。


f:id:nodamushi:20170723052222p:plain

 上↑の画像のような状態でCtrl+;を押すと、下↓の様にIMEで変換できます。

f:id:nodamushi:20170723052322p:plain

 変換完了後はIMEがOFFになります。

f:id:nodamushi:20170723052616p:plain

 「そー言えばこれは変換に失敗します」と打ちたかったのですが、初期設定だと、「そー」が変換されません。

f:id:nodamushi:20170723052649p:plain

 これは、-が区切り文字と見なされているからです。-も変換したい場合はこれを消してください。

f:id:nodamushi:20170723052755p:plain

f:id:nodamushi:20170723052908p:plain

JISキー以外のキーボードの方

 何とか根性でJIS以外のキーボード設定を作って下さい。なんとなく読めば分かると思う。
 ただ、一応くっつけたけど、nodamushiは全くテストしてないので(オイ 動くかは知らない。

ATOKの直前の入力を日本語にするをポップアップさせない方法

 ATOKの直前の入力を日本語にするっていう機能あんまり使わないけど、プログラミングで半角入力のまま日本語入力とか微妙に便利だったりします。
(とある理由で、私にはもう必要の無い機能になったのですが)

 でも、この機能を使っていると、ポップアップがこの上なくウザい。
f:id:nodamushi:20170717141603j:plain

 これを非表示にする方法を調べたのだけども、ググっても出てこなかったのだけど、何故かヘルプの方で検索すると出てきたので、ここでもメモ。

 "日本語入力オフのまま入力した文字を読みにする"というヘルプページに"●こんなときには"という項目に書いてあるのだが

読みへの復帰のキー操作を提示するツールチップを表示したくないときは、以下の手順で設定をオフにします。
1. ATOK プロパティを起動します。
2. [入力・変換]シートの[入力補助-特殊]を選択します。
3. [設定一覧]の[日本語入力オンへの切り替えを通知する]をオフにします。
4. [OK]をクリックします。

 とのこと。
f:id:nodamushi:20170717141845j:plain

 これで確かに出なくなりました。は~、ストレス元が一つ減った。