Skip to content
This repository has been archived by the owner on Feb 13, 2019. It is now read-only.

Add scripting, using Cub #75

Merged
merged 94 commits into from
Apr 9, 2018
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
b71ca7e
Add Cub scripting prototype
louisdh Feb 6, 2018
3e5c199
Add Swiftlint
louisdh Feb 6, 2018
d9469d8
Merge branch 'master' into cub-scripting
louisdh Feb 6, 2018
3efef61
Fix pods
louisdh Feb 6, 2018
ae0c08a
Merge branch 'master' into cub-scripting
louisdh Feb 8, 2018
52c1bde
Merge branch 'master' into cub-scripting
louisdh Feb 8, 2018
2fffdc4
swiftlint autocorrect --format --use-tabs
louisdh Feb 8, 2018
31af3af
Update project
louisdh Feb 8, 2018
d9018d8
Merge branch 'master' into cub-scripting
louisdh Feb 8, 2018
58251e3
Add cub command
louisdh Feb 8, 2018
0497a67
Scripting rewrite
louisdh Feb 10, 2018
0eeeea1
Merge branch 'master' into cub-scripting
louisdh Feb 10, 2018
4d81534
Remove whitespace
louisdh Feb 10, 2018
350cb3f
Remove commented code
louisdh Feb 10, 2018
a1e9f43
Merge branch 'master' into cub-scripting
louisdh Feb 13, 2018
6113745
Move Cub.swift to Commands folder
louisdh Feb 13, 2018
4ab52c6
Merge branch 'master' into cub-scripting
louisdh Feb 13, 2018
334b81c
Update pods
louisdh Mar 2, 2018
6de7154
Fix error
louisdh Mar 2, 2018
e213773
Merge branch 'master' into cub-scripting
louisdh Mar 2, 2018
9c431ee
Add gitmodules
louisdh Mar 2, 2018
2657938
Fix submodule
louisdh Mar 2, 2018
00cabba
Fix text output styles from Cub
louisdh Mar 3, 2018
843ecc0
Fix output from Cub command
louisdh Mar 3, 2018
74f409d
TerminalView: Don't append text if empty string.
louisdh Mar 3, 2018
23b4c0d
Fix document type, NSUbiquitousContainerSupportedFolderLevels
louisdh Mar 3, 2018
be6138c
Add Cub input functions
louisdh Mar 3, 2018
25baa7d
Improve Cub error handling.
louisdh Mar 3, 2018
7397a45
Update Cub to v0.7.1
louisdh Mar 3, 2018
a30cfac
Fix print function.
louisdh Mar 3, 2018
e8595a3
Pod update
louisdh Mar 3, 2018
8f43801
Use SavannaKit master
louisdh Mar 3, 2018
de10325
Script edit view controller WIP
louisdh Mar 3, 2018
f472b27
Update SavannaKit
louisdh Mar 4, 2018
fbdd9e5
Cleanup
louisdh Mar 4, 2018
bf37aef
Add auto completer to script editor
louisdh Mar 4, 2018
fa639a2
Global scripts WIP
louisdh Mar 4, 2018
1bc31b8
Auto complete: don't skip hidden directories
louisdh Mar 4, 2018
f0d8d88
Fix panel background colors
louisdh Mar 4, 2018
1ed6881
Script editor: fix inputAssistantView style
louisdh Mar 5, 2018
47dc405
Script editor: auto completion cleanup
louisdh Mar 5, 2018
af286a4
Update SavannaKit
louisdh Mar 5, 2018
ffd43f9
Add "url" to Script class
louisdh Mar 6, 2018
07c6f58
Implement PanelContentDelegate on ScriptEditViewController
louisdh Mar 6, 2018
826de69
Fix Cub scripts calling Cub scripts
louisdh Mar 7, 2018
714f6dc
PanelKit fixes
louisdh Mar 7, 2018
3803d0f
Update SavannaKit
louisdh Mar 7, 2018
a1afac1
Set contentWrapperView's background color
louisdh Mar 7, 2018
8221a86
Merge branch 'master' into cub-scripting
louisdh Mar 7, 2018
4eed964
Add Savanna command
louisdh Mar 7, 2018
4c46f61
Only adjust script panel for keyboard if text view is first responder.
louisdh Mar 7, 2018
4d84b8a
Merge branch 'master' into cub-scripting
louisdh Mar 20, 2018
6380233
Fix typos
louisdh Mar 20, 2018
d3ce647
Merge branch 'master' into cub-scripting
louisdh Mar 22, 2018
046a8a0
Update dependencies
louisdh Mar 22, 2018
adee51d
Update test for Cub and Savanna commands.
louisdh Mar 22, 2018
dcfbe1d
Disable Main Thread Checker for tests.
louisdh Mar 22, 2018
38e956c
Merge branch 'master' into cub-scripting
louisdh Mar 31, 2018
84bba0c
Pridelands WIP
louisdh Apr 1, 2018
dfbd0b1
Merge branch 'master' into cub-scripting
louisdh Apr 1, 2018
69c233b
Script UI WIP
louisdh Apr 3, 2018
44e6d8a
Add HueKit
louisdh Apr 3, 2018
73cf0b0
Script UI WIP
louisdh Apr 4, 2018
7bd0313
Edit script metadata WIP
louisdh Apr 4, 2018
8c51310
Update pods
louisdh Apr 6, 2018
fde9985
Add PridelandDocument
louisdh Apr 6, 2018
d10471b
Remove local podspec
louisdh Apr 6, 2018
920a3e8
Prideland overview WIP
louisdh Apr 6, 2018
d001003
Prideland overviews reloading
louisdh Apr 6, 2018
681b33b
Cleanup
louisdh Apr 6, 2018
2d9db7e
Update colors
louisdh Apr 6, 2018
7e8c10c
Update ScriptEditViewController for prideland
louisdh Apr 6, 2018
bb2d54c
Fix auto complete crash
louisdh Apr 6, 2018
333086c
Script view controller: adjust for keyboard
louisdh Apr 6, 2018
09e7d55
Script auto complete: show correct titles.
louisdh Apr 6, 2018
7e8139d
Scripts: Update gradients.
louisdh Apr 7, 2018
8865972
Script metadata WIP
louisdh Apr 7, 2018
329d780
Restructure
louisdh Apr 8, 2018
38ae772
Move String utils to separate file
louisdh Apr 8, 2018
f3623ee
Restructure
louisdh Apr 8, 2018
6be15fa
Fix linting warning
louisdh Apr 8, 2018
4bbc75c
Remove unnecessary UIKit import
louisdh Apr 8, 2018
a42f4db
Cleanup
louisdh Apr 8, 2018
a8f514c
Refactor Cub script error handling
louisdh Apr 8, 2018
a37c6a7
Don't use TerminalView for script error output, use executor.delegate
louisdh Apr 8, 2018
fcdf334
No longer rely on TerminalView for script execution.
louisdh Apr 8, 2018
546d9d1
Fix share command
louisdh Apr 8, 2018
c1da715
Script create/update
louisdh Apr 8, 2018
49dcd77
Script saving
louisdh Apr 9, 2018
e8bbd39
Close script documents
louisdh Apr 9, 2018
c54edd6
Fix script executing, cleanup old scripting code.
louisdh Apr 9, 2018
7677a52
Remove Savanna command
louisdh Apr 9, 2018
30cf8bb
Fix test
louisdh Apr 9, 2018
4c535cf
Remove "Library" from scripts screen.
louisdh Apr 9, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions OpenTerm.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@
BE3808601FD9BFB600393EB8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE38085E1FD9BFB600393EB8 /* LaunchScreen.storyboard */; };
BE505066201E5ED900CDFC60 /* Share.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE505065201E5ED900CDFC60 /* Share.swift */; };
BE9275062013961D00BD2761 /* UserDefaultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9275052013961D00BD2761 /* UserDefaultsController.swift */; };
BEA14A69202CEE5800AB7351 /* Cub+SavannaKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA14A68202CEE5800AB7351 /* Cub+SavannaKit.swift */; };
BEA14A65202CE5B700AB7351 /* Cub+SavannaKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA14A64202CE5B600AB7351 /* Cub+SavannaKit.swift */; };
BEA14A67202CE5D300AB7351 /* Cub.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA14A66202CE5D300AB7351 /* Cub.swift */; };
BEA499261FD9C4D7001B9B9D /* DocumentManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA499251FD9C4D7001B9B9D /* DocumentManager.swift */; };
BEA4992C1FDC0918001B9B9D /* icon-320.png in Resources */ = {isa = PBXBuildFile; fileRef = BEA4992B1FDC0918001B9B9D /* icon-320.png */; };
BEA4992E1FDC305B001B9B9D /* KeyboardObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA4992D1FDC305B001B9B9D /* KeyboardObserver.swift */; };
BEA499301FDC3B93001B9B9D /* TerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA4992F1FDC3B93001B9B9D /* TerminalView.swift */; };
BEA8E2912001348C00002475 /* UIColor+AssetCatalog.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEA8E2902001348C00002475 /* UIColor+AssetCatalog.swift */; };
BEC75BFD202B716600216462 /* OpenTermTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEC75BFC202B716600216462 /* OpenTermTests.swift */; };
BEE5D940202658F80040C72A /* (null) in Sources */ = {isa = PBXBuildFile; };
BEECFF0A1FFC1DC0009608B3 /* HistoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEECFF091FFC1DC0009608B3 /* HistoryViewController.swift */; };
BEECFF391FFEC187009608B3 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEECFF381FFEC187009608B3 /* SettingsViewController.swift */; };
F456629E200B9BC500C574AA /* ColorDisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F456629D200B9BC500C574AA /* ColorDisplayView.swift */; };
Expand Down Expand Up @@ -142,7 +144,8 @@
BE3808611FD9BFB600393EB8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
BE505065201E5ED900CDFC60 /* Share.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Share.swift; sourceTree = "<group>"; };
BE9275052013961D00BD2761 /* UserDefaultsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsController.swift; sourceTree = "<group>"; };
BEA14A68202CEE5800AB7351 /* Cub+SavannaKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Cub+SavannaKit.swift"; sourceTree = "<group>"; };
BEA14A64202CE5B600AB7351 /* Cub+SavannaKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Cub+SavannaKit.swift"; sourceTree = "<group>"; };
BEA14A66202CE5D300AB7351 /* Cub.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cub.swift; sourceTree = "<group>"; };
BEA499241FD9C46C001B9B9D /* OpenTerm.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OpenTerm.entitlements; sourceTree = "<group>"; };
BEA499251FD9C4D7001B9B9D /* DocumentManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentManager.swift; sourceTree = "<group>"; };
BEA4992B1FDC0918001B9B9D /* icon-320.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-320.png"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -243,7 +246,7 @@
children = (
3CA32101201FF6B100974B5F /* Script.swift */,
3CA3210820211D5600974B5F /* ScriptExecutorCommand.swift */,
BEA14A68202CEE5800AB7351 /* Cub+SavannaKit.swift */,
BEA14A64202CE5B600AB7351 /* Cub+SavannaKit.swift */,
);
path = Scripting;
sourceTree = "<group>";
Expand Down Expand Up @@ -380,6 +383,7 @@
BEA8E28F2001346D00002475 /* Util */ = {
isa = PBXGroup;
children = (
BEA14A66202CE5D300AB7351 /* Cub.swift */,
3CE576442022607000760E43 /* Parsing & Formatting */,
3C406E1B2020987B005F97C4 /* AutoComplete */,
3C406E1820207CDA005F97C4 /* Execution */,
Expand Down Expand Up @@ -617,7 +621,6 @@
3CA32102201FF6B100974B5F /* Script.swift in Sources */,
BEA499301FDC3B93001B9B9D /* TerminalView.swift in Sources */,
3CE57680202A529200760E43 /* TerminalTabViewController.swift in Sources */,
BEA14A69202CEE5800AB7351 /* Cub+SavannaKit.swift in Sources */,
F4602B49200A63FC009D0547 /* UserDefaults+UIColor.swift in Sources */,
28CDA426202444CC0055206D /* BookmarkViewController.swift in Sources */,
3CA32105201FFC1300974B5F /* ScriptEditViewController.swift in Sources */,
Expand All @@ -626,6 +629,8 @@
F456629E200B9BC500C574AA /* ColorDisplayView.swift in Sources */,
BE165408201909040067EC92 /* xCallBackUrl.swift in Sources */,
BEA499261FD9C4D7001B9B9D /* DocumentManager.swift in Sources */,
BEE5D940202658F80040C72A /* (null) in Sources */,
BEA14A65202CE5B700AB7351 /* Cub+SavannaKit.swift in Sources */,
BE505066201E5ED900CDFC60 /* Share.swift in Sources */,
3CE5764820226A1500760E43 /* ANSITextState.swift in Sources */,
3CE576A0202A874C00760E43 /* OutputSanitizer.swift in Sources */,
Expand All @@ -642,6 +647,7 @@
BE3808561FD9BFB600393EB8 /* AppDelegate.swift in Sources */,
3C406E1A20207CE7005F97C4 /* CommandExecutor.swift in Sources */,
3C905FCA20265BC60084BA63 /* StoreReviewPrompter.swift in Sources */,
BEA14A67202CE5D300AB7351 /* Cub.swift in Sources */,
3CE5764320225E1B00760E43 /* HistoryManager.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
33 changes: 24 additions & 9 deletions OpenTerm/Controller/Scripting/ScriptEditViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@

import UIKit
import InputAssistant
import Cub
import SavannaKit

class ScriptEditViewController: UIViewController {

var script: Script
let textView: TerminalTextView
let textView: SyntaxTextView
let autoCompleteManager: AutoCompleteManager
let inputAssistantView: InputAssistantView

init(script: Script) {
self.script = script
self.textView = TerminalTextView()
self.textView = SyntaxTextView()
self.autoCompleteManager = AutoCompleteManager()
self.inputAssistantView = InputAssistantView()
super.init(nibName: nil, bundle: nil)
Expand All @@ -43,15 +45,15 @@ class ScriptEditViewController: UIViewController {
// Set up input assistant and text view for auto completion
self.inputAssistantView.delegate = self
self.inputAssistantView.dataSource = self.autoCompleteManager
self.textView.inputAccessoryView = self.inputAssistantView
// self.textView.inputAccessoryView = self.inputAssistantView
self.inputAssistantView.tintColor = .lightGray

// Hide default undo/redo/etc buttons
textView.inputAssistantItem.leadingBarButtonGroups = []
textView.inputAssistantItem.trailingBarButtonGroups = []

// Disable built-in autocomplete
textView.autocorrectionType = .no
// textView.autocorrectionType = .no
}

override func viewDidAppear(_ animated: Bool) {
Expand All @@ -68,6 +70,19 @@ class ScriptEditViewController: UIViewController {

}

extension ScriptEditViewController: SyntaxTextViewDelegate {

func didChangeText(_ syntaxTextView: SyntaxTextView) {
save()
// autoCompleteManager.reloadData()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't check in the commented out lines in this file, but it's up to you.

}

func lexerForSource(_ source: String) -> SavannaKit.Lexer {
return Cub.Lexer(input: source)
}

}

extension ScriptEditViewController: UITextViewDelegate {

func textViewDidChange(_ textView: UITextView) {
Expand Down Expand Up @@ -95,10 +110,10 @@ extension ScriptEditViewController: InputAssistantViewDelegate {
func inputAssistantView(_ inputAssistantView: InputAssistantView, didSelectSuggestionAtIndex index: Int) {
let suggestion = autoCompleteManager.completions[index]

if suggestion.name == "+ new argument" {
textView.insertText("$<<argument>>")
} else {
textView.insertText("$<<\(suggestion.name)>>")
}
// if suggestion.name == "+ new argument" {
// textView.insertText("$<<argument>>")
// } else {
// textView.insertText("$<<\(suggestion.name)>>")
// }
}
}
1 change: 1 addition & 0 deletions OpenTerm/Controller/TerminalViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class TerminalViewController: UIViewController {
replaceCommand("share", mangleFunctionName("shareFile"), true)
replaceCommand("pbcopy", mangleFunctionName("pbcopy"), true)
replaceCommand("pbpaste", mangleFunctionName("pbpaste"), true)
replaceCommand("cub", mangleFunctionName("cub"), true)

// Call reloadData for the added commands.
terminalView.autoCompleteManager.reloadData()
Expand Down
160 changes: 160 additions & 0 deletions OpenTerm/Util/Cub.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
//
// Cub.swift
// OpenTerm
//
// Created by Louis D'hauwe on 03/02/2018.
// Copyright © 2018 Silver Fox. All rights reserved.
//

import Foundation
import Cub
import ios_system
import TabView

public func cub(argc: Int32, argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?) -> Int32 {

let tabViewContainer = UIApplication.shared.keyWindow?.rootViewController as! TabViewContainerViewController<TerminalTabViewController>

guard let activeVC = tabViewContainer.primaryTabViewController.visibleViewController as? TerminalViewController else {
return 0
}

activeVC.terminalView.isExecutingScript = true
let executor = activeVC.terminalView.executor

guard argc == 2 else {
fputs("Usage: cub script.cub\n", thread_stderr)
return 1
}

guard let fileName = argv?[1] else {
fputs("Usage: cub script.cub\n", thread_stderr)
return 1
}

let path = String(cString: fileName)

guard FileManager.default.fileExists(atPath: path) else {
fputs("Missing file \(path)\n", thread_stderr)
return 1
}

let url = URL(fileURLWithPath: path)

guard let data = FileManager.default.contents(atPath: url.path) else {
fputs("Missing file \(path)\n", thread_stderr)
return 1
}

guard let source = String.init(data: data, encoding: .utf8) else {
fputs("Missing file \(path)\n", thread_stderr)
return 1
}

let runner = Runner(logDebug: true, logTime: false)

runner.registerExternalFunction(name: "print", argumentNames: ["input"], returns: false) { (arguments, callback) in

for (name, arg) in arguments {
fputs("\(arg)\n", thread_stdout)
}

callback(nil)
return
}

runner.registerExternalFunction(name: "exec", argumentNames: ["command"], returns: true) { (arguments, callback) in

var arguments = arguments

guard let command = arguments.removeValue(forKey: "command") else {
callback(.number(1))
return
}

guard case let .string(commandStr) = command else {
callback(.number(1))
return
}

print("run command: \(commandStr)")

// executor.dispatch(commandStr, callback: { (code) in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will you end up doing here for execution? Will you need to add a callback?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added CubCommandExecutor, which conforms to CommandExecutorDelegate and ParserDelegate. It takes a TerminalView and temporarily sets itself as the delegates.

//
// print("did run command: \(commandStr) -> \(code)")
//
// DispatchQueue.main.async {
//
// callback(.number(Double(code)))
// }
//
// })

}

runner.registerExternalFunction(name: "format", argumentNames: ["input", "arg"], returns: true) { (arguments, callback) in

var arguments = arguments

guard let input = arguments.removeValue(forKey: "input") else {
callback(.string(""))
return
}

guard case let .string(inputStr) = input else {
callback(.string(""))
return
}

var otherValues = arguments.values

var varArgs = [CVarArg]()

for value in otherValues {

switch value {
case .bool(let b):
break
case .number(let n):
varArgs.append(n)
case .string(let str):
varArgs.append(str)
case .struct:
break
}

}

let output = String(format: inputStr, arguments: varArgs)

callback(.string(output))
return
}

print("run")

do {

runner.executionFinishedCallback = {

print("executionFinishedCallback")

DispatchQueue.main.async {

activeVC.terminalView.isExecutingScript = false
// activeVC.terminalView.isWaitingForCommand = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #82 adds an enum state to the terminal, currently running or idle. Use that instead of adding this boolean.


// activeVC.terminalView.commandExecutor(executor, didFinishDispatchWithExitCode: 0)
// activeVC.terminalView.commandE
}

}

try runner.run(source)

} catch {
return 1
}

return 0
}
5 changes: 4 additions & 1 deletion OpenTerm/View/TerminalView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class TerminalView: UIView {

weak var delegate: TerminalViewDelegate?

private var isWaitingForCommand = false
var isWaitingForCommand = false

var isExecutingScript = false

init() {
super.init(frame: .zero)
Expand Down Expand Up @@ -271,6 +273,7 @@ extension TerminalView: UITextViewDelegate {
if input.isEmpty {
writePrompt()
} else {
isWaitingForCommand = true
newLine()
delegate?.didEnterCommand(String(input))
}
Expand Down