ゆず日記

戦う Vimmer 兼 Dvorakユーザ 兼 Kinesisユーザ 兼 おぺらー が戦わないブログ

OS X maverics で Fn キーの機能を簡単に切り替えられるようにする

やりたいこと

FTL では F1, F2, etc. のキーを多用するが, 普段は明暗/音量切替を多用する為, ファンクションキーのモードを簡単に切り替えたい.

f:id:Yuzuemon:20131122170542p:plain
この設定の切り替え.


AppleScript

アプリケーションでは既に Mac App Store - Palua があるが, 環境設定の切り替えだけなのでこれって AppleScript でも出来るよねーと思って書こうと思ったらこちらも既にあった.

--Check if GUI Scripting is Enabled
tell application "System Events"
    if not UI elements enabled then
        set UI elements enabled to true
    end if
end tell

--Enable/Disable "Use all F1, F2, etc. keys as standard function keys" option in Keyboard & Mouse Preference pane and close System Preferences
tell application "System Events"
    tell application "System Preferences"
        reveal anchor "keyboardTab" of pane "com.apple.preference.keyboard"
    end tell
    click checkbox 1 of tab group 1 of window 1 of application process "System Preferences"
end tell
if application "System Preferences" is running then
    tell application "System Preferences" to quit
end if

osx - Enable/Disable Fn keys from the command line on the Mac - Stack Overflow

後はこの Script を簡単に呼び出せるようにすればいい.


Automator での実装

Quicksilver も Alfred も使っていないので, Spotlight + Automator での実装を行う.
まず Automator を起動し, Application として新しいワークフローを立ち上げる.

f:id:Yuzuemon:20131122165227p:plain



次に, Action の中から "Run AppleScript" を探し出し, 右ペインへドラッグ & ドロップする. ("AppleScript" などで検索するとすぐ見つかる.)

f:id:Yuzuemon:20131122165535p:plain



そして, テキストエリア内に先程のコードをちょっと短くした*1 以下の AppleScript コードを書き込む.

--Enable/Disable "Use all F1, F2, etc. keys as standard function keys" option in Keyboard Preference pane and close System Preferences
tell application "System Events"
	tell application "System Preferences"
		reveal anchor "keyboardTab" of pane "com.apple.preference.keyboard"
	end tell
	click checkbox 1 of tab group 1 of window 1 of application process "System Preferences"
end tell
if application "System Preferences" is running then
	tell application "System Preferences" to quit
end if

f:id:Yuzuemon:20131122174010p:plain
また今回は引数不要の為, テキストエリア下の Options 内の "Ignore this action's input" にチェックを入れる.
テスト実行すると, Dock 内の環境設定がちょっと起動した後にすぐ終了する筈. テスト実行の度に F1 等を押してみて Fn 機能が切り替わっているようなら成功.

テスト実行に失敗する場合

f:id:Yuzuemon:20131122173442p:plain
こんな感じのエラーが出た場合には, 環境設定から, Automator によるコントロールを許可する必要がある.

環境設定 > セキュリティとプライバシー > プライバシータブ から, アクセシビリティを選択し, Automator にチェックを入れる.
f:id:Yuzuemon:20131122171130p:plain

この状態でもう一度実行すると, キチンと動作するようになる.

Automator Application の書き出しと実行

Automator 上での動作が確認できたら, テキトーにファイル名を付けて保存する. (自分が呼び出し易い名前にしとく. ここでは "change_fn_mode" とした.)
保存したら今度は spotlight から呼び出して実行してみる.
f:id:Yuzuemon:20131122171841p:plain

きっとまたエラーが出るか, もしくは Accessibility の設定を促す画面が出る.
f:id:Yuzuemon:20131122173442p:plain
f:id:Yuzuemon:20131122173457p:plain

再度, 環境設定 > セキュリティとプライバシー > プライバシータブ から, アクセシビリティを選択し, 今度は自分が作った Application ファイル名にチェックを付ける.
f:id:Yuzuemon:20131122172936p:plain


これで Application も動作するようになる筈だ.

自分がハマった所

  • Mavericks になって Accessibility の設定箇所が変わった.
  • Automator Application内のコードや設定を変更する度に, System Preferences 内の Accessibility のチェックを付け直さないと再度エラーが出る.
    • Debugで設定を変更する度にエラーが出て困った.
  • AppleScriptの楽な呼び出し方が未だに分からない.
    • 今回の実装は, はじめは QuickSilver や Alfred で試したのだが上手く行かなかった. 多分その際にも Accessibility 周りで引っ掛かってたのだと思う.
    • Alfred は PowerPack を導入しないとフルに使えない気がしつつ, 尚且つそこまでメリットをまだ感じられないのでイマイチ気が乗らない.

OS X: GUI Scripting - Accessibility Access Controls

*1:Mavericks では UI elements enabled を Script 内で有効に出来ない模様.

Mac版 FTL: Faster Than Light を日本語化する

f:id:Yuzuemon:20131121114039p:plain

つー助教授*1の影響で FTL: Faster Than Light を始めた.

つー助教授は他に Civilizationシムシティ などの動画をアップしているが, ゲームを初心者に優しく, かつ面白く紹介しているので見ていて楽しい.



Civilization は英語でも大丈夫だったので FTL も英語のまま... と思ったけど, 何分テキスト量が多いのと, 翻訳プロジェクトの Google スプレッドシート を眺めてたら 「FTL らしさ」 を追求したという翻訳陣の成果を垣間見たくなったので日本語化してみた.


Mac版 FTL: Faster Than Light の 日本語化

ダウンロード

日本語化 - FTL: Faster Than Light JP Wiki - Seesaa Wiki(ウィキ) を参考に,

をダウンロードする.

Grognak's Mod Manager の現時点の最新版の v 1.7.0 では python 2.6 以下が要求されるので, python 2.7系で動く v 1.6.0 の方がオススメ. *2

ちなみに同様の Mod Manager で Slipstream Mod Manager というのがあるが, こちらは要 Java (JDK) だったのでスルーした.

解凍・設置

ダウンロードしたファイルをすべて解凍した後, 日本語化MODと日本語化フォント内のファイルを Mod Manager 内の mods ディレクトリへ移動する.

こんな構成になっていればOK.

Grognaks-Mod-Manager
├── __init__.py
├── ftldat.py
├── ftldat.pyc
├── license.txt
├── main.py
├── modman-log.txt
├── modman.exe
├── modman.ini
├── mods
│   ├── Beginning\ Scrap\ Advantage.ftl
│   ├── Hiragana\ font.ftl
│   ├── Katakana\ font.ftl
│   ├── Nihongo<日付>.ftl
│   ├── NihongoID<日付>.ftl
│   ├── modorder.txt
│   └── readme.txt
└── readme.txt

Mod Manager の実行

Terminal から main.py を実行する.

% python main.py

GUI画面で お好みで Hiragana font か Katakana font と, Nihongo<日付> を選択してPatchをあてれば完了.*3
f:id:Yuzuemon:20131121113806p:plain


起動して, 日本語化チェック.
f:id:Yuzuemon:20131121113951p:plain

ちなみに

*1:つー助・教授 で助教授では無い.

*2:Mavericks のdefaultは python 2.7.5. 今さらpython 2.6系を入れるのはちょっと...

*3:NihongoID<日付>を適用すると, デバッグ用に全ての翻訳箇所にIDが付く.

.vimrcファイルを分割する

自分の .vimrc は600行程なので用途ごとに .vimrc を分け、各ファイルをこんな感じで読み込んでいる。

$HOME/dotfiles/.vimrc

if filereadable(expand('$HOME/dotfiles/.vimrc.neobundle')) " ファイルが読み込み可能かチェック
  source $HOME/dotfiles/.vimrc.neobundle " .vimrcファイル読み込み

  if filereadable(expand('$HOME/dotfiles/.vimrc.plugin'))
    source $HOME/dotfiles/.vimrc.plugin
  endif
endif

if filereadable(expand('$HOME/dotfiles/.vimrc.filetype'))
  source $HOME/dotfiles/.vimrc.filetype
endif

if filereadable(expand('$HOME/dotfiles/.vimrc.office'))
  source $HOME/dotfiles/.vimrc.office
endif

ファイル毎の用途

.vimrc .vimrc本体
.vimrc.neobundle neobundle.vimで読み込むplugin記述ファイル
.vimrc.plugin .vimrc.neobundleで読み込むplugin用設定記述ファイル
.vimrc.filetype filetypeごとの設定記述ファイル
.vimrc.office 仕事のみで使う設定記述ファイル

仕事場用の .vimrc.office は yuzuemon/dotfiles · GitHub に入れてないのが、存在チェックしているので読み込まれずエラーが出ることもない。

ただ github の dotfiles を眺めているとあまり見かけないやり方なので、他にもっといい管理方法があるのかも。

追記(2013/11/17 2:11)

ワイルドカードで自動読み込みできるとのアドバイスをいただきました。


さっそく反映。分割ファイルを conf.d ディレクトリにぶっ込み、以下2行で分割ファイルを読み込めるようになりました。

set rtp+=$HOME/dotfiles/.vim/
runtime! conf.d/*.vim

差分:
Comparing 551ee9f8b75cfb1228109625c4a396a5e1eb41dc...188879bf20455a57d4256c8d33a6ea488dd8b6a3 · yuzuemon/dotfiles · GitHub

JavaScriptで選択範囲内のDOMを取得する

選択範囲内のDOMを取得するやりかた。


ここでは例として、

  • マウスドラッグでWebページ内のコンテンツを選択した際に、
  • 選択範囲内のDOMを取得して、
  • その中のa要素を一括取得し, 別タブで開く

という処理を実装してみる。

document.addEventListener('mouseup', function(){
  var selectionObject = window.getSelection(); // 選択範囲(selectionオブジェクト)の取得
  var selectionDOM = selectObject.getRangeAt(0).cloneContents(); // 1つ目の選択範囲のDocumentFragmentをコピー
  var links = selectionDOM.querySelectorAll('a');
  
  for(var i = 0, l = links.length; l > i; i++){
    window.open(links[i].href);
  }
  selectObject.removeAllRanges(); // 選択範囲の解除
}, false);


参考:
selection - Web API リファレンス | MDN
range - Web API リファレンス | MDN
Range.cloneContents - Web API リファレンス | MDN


Chrome Web Store - LinkMiner (Open all links)でも使われてそう。

Grunt で livereload 環境を作ったお話。

Grunt を使うようになって早数ヶ月。
ガリガリ弄るってことはないのですが、何気なく使う機会は多いのでちょっと纏め。

Gruntの要約

3行で纏めると、

  • node.js で動作するタスク実行ツール
  • livereload や jshint, minify, less, Sass 生成とかを自動実行できる
  • 設定は Gruntfile.js に記述する

諸々全部入りで書こうとすると、何がなんだか分からない & 自分も全部理解していない為、まずは livereload (ファイル変更時にブラウザが自動リロードしてくれる) 環境の構築だけ纏める。

準備

node.js, npmのインストール

node.js からインストール。
node.js の複数バージョン管理をするのであれば、nodebrew とか nvm とかから入れる。
npm (node.jsのパッケージ管理ツール)は、node.js ver.0.6.3(2011/11/25リリース) 以降は node.js 内にインクルードされているので node.js をインストールすれば入る。

grunt-cli をグローバルにインストールする

grunt の0.4.0(2013/02/18リリース)以降では、grunt-cli をグローバルにインストールする必要がある。
(それ以前は grunt をグローバルにインストールする必要があったらしい。)
ここググって過去の日本語記事をあたっても上手く行かずに詰まった...
結局公式ドキュメントを見て解決できたのだが、最初から公式ドキュメントを見るべきだと痛感。
Getting started - Grunt: The JavaScript Task Runner

$ npm install -g grunt-cli # nvm 使っていない人は sudo が必要

以降の作業は、各サイトやプロジェクト用のディレクトリの下でインストールしていく。

$ mkdir my-project-name
$ cd ./my-project-name

package.jsonの設置

まず node.js のパッケージを管理する為の package.json を設置する。
package.json に必要なパッケージリストとバージョンを書いておくと、簡単にパッケージインストールできるようになる。
Ruby でいうなれば、Gemfile。

以下の内容を package.json というファイル名でディレクトリ下に設置する。

{
  "name": "my-project-name",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-connect": "*",
    "grunt-contrib-watch": "*"
  }
}

livereloadの最小構成に必要なパッケージは3つだけ。

  • grunt: Grunt本体
  • grunt-contrib-connect: Grunt上で動くWebサーバ。
  • grunt-contrib-watch: ディレクトリ配下のファイルをWatchし、ファイル変更をトリガーに予め設定した処理を行うことができるGruntのプラグイン*1

上の jsonGetting started - Grunt: The JavaScript Task Runner のコピペ + プラグイン部分を改変したもので、grunt 以外のプラグインのバージョンは今回は "*" にして特に規定していない。

Gruntとgruntpluginsのインストール

上述の通り、package.json に記述されたプラグインは、npm install コマンドで node_modules ディレクトリに一括インストールできる

$ npm install --save-dev // package.json 側に devDependencies と書いてあれば --save-dev は無くてもいい。

package.json 側で devDependencies、または --save-dev オプション付きでインストールすると、開発向けの依存モジュールとしてインストールされる。本番との利用モジュールを区別できるということらしい。

Gruntfile.jsの設置

Grunt の設定ファイルである Gruntfile.js を、gruntjs/grunt-contrib-connect · GitHub を見ながら設定を書いていく。

ここはもう Gruntfile.js 直接見てもらった方が早い。
(説明も兼ねて若干冗長に書いています。)

// 'use strict';

module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    // grunt-contrib-connectの設定(Webサーバの設定)
    connect: {
      site: { // オプション未設定の為、空オブジェクト
      }
    },

    // grunt-contrib-watchの設定(ウォッチ対象の設定)
    watch: {
      html_files: {
        files: '**/*.html' // ウォッチ対象として、ディレクトリ配下の*.htmlを指定
      },
      options: {
        livereload: true // 変更があればリロードするよ
      }
    }
  });

  // Load tasks(grunt実行時に読み込むプラグイン)
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-watch');

  // Default tasks(grunt実行時に実行するタスク)
  grunt.registerTask('default', ['connect', 'watch']);
};

grunt, livereloadの実行と、ブラウザ側の livereload プラグインのインストール

テキトーなindex.htmlを書いて同じ階層に設置し、

./my-project-name
  Gruntfile.js
  node_modules/
  package.json
  index.html

gruntコマンドを実行する

~/my-project-name $ grunt
Running "connect:site" (connect) task
Started connect web server on localhost:8000.

Running "watch" task
Waiting...

この状態で localhost:8000 にアクセスすると index.html をブラウジングできるようになる。

併せて、ブラウザ側にも livereload 用の拡張をインストールする。
Chromeの場合には、Chrome Web Store - LiveReload
Firefoxなど他のブラウザにもあるので、適宜インストールする。

ブラウザ拡張の livereload を有効にした状態で、この時に index.html を編集すると、自動的にリロードしてくれるようになる。

お疲れ様でした。

以下、Gruntfiles.jsの補足

grunt-contrib-connectの設定

Webサーバの設定を記述している。
options以降にポートやホスト名, プロトコルを指定可能。

connect: {
  site: {
    options: {
      hostname: '*',
      port: 9000
    }
  }
}

hostnameはdefaultで'localhost'、もしlocalhost以外でもアクセスしたい場合には hostname: '*' と設定すると別環境からもIPアドレス指定でアクセス可能になる、ステキ。


ちなみに、複数サイトを別ポートで同時起動可能。

connect: {
  site1: {
    options: {
      port: 9000,
      base: 'www-roots/site1'
    }
  },
  site2: {
    options: {
      port: 9001,
      base: 'www-roots/site2'
    }
  }
}

gruntjs/grunt-contrib-connect · GitHub

// grunt-contrib-watchの設定

前述の通り、ファイル変更をトリガーとするプラグインであるgrunt-contrib-watchの設定部分になるが、このプラグインにlivereloadもbuilt-inされている為、ここにlivereloadの設定を記述している。

livereload(というかoptions)の書き方は色々あり、

watch: {
  static_files: {
    files: ['**/*.html', '**/*.css']
    options: {
      livereload: true // static_filesで指定したfilesに対してのみlivereloadオプションを付与
    }
  },
  js_files: {
    files: '**/*.js'
  }
}

みたいに、watchの対象グループをhtml, cssに絞り、jsは対象外にする書き方や、

watch: {
  static_files: {
    files: ['**/*.html', '**/*.css']
  },
  js_files: {
    files: '**/*.js'
  },
  options: {
    livereload: true, // watch対象すべてに対してlivereloadオプションを付与
    spawn: false
  }
}

のようにwatch対象全てをlivereloadする書き方も出来る。

defaultでtrueのspawnオプションは、子プロセスでタスクを実行するかどうか指定するオプション。ファイル数が多いなどで重い場合には、spawn: falseを指定すると解消される場合がある。


ちなみにいろんなブログみた限り全然言及されてなかったけれど、filesは配列で複数指定できる

files: '**/*.html'  //ディレクトリ以下のすべての.htmlファイル
files: '**/*' //ディレクトリ以下のすべてのファイル
files: ['**/*.html', '**/*.css'] // ディレクトリ以下のすべてのhtml, cssファイル

gruntjs/grunt-contrib-watch · GitHub


"Fatal error: EMFILE: Too many opened files."とか言われる時。

ファイル数が多い場合にerrorが出る。OSのulimitの値を大きくすることで解消できる

$ ulimit -n // 現在のプロセス数を確認
256

$ ulimit -n 1024 // プロセス数を1024に変更

なお、都度変更するのが手間な場合には、launchctlで規定値を変更できる

$ launchctl limit // 現在のmaxfilesを確認
        cpu         unlimited      unlimited
        filesize    unlimited      unlimited
        data        unlimited      unlimited
        stack       8388608        67104768
        core        0              unlimited
        rss         unlimited      unlimited
        memlock     unlimited      unlimited
        maxproc     709            1064
        maxfiles    256           256

$ launchctl limit maxfiles 2048 2048 // default maxfilesを2048に変更

osx snow leopard - How to change default ulimit values in Mac OS X 10.6? - Super User

grunt-contrib-livereload プラグインは?

livereload 用にそのものズバリな grunt-contrib-livereload というプラグインがあるが、現在では gruntjs/grunt-contrib-livereload · GitHub を見ての通り grunt-contrib-watch プラグインに内包されている為不要。

ほか

jshint, minify, less, Sass自動生成 などについても纏めようと思ったけど長過ぎたのでここまで。
取り敢えず grunt 使えば出来ます。

終わりに

grunt, livereloadを導入にあたって、下記サイトを参考にさせていただきました。
GruntでLivereload(自動更新)をやってみた! | SAITEI no CHINJUU!!!(最低の珍獣)
grunt を軽く触ってついでに livereload させてみた - 憧れ駆動開発

自分の理解力が乏しい所為もあって、ただ見ながらやるだけでは理解できなかったのですが、
このエントリの為に公式ドキュメントを見たり、検証しながら書くことで大分理解できたと思う。
やっぱり定期的にアウトプットしないダメですね…。

しかし5月に教えてもらって5月に入れたのに、ブログに纏められたのが10月…。もっとペースあげねばw

*1:grunt-contrib-* をgruntpluginと呼ぶらしい。