MacでenthumbleのHJKL(vi) modeをKarabinerで再現
2015/03/15 追記
こちらの方法の方が簡単です!無変換キーも無効にならない!qiita.com
### 追記ここまで ###
Windowsでenthumbleを使っているのですが、無変換キーをベースとしたキーバインドに慣れきってしまっており、Macでも同じように無変換+HJKLで移動したり、無変換+SpaceでEnterにしたくなりました。
そこでKarabiner(旧KeyRemap4MacBook)を使って再現してみました。
無変換(=英数)キーがデフォルトではModifierFlagに登録されていないため、別途登録する必要があるのがミソです。private.xmlは以下の通り。
# 一部オレオレ設定が入っています。
<?xml version="1.0"?> <root> <list> <item> <name>Private</name> <list> <item> <name>Enthumble Mock</name> <list> <modifierdef>JIS_EISUU</modifierdef> <item> <name>change JIS_EISU to modifier key</name> <identifier>private.modifier.jis_eisuu</identifier> <autogen>__KeyToKey__ KeyCode::JIS_EISUU, KeyCode::VK_MODIFIER_JIS_EISUU</autogen> </item> <item> <name>EISUU + HJKL -> Left,Down,Up,Right</name> <identifier>remap.eisuu_hjkl_to_cursor</identifier> <autogen>__KeyToKey__ KeyCode::H, ModifierFlag::JIS_EISUU, KeyCode::CURSOR_LEFT</autogen> <autogen>__KeyToKey__ KeyCode::J, ModifierFlag::JIS_EISUU, KeyCode::CURSOR_DOWN</autogen> <autogen>__KeyToKey__ KeyCode::K, ModifierFlag::JIS_EISUU, KeyCode::CURSOR_UP</autogen> <autogen>__KeyToKey__ KeyCode::L, ModifierFlag::JIS_EISUU, KeyCode::CURSOR_RIGHT</autogen> </item> <item> <name>EISUU + AE -> Home,End</name> <identifier>remap.eisuu_ae_to_home_end</identifier> <autogen>__KeyToKey__ KeyCode::A, ModifierFlag::JIS_EISUU, KeyCode::CURSOR_LEFT, ModifierFlag::COMMAND_L</autogen> <autogen>__KeyToKey__ KeyCode::E, ModifierFlag::JIS_EISUU, KeyCode::CURSOR_RIGHT, ModifierFlag::COMMAND_L</autogen> </item> <item> <name>EISUU + UD -> PageUp,PageDown</name> <identifier>remap.eisuu_ud_to_page_up_down</identifier> <autogen>__KeyToKey__ KeyCode::U, ModifierFlag::JIS_EISUU, KeyCode::PAGEUP</autogen> <autogen>__KeyToKey__ KeyCode::D, ModifierFlag::JIS_EISUU, KeyCode::PAGEDOWN</autogen> </item> <item> <name>EISUU + Spase -> Enter</name> <identifier>remap.eisuu_space_to_enter</identifier> <autogen>__KeyToKey__ KeyCode::SPACE, ModifierFlag::JIS_EISUU, KeyCode::ENTER</autogen> </item> <item> <name>EISUU + N -> Backspace (Delete)</name> <identifier>remap.eisuu_n_to_backspace</identifier> <autogen>__KeyToKey__ KeyCode::N, ModifierFlag::JIS_EISUU, KeyCode::DELETE</autogen> </item> </list> </item> </list> </item> </list> </root>
EclipseのShell (bahs)エディタ
通常のTextエディタだと見づらいので...。
Help→Install New Softwares...で以下のURLを追加してインストール。
http://sourceforge.net/projects/shelled/files/shelled/update/
HerokuにJavaアプリをデプロイしてみた。
Herokuを試してみたかったので、https://devcenter.heroku.com/articles/getting-started-with-heroku-eclipseに従ってやってみる。
EclipseにHerokuプラグインをインストールする。
Eclipseの[Help]→[Install new Software] で以下のサイトを追加する。
- Name: Heroku
- Location: https://eclipse-plugin.herokuapp.com/install
表示された「Heroku Eclipse Integration」にチェックを入れて[Next]を2回。表示されたライセンスをacceptして[Finish]。インストール後にEclipseが再起動される。
APIキー設定
Ecliseで[Window]>[Preferences]>[Heroku]を選択。[Email]、[Password]を入力して、[Login]ボタンを押す。[API Key]が自動的に入力される。
SSHキーの作成と設定。
eGitを使ってHerokuと接続するために必要。Eclipseで[Window]>[Preferences]>[General]>[Network Connections]>[SSH2]を選択する。[Key Management]タグを選択し、[Generate RSA Key...]を押す。[Save Private Key...]を押して、[OK]を押してファイルとして保存する。保存したファイルをPreferencesの[Heroku]にて、[Load SSH Key]を押して読み込ませ、[Add]ボタンでHerokuにSSHキーを追加する。
テンプレートからアプリを作成する。
[File]>[New]>[Other]>[Heroku]>[Create Heroku App from Template]を選択し、[Next]。テンプレートを選択し、アプリ名を設定する。アプリ名を指定しない場合、Herokuが自動的にアプリ名を設定してくれる。
テンプレートを「Spring MVC & Tomcat application」、アプリ名を「heroku-spring-mvc-sample」とした。
が、失敗。どうやらSSH系の設定が良くないらしい。
Gitリポジトリからcloneする。
ググったところどうやら1回、eGitでHerokuからcloneすると良いらしい。Heroku側にアプリケーションはできていたので、Herokuのアプリケーションの[Setting]>[Info]に記載されているgitのURLからeGitでCloneする。
Protocolなどは選ばずに、そのまま[Next]>[Next]>[Finish]。
Working Directoryを右クリックして、[Import Projects...]。[Import as general project]を選んで[Finish]。
Java EEのPespectiveに戻って、インポートされたプロジェクトを右クリックして、[Configure]>[Convert to Maven Projects]、でMavanプロジェクトとなる。そのままEclipse上で[Run as]>[Run on Server]で、ローカルTomcat上で起動できる。
動作確認
Herokuのアプリケーション管理画面のアプリケーション名の横にあるリンクか、SettingsのDomainsでドメインを確認してアクセスしてみる。こんなページが出れば成功。
「./people」にアクセスすればサンプルのアプリが確認できる。
もし、以下の画面が出てしまったら、デプロイ後に1時間以上アクセスがなくて停止してしまっている。再起動すればOK。
EclipseでHerokuの[My Heroku Applications]Viewを開いて、アプリケーションを右クリック→[Restart]を選択すれば起動する(管理画面からもできそうな気はするが...)。
以上
とりえあずサンプルは動かすことができた。gitリポジトリにコミットするだけでリリースされるのはすごいね。
「Web x Java - HTML5で進化したWeb標準を、Java技術でどう扱うのか? -」に参加してきました。
久しぶりにセミナに参加してきたのでメモ。
関連リンク
- Web✕Java - HTML5で進化したWeb標準を、Java技術でどう扱うのか? - : ATND
- Toggetter(出てきたら)
今のWeb標準とStruts/Javaの問題(仮)
Strtusが対応していないもの。
Strutsが対応していない!
→ 独自flameworkの開発!
→ ベンダー(SIer)ロックイン&技術のガラパゴス化。
# カスタムタグ作りすぎて、flameworkに沿ったJSPの書き方を
# 一から覚え直したりね...。
Web界はHTML5でガラパゴス化(ブラウザ間の差異)から脱出(標準化)を進めている。
→ サーバサイド(Java)側はどうする???
Java EE の概要と HTML 5 の取り組み
- Java EE7, html5(not 発表資料)
10年前はStruts+Spring+Hibernate(通称SSH)が流行りだったが今はどうか。
寺田さんがもうやめましょうと訴えたいのは以下の2つ。
2012年のEclipse ServeyでもStruts1.x, 2.xを使いたい人は殆どいなかった。
Struts+Spring+Hibernateはメンテナンスコストが大!
今後Strutsでバグが出たら、誰がその修正の影響範囲を調査・試験する??
→ その点、Java EE ならJSF+CDI+JPAをトータルで管理してますよー。
# JBossの保守はサポートしてくれるらしい。
# SAStrutsもStrutsにバグ出たら治すって言ってた気がする。
# それなりに保守される上位flameworkを使っていれば平気?
Java EE 7ではWebSocketやJAX-RSが標準装備されているので、viewとmodelをサーバ側で結合せずに、別々に取得することができる(modelだけ取得可能)。
WebSocket vs JAX-RS?
→WebSocketはHTTP Headerなどを送信するのがはじめの1度のみなので、パフォーマンス的にはWebSocketが有利か。
Java EE 7の良い所
# 作ろうと思ったことがなかった...。
# 今までは作るとAPサーバと別プロセスにスレッドができて管理しづらいらしい。
Strutsから移行する人のためのJSF基礎
なぜJSF?
作れるUI
- JavaScriptレスでAjax。
# 普通のJavaScriptからのAjaxは使えるのかな?
# その時はJAX-RSでも使えばよいのかしら。
拡張ライブラリ
- PrimeFaces
- RichFaces
- ICEFaces
拡張ライブラリ使用上の注意
「※ただし、ブラウザ最新版に限る。」
移行ポイントの詳細はスライドを参照。
- managed-baenの定義はXMLでもアノテーションでも。
- JSPと違ってServletに変換されない→エラー時はStackTraceにXHTMLの行数が表示。
- 画面側でのvalidationを標準装備。
# サーバ側でのvalidationとエラー時の表示は共通化できるのかしら?
- RequestProcessor の processXXX 系の処理は全てPhaseListenerで外から実装できる。
JSF利用時の注意
Maven, Seleniumを使った受け入れテストの自動化
Apache Maven 3クックブック Javaソフトウェア開発のための特選レシピ集
- 作者: Srirangan,長尾高弘
- 出版社/メーカー: アスキー・メディアワークス
- 発売日: 2012/03/02
- メディア: 大型本
- 購入: 7人 クリック: 89回
- この商品を含むブログ (12件) を見る
上記の書籍を使ってMavenの勉強中なのだが、「2.6 受け入れテストを自動化する」で書籍の内容通りにコーディングをしてもうまく動作しなかったので、うまく動作した結果を残しておく。
Mavanプロジェクトの生成
Webアプリケーションプロジェクトを生成する
$ mvn archetype:generate -DgroupId=net.kuronicle.maven -DartifactId=webappsample -DarchetypeArtifactId=maven-archetype-webapp
jUnitのバージョン設定
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.1</version> <scope>test</scope> </dependency>
Seleniumライブラリの追加
pom.xmlのdependenciesに以下を追加することで、Seleniumに必要なライブラリがインポートされる。
<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.24.1</version> <scope>test</scope> </dependency>
テスト対象の用意
デフォルトで存在する/src/main/webapp/index.jspを利用する。
<html> <body> <h2>Hello World!</h2> </body> </html>
Seleniumテストコードの作成
/src/test/java/Selenium2Example.javaを作成する。
import static org.junit.Assert.*; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; public class Selenium2Example { @Test public void testHelloWorld() { WebDriver driver = new FirefoxDriver(); try { driver.get("http://localhost:8080/webappsample/index.jsp"); WebElement element = driver.findElement(By.tagName("h2")); assertEquals("Hello World!", element.getText()); } catch (Exception e) { fail(e.getMessage()); } finally { driver.quit(); } } }
integration-testフェーズの設定
pom.xmlにintegration-testの前後でJettyを起動・停止する設定と、integration-testで先ほど作成したSeleniumテストケースを実行する設定を追加する。
<build> <finalName>webappsample</finalName> <plugins> <!-- JDK1.6でコンパイル --> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <!-- integration-testフェーズ前後にJetty起動停止 --> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>${maven-jetty-plugin.version}</version> <executions> <execution> <id>start-jetty</id> <phase>pre-integration-test</phase> <goals> <goal>run</goal> </goals> <configuration> <scanIntervalSeconds>0</scanIntervalSeconds> <daemon>true</daemon> </configuration> </execution> <execution> <id>stop-jetty</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> <configuration> <stopKey>foo</stopKey> <stopPort>9999</stopPort> </configuration> </execution> </executions> </plugin> <!-- integration-testフェーズでSeleniumテストケース(*Selenium*.java)を実行 --> <plugin> <artifactId>maven-surefire-plugin</artifactId> <executions> <execution> <id>selenium-test</id> <phase>integration-test</phase> <goals> <goal>test</goal> </goals> <configuration> <includes> <include>**/*Selenium*.java</include> </includes> </configuration> </execution> </executions> </plugin> </plugins> </build>
integration-testの実行
integration-testを実行する。Firefoxが自動的に立ち上がり、試験が実行される。
$ mvn integration-test
以上。
なぜ書籍のサンプルコードが動かなかったのかは結局わからず…。
レジストリをいじってキーボードレイアウトをカスタマイズ
キーボードにHappyHackingKeybordLite2を使っているんだけど、WindowsキーがFnキーを利用しないと機能しないため、面倒。
ということで半角/全角キーと左Windowsキーを入れ替えました。
- [スタート]→[ファイル名を指定して実行]→「regedit」と入力して[OK]
- 「HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout」を右クリック
- [新規]-[バイナリ値]
- 新しい値の名前を「Scancode Map」とする
- 「Scancode Map」をダブルクリックし、以下の値を設定
00 00 00 00 00 00 00 00
03 00 00 00 5B E0 29 00
29 00 5B E0 00 00 00 00
- 再ログイン or 再起動
設定値の詳細などは下記のサイトを参照のこと。
Windows Vista/XP/2000/NT4.0のキー配列の変更方法
ちなみに自分は、
に設定しているので半角/全角キーをWindowsキーにしてしまったw
Google App Engine for Java でデータストアに保存したデータからメールを送信
Google App Engine for Java で受信したメールをデータストアに保存 の続き。
データストアに保存したメールデータを利用してメールを送信するよ。
データストアから受信メールデータを取得
受信後すぐに送信するので本当はデータストアから取得する必要はないのだけどw
sentDateで並び替えて最新の1件を取得。
// データストアから最新の1件を取得 String query = "select from " + ReceivedMail.class.getName() + " order by sentDate desc range 0,1"; List<ReceivedMail> mailList = (List<ReceivedMail>) pm.newQuery(query).execute(); ReceivedMail storedMail = mailList.get(0);
取得した受信メールデータを送信メールに入力して送信
送信元に返信。件名はそのままで、本文には送信元、送信先、件名、本文を設定。
件名は文字コードを設定しないと文字化けした。本文は何故か平気だった。
if(!(storedMail==null)) { Message sendMsg = new MimeMessage(session); // 送信元(From)の設定 sendMsg.setFrom(new InternetAddress(ADMIN_MAIL_ADDRESS)); // 送信先(To)の設定 sendMsg.addRecipients(Message.RecipientType.TO, InternetAddress.parse(storedMail.getFrom())); // 件名(Subject)の設定 ((MimeMessage)sendMsg).setSubject(storedMail.getSubject(), "UTF-8"); // 本文(text)の設定 StringBuffer sb = new StringBuffer(); sb.append("From:" + storedMail.getFrom() + "\n"); sb.append("To:" + storedMail.getTo() + "\n"); sb.append("Sbuject:" + storedMail.getSubject() + "\n"); sb.append("Body:\n" + storedMail.getText()); sendMsg.setText(sb.toString()); // メールの送信 Transport.send(sendMsg); }
一応、メール関連の動作確認サンプルは完成?
メール受信、データストアへ保存、メール送信を一通り実行するサンプルが完成。
ひとまずこれで終了かな。
package jp.kuronicle.kuromail; import java.io.IOException; import java.util.List; import java.util.Properties; import javax.jdo.PersistenceManager; import javax.mail.Address; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import jp.kuronicle.kuromail.datastore.ReceivedMail; public class MailHandlerServlet extends HttpServlet { private static final String ADMIN_MAIL_ADDRESS = "hogehoge@fugafuga.appspotmail.com"; public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { PersistenceManager pm = PMF.get().getPersistenceManager(); Properties prop = new Properties(); Session session = Session.getDefaultInstance(prop, null); try { // 受信メールを取得 MimeMessage recMsg = new MimeMessage(session, req.getInputStream()); // 永続化用JDOに値を入力 ReceivedMail mail = new ReceivedMail(); mail.setSentDate(recMsg.getSentDate()); mail.setFrom(recMsg.getFrom()[0].toString()); mail.setTo(recMsg.getAllRecipients()[0].toString()); mail.setSubject(recMsg.getSubject()); mail.setText(this.getText(recMsg.getContent())); // 永続化 pm.makePersistent(mail); // データストアから最新の1件を取得 String query = "select from " + ReceivedMail.class.getName() + " order by sentDate desc range 0,1"; List<ReceivedMail> mailList = (List<ReceivedMail>) pm.newQuery(query).execute(); ReceivedMail storedMail = mailList.get(0); if(!(storedMail==null)) { Message sendMsg = new MimeMessage(session); // 送信元(From)の設定 sendMsg.setFrom(new InternetAddress(ADMIN_MAIL_ADDRESS)); // 送信先(To)の設定 sendMsg.addRecipients(Message.RecipientType.TO, InternetAddress.parse(storedMail.getFrom())); // 件名(Subject)の設定 ((MimeMessage)sendMsg).setSubject(storedMail.getSubject(), "UTF-8"); // 本文(text)の設定 StringBuffer sb = new StringBuffer(); sb.append("From:" + storedMail.getFrom() + "\n"); sb.append("To:" + storedMail.getTo() + "\n"); sb.append("Sbuject:" + storedMail.getSubject() + "\n"); sb.append("Body:\n" + storedMail.getText()); sendMsg.setText(sb.toString()); // メールの送信 Transport.send(sendMsg); } } catch (MessagingException e) { e.printStackTrace(); } finally { pm.close(); } } private String getText(Object content) throws IOException, MessagingException { String text = null; StringBuffer sb = new StringBuffer(); if (content instanceof String) { sb.append((String) content); } else if (content instanceof Multipart) { Multipart mp = (Multipart) content; for (int i = 0; i < mp.getCount(); i++) { BodyPart bp = mp.getBodyPart(i); sb.append(getText(bp.getContent())); } } text = sb.toString(); return text; } }