CygwinでGitを使うと.gitconfigが効かない問題

Windows機にCygwinを入れ、その上でGitを使おうとして少しハマったのでメモ。

現象

  • git cloneしたリポジトリのファイルフォーマットがDOS形式になっている

僕はGitHubでdotfilesを管理し、Zsh / Tmux / Vimの設定ファイルをほぼ自動でデプロイできるようにしている。

以前にCygwin環境を構築したWin機では、特に問題なく設定ファイルを使用できていたので、 今回も同じようにリポジトリをcloneし、インストール用のスクリプトを動かそうとすると、 下記のように怒られた。

'r\' command not found

これはWindowsLinux系で改行コードが違うことから発生する問題で、cloneしたリポジトリ内のファイルの fileformatをいくつか見てみると、確かにすべてDOS形式になっていた。


試したこと

適当にググって、以下のことを試した。

clone時の改行コードの変換設定を変更

Cygwin内で以下のコマンドを実行。

> git config --global core.autocrlf input

~/.gitconfigに以下の設定が追加されていることを確認。

……
[core]
    autocrlf = input
……

この状態でリポジトリを再cloneするも、解決せず。

どうやら.gitconfigが効いていない様子。

GitHubから直接ZIPファイルを落とす

さすがにファイルフォーマットはunixになっていて、デプロイも問題無く行うことができた。

しかし、ZIPファイルでダウンロードしてきたリポジトリには.gitフォルダが作成されないので、 リポジトリに変更があった際にgit pullできず、その都度最新のZIPを落として展開……などという 無駄につらい作業が発生してしまう。

また、この手段では今回の問題の本質的なところは解決せず、別のリポジトリを取得して実際に開発を行う場合に 結局同じ問題が発生することになるので、この案は最悪の手段として一旦保留にした。


解決

何気なくwhich gitしてみたら、なんと以下のように表示された。

> which git
/cygdrive/c/Program Files/Git/cmd/git

以前同機にインストールした、Git for Windowsのgitコマンドのパスだ。 原因はこれだった。

Git for Windows~/.gitconfigではなくWindowsユーザーフォルダ直下の.gitconfigを見に行くため、 ~/.gitconfigをいくら編集しても意味が無かったということだった。

Git for Windowsはもう使っていなかったのでアンインストールし、Cygwinのsetup.exeでgitをインストールすると問題が解決した。

setup.exeでgitをインストールするのを忘れていて、かつGit for Windowsのおかげでgitコマンドが使えてしまっていたせいで時間をとられてしまった。

MacBook Pro に Hammperspoon を導入した

マカーの仲間入り

先日、ついにMacBook Proを購入し、僕も無事マカーの仲間入りを果たした。
購入したのは、MacBook Pro 13インチ(Touch Barなし)だ。
Touch Barについては、現時点ではまだ必要性が感じられないことと、Escキーを多用する自分にとってはハードキーがなくなると精神的につらいこともあり、今回は購入を見送った。

MacBook のいいところ

なんといっても、デフォルトでシェルが使える。
Windows時代から、CygwinだのBabunだのを入れたり、自宅鯖を立ててSSHしていた自分にとっては、何の設定もせずにシェル環境が整っているmacOSは非常に良い物だ。
さっそくiTerm2を導入し、自分用の環境を整えた。
今まで育ててきたDOTFILESも、概ね良好に動作している。

不満点

しばらく使用してみて思ったのは、macOSのショートカットによるウィンドウ操作が、Windowsよりも不便だということ。

例えば、ウィンドウの切り替えはWindowsではAlt + TabmacOSだとCommand + Tabだが、macOSでは切り換えの対象がウィンドウ単位でなくアプリケーション単位になっている。

つまり、FinderやChromeなどを複数ウィンドウ開いている場合、それらをまとめて切り替えてしまう。同一アプリ内でウィンドウ切り替えを行うCommand + F1というショートカットキーもあるが、WindowsAlt + Tabに慣れきった身としては、アプリなんか関係なくウィンドウの切り替えを行いたいものだ。

また、Win + →Win + ←のような、ウィンドウを画面の左右半面に展開するといった動作も実現できない。

さらに、macOSの「ウィンドウ最大化」は言うなれば「ウィンドウ最適化」であり、画面全体にウィンドウが広がらない。Ctrl + Command + Fでフルスクリーンにはなるものの、今度はメニューバーが隠れてしまうなど、どうも思ったような挙動をしてくれない。

Hammerspoon を導入

上記のような問題を解決するために、Hammerspoonというアプリを導入した。
Hammerspoonは、設定をLuaによって記述できる、macOSの動作を自動化するためのツール。
アプリケーションやウィンドウ、ファイル、オーディオデバイス、クリップボードなど様々なものを制御できるらしいが、今回はショートカットキーによってウィンドウを操作するスクリプトを作った。

local prefix = {"cmd", "ctrl"}

-- Command + Ctrl + ↑ : フルスクリーン
hs.hotkey.bind(prefix, "Up", function()
    local win = hs.window.focusedWindow()
    local f = win:frame()
    local screen = win:screen()
    local max = screen:frame()

    f.x = max.x
    f.y = max.y
    f.w = max.w
    f.h = max.h

    win:setFrame(f)
end)

-- Command + Ctrl + ← : ウィンドウ左寄せ
hs.hotkey.bind(prefix, "Left", function()
    local win = hs.window.focusedWindow()
    local f = win:frame()
    local screen = win:screen()
    local max = screen:frame()

    f.x = max.x
    f.y = max.y
    f.w = max.w / 2
    f.h = max.h

    win:setFrame(f)
end)

-- Command + Ctrl + ← : ウィンドウ右寄せ
hs.hotkey.bind(prefix, "Right", function()
    local win = hs.window.focusedWindow()
    local f = win:frame()
    local screen = win:screen()
    local max = screen:frame()

    f.x = max.x + (max.w / 2)
    f.y = max.y
    f.w = max.w / 2
    f.h = max.h

    win:setFrame(f)
end)

-- Alt + Tab : ウィンドウ切り替え
hs.hotkey.bind("alt", "tab", function()
    hs.window.switcher.nextWindow()
end)

-- Alt + Tab : ウィンドウ切り替え(逆)
hs.hotkey.bind({"alt", "shift"}, "tab", function()
    hs.window.switcher.previousWindow()
end)

上記スクリプト~/.hammerspoon/init.luaにコピペし、Reload Configすると、コメントに書いてある通りの動作が実現できた。
ウィンドウの切り換えも、Windowsのように全てのアプリウィンドウを選択できるようになった。
アクティブなアプリによって挙動を変えるといったことも可能なようなので、今後も色々と試していきたい。

参考

Raspberry Pi 3 model B でエアコンをコントロールした話

やったこと

Raspberry Pi 3 model B に赤外線送受信モジュールを繋いで、エアコンのリモコン信号を解析
→ 解析した信号をRasPiから送信できるようにした

使ったもの

  • Raspberry Pi 3 model B
  • ブレッドボードとジャンパーワイヤ数本
  • 抵抗 270Ω
  • 赤外線リモコン受信モジュール(OSRB38C9AA)
  • 赤外線送信LED (OSI5FU5111C-40)

LIRCとの戦い

以前にRasPi2 model B+を使って同じことをした経験があったので、最近発売されたRasPi3でも挑戦してみた。
結論から言うと、RasPi2と同じ方法では実現出来なかった。

RasPi2ではLIRCというモジュールを使い、irrecordやmode2コマンドで信号解析、irsendコマンドによって信号送信ができた。
しかしRasPi3では、irrecord/mode2で信号解析することは出来たものの、irsendでエラーが発生し、信号送信が出来なかった。

参考: Slack経由で家の外からエアコンをon, offできる装置を、Raspberry Piで作ってみた。(しかも御坂美琴ちゃんが応答してくれる)

参考サイトとは、ピンの位置等が少々異なるので注意。

配線
f:id:s4kr4:20160724121555j:plain

lircインストール

$ sudo apt-get install lirc

/boot/config.txtに追記

dtoverlay=lirc-rpi
dtparam=gpio_in_pin=21
dtparam=gpio_out_pin=20

/etc/lirc/hardware.conf

……
LIRCD_ARGS="--uinput"

#Don't start lircmd even if there seems to be a good config file
#START_LIRCMD=false

#Don't start irexec, even if a good config file seems to exist.
#START_IREXEC=false

#Try to load appropriate kernel modules
LOAD_MODULES=true

# Run "lircd --driver=help" for a list of supported drivers.
#DRIVER="UNCONFIGURED"
DRIVER="default"
# usually /dev/lirc0 is the correct setting for systems using udev
DEVICE="/dev/lirc0"
MODULES="lirc_rpi"
……

ここで一度再起動

バイスファイルの確認

$ ls -l /dev/lirc*
crw-rw---- 1 root video 244, 0 Jul 23 21:02 /dev/lirc0

モジュールの確認

$ lsmod | grep lirc
lirc_rpi                6478  0
lirc_dev                8310  1 lirc_rpi
rc_core                16468  1 lirc_dev

信号解析

$ mode2 -d /dev/lirc0 | tee AIRON
space 4898472
pulse 3516
space 1710
pulse 460
space 404
pulse 457
space 1278
pulse 457
space 406
pulse 457
space 405
pulse 458
space 404
pulse 448
space 414
……
^C

$ mode2 -d /dev/lirc0 | tee AIROFF
……
^C

カレントディレクトリに、"AIRON" "AIROFF"というファイルができる。これらを数値のみのデータに変換し、/etc/lirc/lircd.confに書き込む。

# parse_pulse.rb
lines =  File.open(ARGV[0]).readlines
lines_without_first = lines.slice(1..-1)
puts lines_without_first.map{|line|line.split(" ")[1]}.join(" ")
$ ruby parse_pulse.rb AIRON
$ ruby parse_pulse.rb AIROFF

/etc/lirc/lircd.conf

begin remote

  name  aircon
  flags RAW_CODES
  eps            30
  aeps          100

  gap          200000
  toggle_bit_mask 0x0

      begin raw_codes
    name on
# AIR_ONの中身
3483 1748 423 492 370 1307 428 493 370 472 391 491 371 492 369
492 370 493 369 493 375 487 369 493 370 492 369 493 369 1315 422
491 370 493 369 494 367 495 368 493 368 494 368 500 362 1314 420
1368 368 1314 423 495 366 497 367 1319 413 497 366 497 368 442
418 497 365 496 366 496 368 494 366 496 366 496 374 487 367 497
……

    name off
# AIR_OFFの中身
3476 1747 421 468 394 1319 417 466 396 466 395 492 371 466 394
472 392 467 395 467 395 466 395 470 393 467 395 492 371 1338 398
466 395 469 393 469 395 467 394 468 394 470 392 469 393 1321 416
1325 411 1338 401 489 369 494 368 1323 414 468 392 494 369 467
395 468 394 468 394 493 369 467 395 493 370 468 394 492 369 467
……

      end raw_codes

end remote

ここまでは順調で、あとはirsendで信号を送信するだけ……だったのだが、最初に書いた通りここで躓いた。

$ irsend LIST "" ""
irsend: aircon

$ irsend LIST aircon ""
irsend: 0000000000000001 on
irsend: 0000000000000002 off

$ irsend SEND_ONCE aircon on
irsend: command failed: SEND_ONCE aircon on
irsend: hardware does not support sending

$ irsend SEND_ONCE aircon off
irsend: command failed: SEND_ONCE aircon off
irsend: hardware does not support sending

このように、airconコマンドは登録されているものの、実行ができない。

色々とググっていると、こちらで紹介されているように、Raspberry Pi2 model Bではlircが動作しないらしい。これと同じ現象が、RasPi3で起こっているのかもしれない。 記事にはRasPiのファームウェアをアップデートすると動作するかもしれない……とも書かれていたので、早速試してみる。

$ sudo apt-get install rpi-update
$ sudo rpi-update

しかし、RasPi3では、ファームウェアをアップデートしても問題は解決しなかった。

LIRCは諦めよう

もうLIRCではどうにもならなさそうなので、上記ページで紹介されていたプログラムを使って信号解析・送信をすることにした。

GPIO制御用ライブラリのインストール

$ git clone git://git.drogon.net/wiringPi
$ cd wiringPi
$ ./build

バージョン確認

$ gpio -v
gpio version: 2.32
Copyright (c) 2012-2015 Gordon Henderson
This is free software with ABSOLUTELY NO WARRANTY.
For details type: gpio -warranty

Raspberry Pi Details:
  Type: Pi 3, Revision: 02, Memory: 1024MB, Maker: Embest
  * Device tree is enabled.
  * This Raspberry Pi supports user-level GPIO access.
    -> See the man-page for more details
    -> ie. export WIRINGPI_GPIOMEM=1

scanir.c, sendir.cをコピペし、コンパイルする。

$ sudo gcc scanir.c -o scanir -lwiringPi
$ sudo gcc sendir.c -lm -o sendir -lwiringPi

wiringPiで使用するPIN番号を調べる。

$ gpio readall
 +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
 |   2 |   8 |   SDA.1 |   IN | 1 |  3 || 4  |   |      | 5V      |     |     |
 |   3 |   9 |   SCL.1 |   IN | 1 |  5 || 6  |   |      | 0v      |     |     |
 |   4 |   7 | GPIO. 7 |   IN | 1 |  7 || 8  | 0 | IN   | TxD     | 15  | 14  |
 |     |     |      0v |      |   |  9 || 10 | 1 | IN   | RxD     | 16  | 15  |
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 1 | IN   | GPIO. 1 | 1   | 18  |
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |
 |     |     |    3.3v |      |   | 17 || 18 | 1 | IN   | GPIO. 5 | 5   | 24  |
 |  10 |  12 |    MOSI |   IN | 0 | 19 || 20 |   |      | 0v      |     |     |
 |   9 |  13 |    MISO |   IN | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |
 |  11 |  14 |    SCLK |   IN | 0 | 23 || 24 | 1 | IN   | CE0     | 10  | 8   |
 |     |     |      0v |      |   | 25 || 26 | 1 | IN   | CE1     | 11  | 7   |
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |
 |   5 |  21 | GPIO.21 |   IN | 0 | 29 || 30 |   |      | 0v      |     |     |
 |   6 |  22 | GPIO.22 |   IN | 1 | 31 || 32 | 0 | IN   | GPIO.26 | 26  | 12  |
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | OUT  | GPIO.28 | 28  | 20  |
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+

Physical欄が実際のPIN番号、wPi欄がwiringPiで使用するPIN番号。
赤外線受信にはGPIO.29、送信にはGPIO.28を使用していたので、プログラムを以下のように使用する。

$ sudo ./scanir air_on.data 29
write file: air_on.data
scaning pin: 29 (wiringpi)
max keep time: 40(ms)
Infrared LED scanning start.
Pressed Ctrl+C, this program will exit.

# ここで受信モジュールに向けてリモコンのONボタンを押下
Scanning has been done.

$ sudo ./scanir air_off.data 29
write file: air_off.data
scaning pin: 29 (wiringpi)
max keep time: 40(ms)
Infrared LED scanning start.
Pressed Ctrl+C, this program will exit.

# ここで受信モジュールに向けてリモコンのOFFボタンを押下
Scanning has been done.

カレントディレクトリに、"air_on.data" "air_off.data"の2つのデータファイルができる。このファイルを、送信用プログラムに渡してやる。

$ sudo ./sendir air_on.data 1 28

これでようやく信号が送信され、無事エアコンのON/OFFができた。