LoginSignup
5
5

More than 5 years have passed since last update.

NSTask経由でscalaスクリプトを実行する (プログラミング学習用アプリを作る)

Last updated at Posted at 2015-02-08

 新しめのプログラミング言語にはREPLがあったり、スクリプトファイルから実行できたりします。書きながら勉強できますから、重宝しますよね。

 が、しかし… エディターとターミナルを行ったり来たりするのはちょっと面倒です。

CotEditorは素晴らしいエディターです

 ウィンドウが2つあると、色々な操作が増えます。艦これのために動かしてスペースを開けるだけで数秒余計にかかります。
 IDEを使えばいいんですが、こちらは基本的にサイズが大きいので「macbookでちょっと勉強」という用途には大げさだったりします。もっと単純に「右側に出力があって、左側に書いてキーボードショートカットで実行できる」というだけで充分なこともあります。

 それくらいならNSTaskで簡単に作れそうです。
 ということで実際に作りました。

スクリーンショット 2015-02-08 17.27.59.png

 セキュリティとかエラーとか考えなければ、左側に書いてcommand+Rで実行できるモノを40行で作ることができます。

作り方

 基本的には、NSTaskを動かして出力をそのまんま書き込みます。
 ViewControllerにrun()を書いて、メニュー経由でこれを呼びましょう。

 run()は単純なメソッドで、(1)テキストを保存し、(2)保存したファイルをscalaに渡し、(3)タスクが終わるまで待ってから結果を読み取り、(4)データを変換して表示します。

import Cocoa

class ViewController: NSViewController {

    @IBOutlet var editor: NSTextView! {
        didSet {
            editor.automaticTextReplacementEnabled = false
        }
    }
    @IBOutlet var output: NSTextView!

    @IBAction func run(sender: NSMenuItem) {
        let task = NSTask()
        let output = NSPipe()
        let error = NSPipe()
        let name = "scEditor" + NSDate().timeIntervalSince1970.description

        if let path = NSTemporaryDirectory().stringByAppendingPathComponent(name).stringByAppendingPathExtension("scala") {
            editor.string?.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: nil)

            task.standardOutput = output
            task.standardError = error
            task.launchPath = "/usr/local/bin/scala"
            task.arguments = [path]
            task.launch()

            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
                task.waitUntilExit()
                let result = output.toString() + error.toString()
                dispatch_async(dispatch_get_main_queue()) {
                    self.output.string = result
                }
            }
        } else {
            println("error")
        }
    }
}

extension NSPipe {
    func toString() -> String {
        let data = self.fileHandleForReading.availableData
        return NSString(data: data, encoding: NSUTF8StringEncoding) ?? ""
    }
}

 キーボードショートカットは、メニューを弄ることで設定できます。
 ファーストレスポンダー宛てにrun()を呼ばせるだけです。

スクリーンショット 2015-02-08 16.44.28.png

 あとは適当にテキストビューを2つ置いて、アウトレットとして接続すれば動きます。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5