Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

 新しめのプログラミング言語には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つ置いて、アウトレットとして接続すれば動きます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした