diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..b33b744
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,77 @@
+### Swift ###
+# Xcode
+#
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
+
+## Build generated
+build/
+DerivedData/
+
+## Various settings
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata/
+
+## Other
+*.moved-aside
+*.xccheckout
+*.xcscmblueprint
+
+## Obj-C/Swift specific
+*.hmap
+*.ipa
+*.dSYM.zip
+*.dSYM
+
+## Playgrounds
+timeline.xctimeline
+playground.xcworkspace
+
+# Swift Package Manager
+#
+# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
+# Packages/
+# Package.pins
+.build/
+
+# CocoaPods - Refactored to standalone file
+
+# Carthage - Refactored to standalone file
+
+# fastlane
+#
+# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
+# screenshots whenever they are needed.
+# For more information about the recommended setup visit:
+# https://docs.fastlane.tools/best-practices/source-control/#source-control
+
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+
+### Xcode ###
+# Xcode
+#
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
+
+## Build generated
+
+## Various settings
+
+## Other
+
+### Xcode Patch ###
+*.xcodeproj/*
+!*.xcodeproj/project.pbxproj
+!*.xcodeproj/xcshareddata/
+!*.xcworkspace/contents.xcworkspacedata
+/*.gcno
+CodeEditor/Assets.xcassets/.DS_Store
+.DS_Store
diff --git a/CodeEditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/CodeEditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 941d038..0000000
--- a/CodeEditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/CodeEditor.xcodeproj/project.xcworkspace/xcuserdata/mini.xcuserdatad/UserInterfaceState.xcuserstate b/CodeEditor.xcodeproj/project.xcworkspace/xcuserdata/mini.xcuserdatad/UserInterfaceState.xcuserstate
deleted file mode 100644
index eb02d0e..0000000
Binary files a/CodeEditor.xcodeproj/project.xcworkspace/xcuserdata/mini.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ
diff --git a/CodeEditor.xcodeproj/xcuserdata/mini.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/CodeEditor.xcodeproj/xcuserdata/mini.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
deleted file mode 100644
index fe2b454..0000000
--- a/CodeEditor.xcodeproj/xcuserdata/mini.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/CodeEditor.xcodeproj/xcuserdata/mini.xcuserdatad/xcschemes/xcschememanagement.plist b/CodeEditor.xcodeproj/xcuserdata/mini.xcuserdatad/xcschemes/xcschememanagement.plist
deleted file mode 100644
index 97ca160..0000000
--- a/CodeEditor.xcodeproj/xcuserdata/mini.xcuserdatad/xcschemes/xcschememanagement.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- SchemeUserState
-
- CodeEditor.xcscheme
-
- orderHint
- 0
-
-
- SuppressBuildableAutocreation
-
- 3D106F311E29BFDE0081E0EC
-
- primary
-
-
-
-
-
diff --git a/CodeEditor/AppDelegate.swift b/CodeEditor/AppDelegate.swift
old mode 100644
new mode 100755
index e8981b6..b54193d
--- a/CodeEditor/AppDelegate.swift
+++ b/CodeEditor/AppDelegate.swift
@@ -7,6 +7,7 @@
//
import Cocoa
+import NotificationCenter
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@@ -14,28 +15,59 @@ class AppDelegate: NSObject, NSApplicationDelegate {
var appFolderName = "MacawEditor"
var appFolderUrl: URL?
var filename: String = ""
- var settings = Settings()
+ var currentBuild = Int(Bundle.main.infoDictionary?["CFBundleVersion"] as! String)!
+ var preferencesController: NSWindowController?
override init(){
super.init()
- print("Hello!")
+
+ DistributedNotificationCenter.default.addObserver(
+ self,
+ selector: #selector(interfaceColorChanged),
+ name: .AppleInterfaceThemeChangedNotification,
+ object: nil
+ )
+
setupAppFolder()
- settings.load()
+ Settings.shared.load()
+ }
+
+ @objc func interfaceColorChanged() {
+ NotificationCenter.default.post(name: .updateTheme, object: nil)
}
func setupAppFolder() {
-
+ var forceInstall = false
+ var installError = false
let filer = FileManager.default
- if let libFolder = filer.urls(for: .applicationSupportDirectory, in: .userDomainMask).first {
+ if let libFolder = filer.urls(
+ for: .applicationSupportDirectory,
+ in: .userDomainMask
+ ).first {
+
+ appFolderUrl = libFolder.appendingPathComponent(
+ appFolderName, isDirectory: true
+ )
- appFolderUrl = libFolder.appendingPathComponent(appFolderName, isDirectory: true)
+ if let lastInstall = UserDefaults.standard.object(forKey: "installed") {
+ if Int(lastInstall as! Int) < currentBuild {
+ forceInstall = true
+ }
+ }
- if !filer.fileExists(atPath: appFolderUrl!.path) {
- print("Setting up app folder")
+ if forceInstall || !filer.fileExists(atPath: appFolderUrl!.path) {
+ print(forceInstall ? "Upgrading app folder to build \(currentBuild)" : "Setting up app folder")
do {
try filer.createDirectory(at: appFolderUrl!, withIntermediateDirectories: true, attributes: nil)
-
+ UserDefaults.standard.set(currentBuild, forKey: "installed")
+ } catch {
+ installError = true
+ print("Error creating app folder and copying syntax files")
+ Alert("Error creating app folder. Syntax files not loaded. Verify you have permissions to write in folder ~/Library/Application Support/").show()
+ }
+
+ if !installError {
// Copy syntax files to appFolder
let files = [
"Settings.yaml",
@@ -45,23 +77,35 @@ class AppDelegate: NSObject, NSApplicationDelegate {
"json.default.yaml",
"swift.default.yaml",
"xml.default.yaml",
+ "php.default.yaml",
"yaml.default.yaml"
]
print("Copying syntax files to app folder")
-
+
for item in files {
+ if filer.fileExists(atPath: (appFolderUrl?.appendingPathComponent(item).path)!) {
+ do {
+ try filer.removeItem(at: (appFolderUrl?.appendingPathComponent(item))!)
+ }
+ catch {
+ print("Failed to upgrade \(item)")
+ Alert("Error accessing app folder. Syntax files not loaded. Verify you have permissions to read from folder ~/Library/Application Support/").show()
+ }
+ }
+
if let source = Bundle.main.url(file: item),
let target = appFolderUrl?.appendingPathComponent(item)
{
- //print("Copying file \(source) to \(target)")
- try filer.copyItem(at: source, to: target)
+ do {
+ try filer.copyItem(at: source, to: target)
+ }
+ catch {
+ print("Failed to upgrade \(item)")
+ Alert("Error accessing app folder. Syntax files not loaded. Verify you have permissions to read from folder ~/Library/Application Support/").show()
+ }
}
}
-
- } catch {
- print("Error creating app folder and copying syntax files")
- Alert("Error creating app folder. Syntax files not loaded. Verify you have permissions to write in folder ~/Library/Application Support/").show()
}
}
} else {
@@ -77,7 +121,18 @@ class AppDelegate: NSObject, NSApplicationDelegate {
main.fileOpenByOS(filename)
return true
}
-
+
+ @IBAction func showPreferences(_ sender: Any) {
+ if (preferencesController == nil) {
+ let storyboard = NSStoryboard(name: NSStoryboard.Name("Preferences"), bundle: nil)
+ preferencesController = storyboard.instantiateInitialController() as? NSWindowController
+ }
+
+ if (preferencesController != nil) {
+ preferencesController!.showWindow(sender)
+ }
+ }
+
func applicationDidFinishLaunching(_ notification: Notification) {
//
}
@@ -87,7 +142,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
- print("Goodbye!")
return true
}
diff --git a/CodeEditor/Assets.xcassets/AppIcon.appiconset/Contents.json b/CodeEditor/Assets.xcassets/AppIcon.appiconset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor016.png b/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor016.png
old mode 100644
new mode 100755
index 67cfebd..5d97e8a
Binary files a/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor016.png and b/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor016.png differ
diff --git a/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor032.png b/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor032.png
old mode 100644
new mode 100755
index 5bb59fe..32b9d9b
Binary files a/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor032.png and b/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor032.png differ
diff --git a/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor128.png b/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor128.png
old mode 100644
new mode 100755
index abc3b7f..e69da06
Binary files a/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor128.png and b/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor128.png differ
diff --git a/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor256.png b/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor256.png
old mode 100644
new mode 100755
index 149bfa2..2995987
Binary files a/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor256.png and b/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor256.png differ
diff --git a/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor512.png b/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor512.png
old mode 100644
new mode 100755
index 612b803..217b291
Binary files a/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor512.png and b/CodeEditor/Assets.xcassets/AppIcon.appiconset/macaweditor512.png differ
diff --git a/CodeEditor/Assets.xcassets/Contents.json b/CodeEditor/Assets.xcassets/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/appicon.imageset/Contents.json b/CodeEditor/Assets.xcassets/appicon.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/appicon.imageset/appicon.png b/CodeEditor/Assets.xcassets/appicon.imageset/appicon.png
old mode 100644
new mode 100755
index 1c26a35..249d655
Binary files a/CodeEditor/Assets.xcassets/appicon.imageset/appicon.png and b/CodeEditor/Assets.xcassets/appicon.imageset/appicon.png differ
diff --git a/CodeEditor/Assets.xcassets/icon_dark.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_dark.imageset/Contents.json
deleted file mode 100644
index 53b28ba..0000000
--- a/CodeEditor/Assets.xcassets/icon_dark.imageset/Contents.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "icon_dark.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/CodeEditor/Assets.xcassets/icon_dark.imageset/icon_dark.png b/CodeEditor/Assets.xcassets/icon_dark.imageset/icon_dark.png
deleted file mode 100644
index 90dc57a..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_dark.imageset/icon_dark.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_dark.png b/CodeEditor/Assets.xcassets/icon_dark.png
deleted file mode 100644
index 90dc57a..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_dark.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_dark2.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_dark2.imageset/Contents.json
deleted file mode 100644
index 294f3ea..0000000
--- a/CodeEditor/Assets.xcassets/icon_dark2.imageset/Contents.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "icon_dark2.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/CodeEditor/Assets.xcassets/icon_dark2.imageset/icon_dark2.png b/CodeEditor/Assets.xcassets/icon_dark2.imageset/icon_dark2.png
deleted file mode 100644
index 2c0584c..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_dark2.imageset/icon_dark2.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_dark2.png b/CodeEditor/Assets.xcassets/icon_dark2.png
deleted file mode 100644
index 2c0584c..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_dark2.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_menu.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_menu.imageset/Contents.json
deleted file mode 100644
index 5541c90..0000000
--- a/CodeEditor/Assets.xcassets/icon_menu.imageset/Contents.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "icon_menu.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/CodeEditor/Assets.xcassets/icon_menu.imageset/icon_menu.png b/CodeEditor/Assets.xcassets/icon_menu.imageset/icon_menu.png
deleted file mode 100644
index ea81e85..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_menu.imageset/icon_menu.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_menu.png b/CodeEditor/Assets.xcassets/icon_menu.png
deleted file mode 100644
index ea81e85..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_menu.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_menu2.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_menu2.imageset/Contents.json
deleted file mode 100644
index 427592a..0000000
--- a/CodeEditor/Assets.xcassets/icon_menu2.imageset/Contents.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "icon_menu2.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/CodeEditor/Assets.xcassets/icon_menu2.imageset/icon_menu2.png b/CodeEditor/Assets.xcassets/icon_menu2.imageset/icon_menu2.png
deleted file mode 100644
index 8338b74..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_menu2.imageset/icon_menu2.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_menu2.png b/CodeEditor/Assets.xcassets/icon_menu2.png
deleted file mode 100644
index 8338b74..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_menu2.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_new.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_new.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_new.imageset/icon_new.png b/CodeEditor/Assets.xcassets/icon_new.imageset/icon_new.png
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_new.png b/CodeEditor/Assets.xcassets/icon_new.png
old mode 100644
new mode 100755
index 754ac84..5350446
Binary files a/CodeEditor/Assets.xcassets/icon_new.png and b/CodeEditor/Assets.xcassets/icon_new.png differ
diff --git a/CodeEditor/Assets.xcassets/icon_new2.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_new2.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_new2.imageset/icon_new2.png b/CodeEditor/Assets.xcassets/icon_new2.imageset/icon_new2.png
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_new2.png b/CodeEditor/Assets.xcassets/icon_new2.png
old mode 100644
new mode 100755
index f998b4e..a47a6df
Binary files a/CodeEditor/Assets.xcassets/icon_new2.png and b/CodeEditor/Assets.xcassets/icon_new2.png differ
diff --git a/CodeEditor/Assets.xcassets/icon_open.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_open.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_open.imageset/icon_open.png b/CodeEditor/Assets.xcassets/icon_open.imageset/icon_open.png
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_open.png b/CodeEditor/Assets.xcassets/icon_open.png
old mode 100644
new mode 100755
index f0988d3..7aad7e3
Binary files a/CodeEditor/Assets.xcassets/icon_open.png and b/CodeEditor/Assets.xcassets/icon_open.png differ
diff --git a/CodeEditor/Assets.xcassets/icon_open2.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_open2.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_open2.imageset/icon_open2.png b/CodeEditor/Assets.xcassets/icon_open2.imageset/icon_open2.png
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_open2.png b/CodeEditor/Assets.xcassets/icon_open2.png
old mode 100644
new mode 100755
index 7bf5be5..39d4bc5
Binary files a/CodeEditor/Assets.xcassets/icon_open2.png and b/CodeEditor/Assets.xcassets/icon_open2.png differ
diff --git a/CodeEditor/Assets.xcassets/icon_options.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_options.imageset/Contents.json
deleted file mode 100644
index 044bb32..0000000
--- a/CodeEditor/Assets.xcassets/icon_options.imageset/Contents.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "icon_options.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/CodeEditor/Assets.xcassets/icon_options.imageset/icon_options.png b/CodeEditor/Assets.xcassets/icon_options.imageset/icon_options.png
deleted file mode 100644
index 1a311b5..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_options.imageset/icon_options.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_options.png b/CodeEditor/Assets.xcassets/icon_options.png
deleted file mode 100644
index 1a311b5..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_options.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_options2.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_options2.imageset/Contents.json
deleted file mode 100644
index cc129c2..0000000
--- a/CodeEditor/Assets.xcassets/icon_options2.imageset/Contents.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "icon_options2.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/CodeEditor/Assets.xcassets/icon_options2.imageset/icon_options2.png b/CodeEditor/Assets.xcassets/icon_options2.imageset/icon_options2.png
deleted file mode 100644
index c6900c0..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_options2.imageset/icon_options2.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_options2.png b/CodeEditor/Assets.xcassets/icon_options2.png
deleted file mode 100644
index c6900c0..0000000
Binary files a/CodeEditor/Assets.xcassets/icon_options2.png and /dev/null differ
diff --git a/CodeEditor/Assets.xcassets/icon_save.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_save.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_save.imageset/icon_save.png b/CodeEditor/Assets.xcassets/icon_save.imageset/icon_save.png
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_save.png b/CodeEditor/Assets.xcassets/icon_save.png
old mode 100644
new mode 100755
index a828805..16ea5ab
Binary files a/CodeEditor/Assets.xcassets/icon_save.png and b/CodeEditor/Assets.xcassets/icon_save.png differ
diff --git a/CodeEditor/Assets.xcassets/icon_save2.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_save2.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_save2.imageset/icon_save2.png b/CodeEditor/Assets.xcassets/icon_save2.imageset/icon_save2.png
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_save2.png b/CodeEditor/Assets.xcassets/icon_save2.png
old mode 100644
new mode 100755
index dd0f144..d610c8d
Binary files a/CodeEditor/Assets.xcassets/icon_save2.png and b/CodeEditor/Assets.xcassets/icon_save2.png differ
diff --git a/CodeEditor/Assets.xcassets/icon_saved.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_saved.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_saved.imageset/icon_saved.png b/CodeEditor/Assets.xcassets/icon_saved.imageset/icon_saved.png
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_saved.png b/CodeEditor/Assets.xcassets/icon_saved.png
old mode 100644
new mode 100755
index 6e537dd..b7686d1
Binary files a/CodeEditor/Assets.xcassets/icon_saved.png and b/CodeEditor/Assets.xcassets/icon_saved.png differ
diff --git a/CodeEditor/Assets.xcassets/icon_saved2.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_saved2.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_saved2.imageset/icon_saved2.png b/CodeEditor/Assets.xcassets/icon_saved2.imageset/icon_saved2.png
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_saved2.png b/CodeEditor/Assets.xcassets/icon_saved2.png
old mode 100644
new mode 100755
index 60b9b9d..b40dd60
Binary files a/CodeEditor/Assets.xcassets/icon_saved2.png and b/CodeEditor/Assets.xcassets/icon_saved2.png differ
diff --git a/CodeEditor/Assets.xcassets/icon_trash.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_trash.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_trash.imageset/icon_trash.png b/CodeEditor/Assets.xcassets/icon_trash.imageset/icon_trash.png
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_trash.png b/CodeEditor/Assets.xcassets/icon_trash.png
old mode 100644
new mode 100755
index a42e104..7a2dc00
Binary files a/CodeEditor/Assets.xcassets/icon_trash.png and b/CodeEditor/Assets.xcassets/icon_trash.png differ
diff --git a/CodeEditor/Assets.xcassets/icon_trash2.imageset/Contents.json b/CodeEditor/Assets.xcassets/icon_trash2.imageset/Contents.json
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_trash2.imageset/icon_trash2.png b/CodeEditor/Assets.xcassets/icon_trash2.imageset/icon_trash2.png
old mode 100644
new mode 100755
diff --git a/CodeEditor/Assets.xcassets/icon_trash2.png b/CodeEditor/Assets.xcassets/icon_trash2.png
old mode 100644
new mode 100755
index 714ce40..ab82f01
Binary files a/CodeEditor/Assets.xcassets/icon_trash2.png and b/CodeEditor/Assets.xcassets/icon_trash2.png differ
diff --git a/CodeEditor/Base.lproj/Main.storyboard b/CodeEditor/Base.lproj/Main.storyboard
old mode 100644
new mode 100755
index d2da531..868bc33
--- a/CodeEditor/Base.lproj/Main.storyboard
+++ b/CodeEditor/Base.lproj/Main.storyboard
@@ -1,8 +1,9 @@
-
+
-
+
+
@@ -11,25 +12,29 @@
-
+
@@ -712,13 +712,44 @@ GQ
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -729,7 +760,7 @@ GQ
-
+
@@ -749,16 +780,16 @@ GQ
-
+
-
+
-
+
@@ -818,28 +849,17 @@ GQ
-
+
-
+
-
-
@@ -894,26 +901,26 @@ GQ
-
+
-
+
-
+
+
-
-
+
-
+
@@ -960,26 +967,26 @@ GQ
-
+
-
+
-
+
+
-
-
+
-
+
@@ -1003,13 +1010,12 @@ GQ
-
-
+
@@ -1027,8 +1033,6 @@ GQ
-
-
diff --git a/CodeEditor/EditorController.swift b/CodeEditor/EditorController.swift
old mode 100644
new mode 100755
index 40a6365..999d83c
--- a/CodeEditor/EditorController.swift
+++ b/CodeEditor/EditorController.swift
@@ -1,5 +1,5 @@
//
-// EditorController..swift
+// EditorController.swift
// CodeEditor
//
// Created by Mac Mini on 1/21/17.
@@ -11,28 +11,22 @@ import Foundation
class EditorController: NSTextView, NSTextViewDelegate {
-
let spacer = 4 // TODO: get from defaults
-
-/*
- TODO:
-
- - if } alone in line, unindent before inserting new line
-
- */
-
+ /*
+ TODO:
+ - if } alone in line, unindent before inserting new line
+ */
+
typealias IndentInfo = (count: Int, stop: Bool, last: Character)
func process(_ range: NSRange) {
- guard self.string != nil else { return }
-
- let content = (self.string! as NSString)
- let cursor = range.location
- let index = NSRange(location: cursor, length: 0)
+ let content = (self.string as NSString)
+ let cursor = range.location
+ let index = NSRange(location: cursor, length: 0)
let lineRange = content.lineRange(for: index)
- let lineText = content.substring(with: lineRange)
+ let lineText = content.substring(with: lineRange)
//debugPrint("Line: \(lineText)")
@@ -40,7 +34,7 @@ class EditorController: NSTextView, NSTextViewDelegate {
if lineText.trimmingCharacters(in: .whitespacesAndNewlines) == "}" {
//alignBracket(lineRange)
}
-
+
}
// Stolen from SwiftEditor @ SourceKittenDaemon
@@ -50,45 +44,52 @@ class EditorController: NSTextView, NSTextViewDelegate {
let range = self.selectedRange()
let cursor = range.location
guard cursor != NSNotFound else { return }
-
- guard self.string != nil else { return }
- let content = self.string! as NSString
+
+ let content = self.string as NSString
guard let indent = getPrevLineIndent(range) else { return }
- let currentLineRange = content.lineRange(for: NSRange(location: cursor, length: 0))
+ let currentLineRange = content.lineRange(for:
+ NSRange(location: cursor, length: 0)
+ )
/*
- let previousLineRange = content.lineRange(for: NSRange.init(location: currentLineRange.location - 1, length: 0))
- let previousLine = content.substring(with: previousLineRange)
-
- // get the current indent
- let indentInfo = (count: 0, stop: false, last: Character(" "))
- var indent = previousLine.characters.reduce(indentInfo) { (info: IndentInfo, char) -> IndentInfo in
- guard info.stop == false
- else {
- // remember the last non-whitespace char
- if char == " " || char == "\t" || char == "\n" {
- return info
- } else {
- return (count: info.count, stop: info.stop, last: char)
- }
- }
- switch char {
- case " " : return (stop: false, count: info.count + 1, last: info.last)
- case "\t": return (stop: false, count: info.count + spacer, last: info.last)
- default : return (stop: true , count: info.count, last: info.last)
- }
- }
- */
+ let previousLineRange = content.lineRange(for: NSRange.init(location: currentLineRange.location - 1, length: 0))
+ let previousLine = content.substring(with: previousLineRange)
+
+ // get the current indent
+ let indentInfo = (count: 0, stop: false, last: Character(" "))
+ var indent = previousLine.characters.reduce(indentInfo) { (info: IndentInfo, char) -> IndentInfo in
+ guard info.stop == false
+ else {
+ // remember the last non-whitespace char
+ if char == " " || char == "\t" || char == "\n" {
+ return info
+ } else {
+ return (count: info.count, stop: info.stop, last: char)
+ }
+ }
+ switch char {
+ case " " : return (stop: false, count: info.count + 1, last: info.last)
+ case "\t": return (stop: false, count: info.count + spacer, last: info.last)
+ default : return (stop: true , count: info.count, last: info.last)
+ }
+ }
+ */
// find the last-non-whitespace char
var spaceCount = indent.count
switch indent.last {
- case "{": spaceCount += spacer
- case "}": spaceCount -= spacer; if spaceCount < 0 { spaceCount = 0 }
- default : break
+ case "{":
+ spaceCount += spacer
+ case "}":
+ spaceCount -= spacer
+ if (spaceCount < 0) {
+ spaceCount = 0
+ }
+ default:
+ break
}
//debugPrint("Last char: ", indent.last, indent.count)
@@ -96,10 +97,10 @@ class EditorController: NSTextView, NSTextViewDelegate {
// insert the new indent
let start = NSRange(location: currentLineRange.location, length: 0)
let spaces = String(repeating: " ", count: spaceCount)
-
+
self.insertText(spaces, replacementRange: start)
}
-
+
@IBAction func moveLineUp(_ sender: NSMenuItem) {
self.selectLine(sender)
@@ -131,9 +132,8 @@ class EditorController: NSTextView, NSTextViewDelegate {
@IBAction func duplicateLine(_ sender: NSMenuItem) {
debugPrint("DUPLICATE LINE!")
- guard self.string != nil else { return }
- let content = self.string! as NSString
-
+ let content = self.string as NSString
+
self.selectLine(sender)
let range = self.selectedRange()
let text = content.substring(with: range)
@@ -153,35 +153,34 @@ class EditorController: NSTextView, NSTextViewDelegate {
}
func alignBracket(_ range: NSRange) {
-
debugPrint("Align bracket")
/*
- guard self.string != nil else { return }
- guard let prevIndent = getPrevLineIndent(range) else { return }
- guard let thisIndent = getThisLineIndent(range) else { return }
-
- var idealIndent = prevIndent.count - spacer
- if idealIndent < 0 { idealIndent = 0 }
- debugPrint("Ideal indent: ", idealIndent)
-
- let currentLineRange = (self.string! as NSString).lineRange(for: NSRange(location: range.location, length: 0))
-
- if thisIndent.count > idealIndent {
- debugPrint("Bracket unindented")
- //self.deleteToBeginOfLine()
- let start = NSRange(location: currentLineRange.location, length: thisIndent.count)
- let spaces = String(repeating: " ", count: idealIndent)
- self.replaceCharacters(in: start, with: spaces)
- //self.insertText(spaces, replacementRange: start)
- } else if thisIndent.count < idealIndent {
- debugPrint("Bracket indented")
- let start = NSRange(location: currentLineRange.location, length: 0)
- let spaces = String(repeating: " ", count: (idealIndent - thisIndent.count))
- self.insertText(spaces, replacementRange: start)
- } else {
- debugPrint("Bracket in position")
- }
- */
+ guard self.string != nil else { return }
+ guard let prevIndent = getPrevLineIndent(range) else { return }
+ guard let thisIndent = getThisLineIndent(range) else { return }
+
+ var idealIndent = prevIndent.count - spacer
+ if idealIndent < 0 { idealIndent = 0 }
+ debugPrint("Ideal indent: ", idealIndent)
+
+ let currentLineRange = (self.string! as NSString).lineRange(for: NSRange(location: range.location, length: 0))
+
+ if thisIndent.count > idealIndent {
+ debugPrint("Bracket unindented")
+ //self.deleteToBeginOfLine()
+ let start = NSRange(location: currentLineRange.location, length: thisIndent.count)
+ let spaces = String(repeating: " ", count: idealIndent)
+ self.replaceCharacters(in: start, with: spaces)
+ //self.insertText(spaces, replacementRange: start)
+ } else if thisIndent.count < idealIndent {
+ debugPrint("Bracket indented")
+ let start = NSRange(location: currentLineRange.location, length: 0)
+ let spaces = String(repeating: " ", count: (idealIndent - thisIndent.count))
+ self.insertText(spaces, replacementRange: start)
+ } else {
+ debugPrint("Bracket in position")
+ }
+ */
}
@@ -190,30 +189,58 @@ class EditorController: NSTextView, NSTextViewDelegate {
func getPrevLineIndent(_ range: NSRange) -> IndentInfo? {
let cursor = range.location
guard cursor != NSNotFound else { return nil }
-
- guard self.string != nil else { return nil }
- let content = self.string! as NSString
- let currentLineRange = content.lineRange(for: NSRange(location: cursor, length: 0))
- let previousLineRange = content.lineRange(for: NSRange(location: currentLineRange.location - 1, length: 0))
+ let content = self.string as NSString
+
+ let currentLineRange = content.lineRange(
+ for: NSRange(location: cursor, length: 0)
+ )
+
+ let previousLineRange = content.lineRange(
+ for: NSRange(location: currentLineRange.location - 1, length: 0)
+ )
+
let previousLineText = content.substring(with: previousLineRange)
// get the current indent
let indentInfo = (count: 0, stop: false, last: Character(" "))
- let indent = previousLineText.characters.reduce(indentInfo) { (info: IndentInfo, char) -> IndentInfo in
+ let indent = previousLineText.reduce(indentInfo) {
+ (info: IndentInfo, char) -> IndentInfo in
guard info.stop == false
- else {
- // remember the last non-whitespace char
- if char == " " || char == "\t" || char == "\n" {
- return info
- } else {
- return (count: info.count, stop: info.stop, last: char)
- }
+ else {
+ // remember the last non-whitespace char
+ if char == " " || char == "\t" || char == "\n" {
+ return info
+ } else {
+ return (
+ count: info.count,
+ stop: info.stop,
+ last: char
+ )
+ }
}
+
switch char {
- case " " : return (stop: false, count: info.count + 1, last: info.last)
- case "\t": return (stop: false, count: info.count + spacer, last: info.last)
- default : return (stop: true , count: info.count, last: info.last)
+ case " " :
+ return (
+ stop: false,
+ count: info.count + 1,
+ last: info.last
+ )
+
+ case "\t":
+ return (
+ stop: false,
+ count: info.count + spacer,
+ last: info.last
+ )
+
+ default:
+ return (
+ stop: true,
+ count: info.count,
+ last: info.last
+ )
}
}
@@ -224,28 +251,58 @@ class EditorController: NSTextView, NSTextViewDelegate {
let cursor = range.location
guard cursor != NSNotFound else { return nil }
- guard self.string != nil else { return nil }
- let content = self.string! as NSString
+ let content = self.string as NSString
+
+ let currentLineRange = content.lineRange(
+ for: NSRange(location: cursor, length: 0)
+ )
- let currentLineRange = content.lineRange(for: NSRange(location: cursor, length: 0))
let currentLineText = content.substring(with: currentLineRange)
-
+
// get the current indent
- let indentInfo = (count: 0, stop: false, last: Character(" "))
- let indent = currentLineText.characters.reduce(indentInfo) { (info: IndentInfo, char) -> IndentInfo in
+ let indentInfo = (
+ count: 0,
+ stop: false,
+ last: Character(" ")
+ )
+
+ let indent = currentLineText.reduce(indentInfo) {
+ (info: IndentInfo, char) -> IndentInfo in
guard info.stop == false
else {
// remember the last non-whitespace char
if char == " " || char == "\t" || char == "\n" {
return info
} else {
- return (count: info.count, stop: info.stop, last: char)
+ return (
+ count: info.count,
+ stop: info.stop,
+ last: char
+ )
}
}
+
switch char {
- case " " : return (stop: false, count: info.count + 1, last: info.last)
- case "\t": return (stop: false, count: info.count + spacer, last: info.last)
- default : return (stop: true , count: info.count, last: info.last)
+ case " " :
+ return (
+ stop: false,
+ count: info.count + 1,
+ last: info.last
+ )
+
+ case "\t":
+ return (
+ stop: false,
+ count: info.count + spacer,
+ last: info.last
+ )
+
+ default:
+ return (
+ stop: true,
+ count: info.count,
+ last: info.last
+ )
}
}
diff --git a/CodeEditor/FileController.swift b/CodeEditor/FileController.swift
old mode 100644
new mode 100755
index fb701fd..075c42a
--- a/CodeEditor/FileController.swift
+++ b/CodeEditor/FileController.swift
@@ -9,7 +9,6 @@
import Cocoa
import Foundation
-
enum DocumentNewResult {
case ok, unknownError
}
@@ -18,28 +17,35 @@ enum DocumentSaveResult {
case ok, emptyText, noEditable, invalidName, unknownError
}
-
class FileController: NSObject {
enum FileKey: String {
- case root = "root"
+ case root = "root"
case folder = "folder"
- case file = "file"
+ case file = "file"
}
var root = FileNode()
var files = [FileNode]()
- var workingFolder = FileNode()
+ var workingFolder = FileNode()
var currentDocument = FileNode()
- var textView : NSTextView?
- var outlineView : NSOutlineView?
- var onSelected : (_ file: FileNode) -> Void = { file in }
+ var textView: NSTextView?
+ var outlineView: NSOutlineView?
+ var onSelected: (_ file: FileNode) -> Void = { file in }
func start() -> FileNode {
- let lastRoot = UserDefaults.standard.url(forKey: FileKey.root.rawValue)
- let lastFolder = UserDefaults.standard.url(forKey: FileKey.folder.rawValue)
- let lastFile = UserDefaults.standard.url(forKey: FileKey.file.rawValue)
+ let lastRoot = UserDefaults.standard.url(
+ forKey: FileKey.root.rawValue
+ )
+
+ let lastFolder = UserDefaults.standard.url(
+ forKey: FileKey.folder.rawValue
+ )
+
+ let lastFile = UserDefaults.standard.url(
+ forKey: FileKey.file.rawValue
+ )
changeRootFolder(lastRoot)
changeWorkingFolder(lastFolder)
@@ -47,18 +53,18 @@ class FileController: NSObject {
//currentDocument.parent = workingFolder
files = listFolder(root.url)
- print("Root: " , lastRoot ?? "Empty")
+ print("Root: ", lastRoot ?? "Empty")
print("Folder: ", lastFolder ?? "Empty")
- print("File: " , lastFile ?? "Empty")
+ print("File: ", lastFile ?? "Empty")
return currentDocument
}
func assignTree(_ treeView: NSOutlineView) {
outlineView = treeView
- outlineView?.delegate = self
+ outlineView?.delegate = self
outlineView?.dataSource = self
- outlineView?.target = self
+ outlineView?.target = self
}
func assignEditor(_ editor: NSTextView) {
@@ -67,14 +73,16 @@ class FileController: NSObject {
func reload() {
outlineView?.reloadData()
- //outlineView?.expandItem(nil, expandChildren: true) // expand all
}
func getWorkingFolder() -> URL? {
let url = workingFolder.url
- if url == nil {
- changeWorkingFolder(FileManager.default.homeDirectoryForCurrentUser)
+ if (url == nil) {
+ changeWorkingFolder(
+ FileManager.default.homeDirectoryForCurrentUser
+ )
+
return workingFolder.url
}
@@ -106,7 +114,7 @@ class FileController: NSObject {
var folder = workingFolder.url!
if !folder.hasDirectoryPath {
- folder = folder.deletingLastPathComponent() // remove file name if any
+ folder = folder.deletingLastPathComponent()
}
workingFolder.url = folder
@@ -117,21 +125,41 @@ class FileController: NSObject {
func saveDefaults() {
print("Saving defaults...")
- UserDefaults.standard.set(root.url, forKey: FileKey.root.rawValue)
- UserDefaults.standard.set(workingFolder.url, forKey: FileKey.folder.rawValue)
- UserDefaults.standard.set(currentDocument.url, forKey: FileKey.file.rawValue)
+ UserDefaults.standard.set(
+ root.url,
+ forKey: FileKey.root.rawValue
+ )
+
+ UserDefaults.standard.set(
+ workingFolder.url,
+ forKey: FileKey.folder.rawValue
+ )
+
+ UserDefaults.standard.set(
+ currentDocument.url,
+ forKey: FileKey.file.rawValue
+ )
}
func saveRootFolder() {
- UserDefaults.standard.set(root.url, forKey: FileKey.root.rawValue)
+ UserDefaults.standard.set(
+ root.url,
+ forKey: FileKey.root.rawValue
+ )
}
func saveWorkingFolder() {
- UserDefaults.standard.set(workingFolder.url, forKey: FileKey.folder.rawValue)
+ UserDefaults.standard.set(
+ workingFolder.url,
+ forKey: FileKey.folder.rawValue
+ )
}
func saveCurrentFile() {
- UserDefaults.standard.set(currentDocument.url, forKey: FileKey.file.rawValue)
+ UserDefaults.standard.set(
+ currentDocument.url,
+ forKey: FileKey.file.rawValue
+ )
}
func getFileInfo(_ url: URL?) -> FileNode {
@@ -163,12 +191,13 @@ class FileController: NSObject {
let options: FileManager.DirectoryEnumerationOptions = [.skipsHiddenFiles]
if let fileArray = try? filer.contentsOfDirectory(at: folder!, includingPropertiesForKeys: props, options: options) {
- let results = fileArray.map { url -> FileNode in
+ let results = fileArray.map {
+ url -> FileNode in
do {
- let info = try url.resourceValues(forKeys: [URLResourceKey.localizedNameKey, URLResourceKey.fileResourceTypeKey, URLResourceKey.creationDateKey, URLResourceKey.fileSizeKey, URLResourceKey.isDirectoryKey])
- let file = FileNode()
- file.url = url
+ let info = try url.resourceValues(forKeys: [URLResourceKey.localizedNameKey, URLResourceKey.fileResourceTypeKey, URLResourceKey.creationDateKey, URLResourceKey.fileSizeKey, URLResourceKey.isDirectoryKey])
+ let file = FileNode()
+ file.url = url
file.name = info.localizedName ?? "Error"
file.path = url.path
file.type = info.fileResourceType ?? URLFileResourceType.unknown
@@ -181,7 +210,6 @@ class FileController: NSObject {
}
return file
-
} catch {
print(error)
}
@@ -198,16 +226,16 @@ class FileController: NSObject {
}
func walkTheTree(_ file: FileNode) -> FileNode? {
- print("Finding: ", file.url)
+ print("Searching: ", file.url ?? "No file")
let find = file.url
if root.url == find { return root }
// From root to file
func walker(_ node: FileNode) -> FileNode? {
- print("Walking folder: ", node.url)
+ print("Walking folder: ", node.url ?? "No folder")
if let kids = node.children {
for item in kids {
- print("Walking item: ", item.url)
+ print("Walking item: ", item.url ?? "No item")
if item.url == find { return item }
if item.isFolder {
if let found = walker(item) { return found }
@@ -219,7 +247,7 @@ class FileController: NSObject {
}
let node = walker(file)
- print("Walker found ", node?.url)
+ print("Walker found ", node?.url ?? "None")
return node
}
@@ -391,7 +419,7 @@ extension FileController {
dialog.canChooseDirectories = true
let choice = dialog.runModal()
- if choice == NSFileHandlingPanelOKButton {
+ if choice.rawValue == NSFileHandlingPanelOKButton {
if let url = dialog.url {
changeWorkingFolder(url)
saveWorkingFolder()
@@ -426,7 +454,7 @@ extension FileController {
}
func save() -> DocumentSaveResult {
- print("Saving \(currentDocument.url) ...")
+ print("Saving \(String(describing: currentDocument.url)) ...")
guard let text = textView?.string else { print("Warn: no text to save"); return .emptyText }
guard currentDocument.isEditable else { print("Warn: file is not editable"); return .noEditable }
@@ -459,7 +487,7 @@ extension FileController {
func delete() {
guard let url = currentDocument.url else { return }
- print("Deleting file \(currentDocument.url)...")
+ print("Deleting file \(String(describing: currentDocument.url))...")
guard var row = outlineView?.row(forItem: currentDocument) else { return }
let index = IndexSet(integer: row)
@@ -468,7 +496,7 @@ extension FileController {
//try FileManager.default.removeItem(at: url)
try FileManager.default.removeItem(atPath: url.path)
//files.remove(at: row)
- outlineView?.removeItems(at: index, inParent: nil, withAnimation: .slideUp)
+ outlineView?.removeItems(at: index, inParent: nil, withAnimation: NSTableView.AnimationOptions.slideUp)
// Keep it inside bounds
let numRows = outlineView?.numberOfRows ?? 0
@@ -553,18 +581,13 @@ extension FileController: NSOutlineViewDataSource, NSOutlineViewDelegate {
}
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
- //print("Column item: ", item)
guard let file = item as? FileNode else { return nil }
- //print("Identifier: ", (tableColumn?.identifier)!)
-
- //let cellId = "filename"
let cellId = "DataCell"
- let result = outlineView.make(withIdentifier: cellId, owner: self) as? NSTableCellView
+ let result = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellId), owner: self) as? NSTableCellView
result?.textField?.stringValue = file.name
result?.imageView?.image = file.getFileImage()
result?.textField?.delegate = self
- //print("Result: ", result)
return result
}
@@ -628,7 +651,7 @@ extension FileController: NSTextFieldDelegate {
*/
- override func controlTextDidEndEditing(_ obj: Notification) {
+ func controlTextDidEndEditing(_ obj: Notification) {
//print("Control endEditing")
if let field = obj.object as? NSTextField {
@@ -647,6 +670,15 @@ extension FileController: NSTextFieldDelegate {
return
}
+ /*
+
+ let result = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellId), owner: self) as? NSTableCellView
+
+ result?.textField?.stringValue = file.name
+ result?.imageView?.image = file.getFileImage(fileExt: file.ext)
+ result?.textField?.delegate = self
+ */
+
// If everything ok, rename it
do {
let source = item.url
@@ -655,6 +687,10 @@ extension FileController: NSTextFieldDelegate {
try FileManager.default.moveItem(at: source!, to: target!)
item.url = target
item.name = newName
+
+ // Update image
+ let tableCellView = outlineView?.rowView(atRow: index, makeIfNecessary: false)?.view(atColumn: 0) as? NSTableCellView
+ tableCellView?.imageView?.image = item.getFileImage()
} catch {
// Revert to old name
field.undoManager?.undo()
diff --git a/CodeEditor/FileNode.swift b/CodeEditor/FileNode.swift
old mode 100644
new mode 100755
index 1e89df3..acbc16e
--- a/CodeEditor/FileNode.swift
+++ b/CodeEditor/FileNode.swift
@@ -11,18 +11,18 @@ import Foundation
class FileNode: NSObject {
- var url : URL?
- var name : String = ""
- var path : String = ""
- var type : URLFileResourceType?
- var date : Date = Date()
- var size : Int = 0
+ var url: URL?
+ var name: String = ""
+ var path: String = ""
+ var type: URLFileResourceType?
+ var date: Date = Date()
+ var size: Int = 0
- var isFolder : Bool = false
- var canSave : Bool = true
- var parent : FileNode?
- var children : [FileNode]?
- var childCount : Int {
+ var isFolder: Bool = false
+ var canSave: Bool = true
+ var parent: FileNode?
+ var children: [FileNode]?
+ var childCount: Int {
get {
if children != nil {
return children!.count
@@ -32,16 +32,16 @@ class FileNode: NSObject {
}
}
- var ext : String {
+ var ext: String {
get {
return url?.pathExtension ?? ""
}
}
- var isEditable : Bool {
+ var isEditable: Bool {
get {
//let valid = "swift txt md html xml css js plist py php rb c h json yaml sql"
- let invalid = "exe bin app"
+ let invalid = "exe bin app zip rar tar gz 7z dmg"
return !invalid.contains(ext)
}
}
@@ -50,32 +50,20 @@ class FileNode: NSObject {
override var description: String {
get {
- return "\n Name: \(name)\n Path: \(path)\n Type: \(type)\n Date: \(date)\n Size: \(size)\n isFolder: \(isFolder)\n "
+ return "\n Name: \(name)\n Path: \(path)\n Type: \(String(describing: type))\n Date: \(date)\n Size: \(size)\n isFolder: \(isFolder)\n "
}
}
func isLeaf() -> Bool {
return !isFolder
- //return (childCount == 0)
}
func getFileImage() -> NSImage {
- //let fileType = self.type!
- //print("Type ", fileType)
- /*
- switch ext {
- case ?
- }
- */
-
if isFolder {
- return NSImage(named: NSImageNameFolder)!
- }
-
- return NSImage(named: NSImageNameMultipleDocuments)!
+ return NSImage(named: NSImage.folderName)!
+ }
+ return NSWorkspace.shared.icon(forFileType: ext)
}
-
-
}
diff --git a/CodeEditor/Info.plist b/CodeEditor/Info.plist
old mode 100644
new mode 100755
index 85f7785..d0c82fe
--- a/CodeEditor/Info.plist
+++ b/CodeEditor/Info.plist
@@ -106,7 +106,7 @@
CFBundleShortVersionString
1.0
CFBundleVersion
- 1
+ 229
LSApplicationCategoryType
public.app-category.developer-tools
LSMinimumSystemVersion
diff --git a/CodeEditor/QuickYaml.swift b/CodeEditor/QuickYaml.swift
old mode 100644
new mode 100755
index d01baba..d91bd83
--- a/CodeEditor/QuickYaml.swift
+++ b/CodeEditor/QuickYaml.swift
@@ -10,12 +10,11 @@ import Foundation
class QuickYaml {
-
- func parse(_ text: String) -> Dixy {
+ func parse(_ text: String) -> [String: Any] {
let lines = text.components(separatedBy: "\n")
- var dixy = Dixy()
- var key = ""
- var children = Dixy()
+ var dixy = [String: Any]()
+ var key = ""
+ var children = [String: Any]()
var hasChildren = false
// Lopp dictionary in order or patterns will mess up colorizing
@@ -34,7 +33,7 @@ class QuickYaml {
key = pair.0
if pair.1.isEmpty {
hasChildren = true
- children = Dixy()
+ children = [String: Any]()
} else {
dixy[key] = pair.1
}
@@ -54,9 +53,9 @@ class QuickYaml {
var val = (parts.last ?? "").trimmingCharacters(in: .whitespaces)
if parts.count > 2 { /* colons in value? */
- let index = text.characters.index(of: ":")
+ let index = text.firstIndex(of: ":")
let position = text.index(index!, offsetBy: 1)
- val = text.substring(from: position).trimmingCharacters(in: .whitespaces)
+ val = text[position...].trimmingCharacters(in: .whitespaces)
//print("Colons \(parts.count) - position: \(position) - text: \(val)")
}
diff --git a/CodeEditor/Settings.swift b/CodeEditor/Settings.swift
old mode 100644
new mode 100755
index d2dbe13..eb084e2
--- a/CodeEditor/Settings.swift
+++ b/CodeEditor/Settings.swift
@@ -7,31 +7,90 @@
//
import Foundation
-
+import Cocoa
struct Settings {
- var theme = "light"
+ /// Shared
+ static var shared = Settings()
+
+ /// Theme
+ var theme: String = "system"
+
+ /// is Dark mode?
var isDarkTheme: Bool {
- get { return theme == "dark" }
- set {
- theme = newValue ? "dark" : "light"
- UserDefaults.standard.set(theme, forKey: "theme")
+ get {
+ if (theme == "system") {
+ if #available(OSX 10.14, *) {
+ return UserDefaults.standard.string(forKey: "AppleInterfaceStyle") == "Dark"
+ }
+ else {
+ return false
+ }
+ }
+
+ return theme == "dark"
}
}
- var fontFamily = "Menlo"
- var fontSize = 14
- var wordWrap = false
+ /// Font family
+ var fontFamily: String = "Menlo"
- var indentationChar = "space"
- var indentationCount = 4
-
- var syntaxDefault = "swift"
- var syntaxUnknown = "txt"
+ /// Font size
+ var fontSize: CGFloat = 14
+
+ /// Word wrap enabled
+ var wordWrap: Bool = false
+ /// Indentation character
+ var indentationChar: String = "space"
+
+ /// Indentation count
+ var indentationCount: Int = 4
+
+ /// Default syntax
+ var syntaxDefault: String = "swift"
+
+ /// Handle unknown files as
+ var syntaxUnknown: String = "txt"
+
+ /// Syntax list
var syntaxList: [String: String] = [:]
+ /// Text color in light mode
+ var light_textColor = NSColor("333333")
+
+ /// Background color in light mode
+ var light_backgroundColor = NSColor("FFFFFF")
+ /// Text color in dark mode
+ var dark_textColor = NSColor("EEEEEE")
+
+ /// Background color in dark mode
+ var dark_backgroundColor = NSColor("333333")
+
+ /// Text color in current mode
+ var textColor: NSColor {
+ get {
+ return isDarkTheme
+ ? dark_textColor
+ : light_textColor
+ }
+ }
+
+ /// Background color in current mode
+ var backgroundColor: NSColor {
+ get {
+ return isDarkTheme
+ ? dark_backgroundColor
+ : light_backgroundColor
+ }
+ }
+
+ /**
+ * Load the settings.
+ *
+ * This overwrites the default settings.
+ */
mutating func load() {
guard let url = Bundle.main.url(forResource: "Settings", withExtension: "yaml") else {
print("WARN: Settings file not found")
@@ -44,19 +103,75 @@ struct Settings {
}
let options = QuickYaml().parse(text)
+
+ theme = Default.string(
+ options["theme"],
+ "system"
+ )
- theme = Default.string(options["theme"], "light")
- fontFamily = Default.string(options["font-family"], "menlo")
- fontSize = Default.int(options["font-size"], 14)
- wordWrap = Default.bool(options["word-wrap"], false)
+ fontFamily = Default.string(
+ options["font-family"],
+ "menlo"
+ )
+
+ if let unwrapped = options["font-size"] as? CGFloat {
+ fontSize = unwrapped
+ }
+
+ wordWrap = Default.bool(
+ options["word-wrap"],
+ false
+ )
- indentationChar = Default.string(options["indentation-char"], "space")
- indentationCount = Default.int(options["indentation-count"], 4)
+ light_textColor = NSColor(
+ Default.string(
+ options["light-textColor"],
+ "333333"
+ )
+ )
- syntaxDefault = Default.string(options["syntax-default"], "swift")
- syntaxUnknown = Default.string(options["syntax-unknown"], "txt")
+ light_backgroundColor = NSColor(
+ Default.string(
+ options["light-backgroundColor"],
+ "FFFFFF"
+ )
+ )
+
+ dark_textColor = NSColor(
+ Default.string(
+ options["dark-textColor"],
+ "EEEEEE"
+ )
+ )
+
+ dark_backgroundColor = NSColor(
+ Default.string(
+ options["dark-backgroundColor"],
+ "333333"
+ )
+ )
+
+ indentationChar = Default.string(
+ options["indentation-char"],
+ "space"
+ )
- if let exts = options["extensions"] as? Dixy {
+ indentationCount = Default.int(
+ options["indentation-count"],
+ 4
+ )
+
+ syntaxDefault = Default.string(
+ options["syntax-default"],
+ "swift"
+ )
+
+ syntaxUnknown = Default.string(
+ options["syntax-unknown"],
+ "txt"
+ )
+
+ if let exts = options["file-extensions"] as? [String: Any] {
syntaxList = exts as! [String : String]
}
@@ -65,23 +180,5 @@ struct Settings {
theme = userTheme
}
}
-
- /*
- func save() {
- guard let url = Bundle.main.url(forResource: "Settings", withExtension: "yaml") else {
- print("WARN: Settings file not found")
- return
- }
-
- let text = "" //QuickYaml.toString(self)
-
- if (try? text.write(to: url, atomically: false, encoding: .utf8)) != nil {
- print("ERROR: Settings file could not be saved")
- return
- }
- }
- */
}
-
-
// End
diff --git a/CodeEditor/Settings.yaml b/CodeEditor/Settings.yaml
old mode 100644
new mode 100755
index c0c36ad..ba1b25e
--- a/CodeEditor/Settings.yaml
+++ b/CodeEditor/Settings.yaml
@@ -2,7 +2,7 @@
# Version: 1.0
# File: Settings
-theme: light
+theme: system
font-family : Menlo
font-size : 14
@@ -14,9 +14,18 @@ indentation-count : 4
syntax-default: swift
syntax-unknown: txt
+# light user interface
+light-textColor: 333333
+light-backgroundColor: FFFFFF
+
+# dark user interface
+dark-textColor: EEEEEE
+dark-backgroundColor: 333333
+# end user interface settings
+
# Syntax files for extensions
-extensions:
+file-extensions:
css : css.default.yaml
html : html.default.yaml
js : js.default.yaml
@@ -30,5 +39,5 @@ extensions:
xcworkspacedata : xml.default.yaml
xml : xml.default.yaml
yaml : yaml.default.yaml
-
+ php : php.default.yaml
# End
diff --git a/CodeEditor/Syntax/css.default.yaml b/CodeEditor/Syntax/css.default.yaml
old mode 100644
new mode 100755
diff --git a/CodeEditor/Syntax/html.default.yaml b/CodeEditor/Syntax/html.default.yaml
old mode 100644
new mode 100755
diff --git a/CodeEditor/Syntax/js.default.yaml b/CodeEditor/Syntax/js.default.yaml
old mode 100644
new mode 100755
diff --git a/CodeEditor/Syntax/json.default.yaml b/CodeEditor/Syntax/json.default.yaml
old mode 100644
new mode 100755
diff --git a/CodeEditor/Syntax/php.default.yaml b/CodeEditor/Syntax/php.default.yaml
new file mode 100755
index 0000000..81ee1b5
--- /dev/null
+++ b/CodeEditor/Syntax/php.default.yaml
@@ -0,0 +1,64 @@
+# Macaw 1.0
+# Syntax: php
+# Author: wdg@github
+
+
+colors:
+ red : 990000
+ green : 009900
+ blue : 0000CC
+ magenta : 990099
+ purple : 999900
+ cyan : 009999
+ orange : DD6633
+ yellow : EECC66
+
+ lite-red : CC3333
+ lite-green : 33AA33
+ lite-blue : 6699DD
+ lite-magenta : CC66CC
+ lite-purple : AAAA33
+ lite-cyan : 33AAAA
+
+ white : FFFFFF
+ snow : EEEEEE
+ lite-gray : CCCCCC
+ gray : AAAAAA
+ dark-gray : 333333
+ black : 000000
+
+styles:
+ keywords : magenta
+ attributes : magenta
+ identifiers : blue
+ types : cyan
+ stringLiteral : red
+ commentLine : green
+ commentBlock : green
+
+styles-dark:
+ keywords : lite-magenta
+ attributes : lite-magenta
+ identifiers : lite-blue
+ types : lite-cyan
+ stringLiteral : yellow
+ commentLine : lite-green
+ commentBlock : lite-green
+
+
+order: keywords, attributes, identifiers, types, stringLiteral, commentLine, commentBlock
+
+patterns:
+ keywords : \b(and|list|abstract|global|private|echo|interface|as|static|endswitch|array|null|if|endwhile|or|const|for|endforeach|self|var|while|isset|public|protected|exit|foreach|throw|elseif|include|__FILE__|empty|do|xor|return|parent|clone|use|__CLASS__|__LINE__|else|break|print|eval|new|catch|__METHOD__|case|exception|default|die|__FUNCTION__|enddeclare|final|try|switch|continue|endfor|endif|declare|unset|true|false|trait|goto|instanceof|insteadof|__DIR__|__NAMESPACE__|yield|finally)\b
+ attributes : ((@)(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B))
+ identifiers : (?<=include_once|require_once|include|require|class|struct|enum|function|extension|protocol|var|let)\s*(\w*)
+ types : \b(Int|Float|Double|String|Bool)\b
+ stringLiteral : (".*")
+ numberLiteral : \b([0-9]*(\.[0-9]*)?)\b
+ commentLine : (//.*)
+ commentBlock : (/\*.*?\*/)
+
+options:
+ commentBlock : multiline
+
+#end
diff --git a/CodeEditor/Syntax/swift.default.yaml b/CodeEditor/Syntax/swift.default.yaml
old mode 100644
new mode 100755
diff --git a/CodeEditor/Syntax/xml.default.yaml b/CodeEditor/Syntax/xml.default.yaml
old mode 100644
new mode 100755
diff --git a/CodeEditor/Syntax/yaml.default.yaml b/CodeEditor/Syntax/yaml.default.yaml
old mode 100644
new mode 100755
diff --git a/CodeEditor/SyntaxColorizer.swift b/CodeEditor/SyntaxColorizer.swift
old mode 100644
new mode 100755
index ae44ee3..e52be6b
--- a/CodeEditor/SyntaxColorizer.swift
+++ b/CodeEditor/SyntaxColorizer.swift
@@ -11,41 +11,39 @@ import Foundation
class SyntaxFormatter {
-
- var colors = Dixy()
- var styles = Dixy()
- var stylesDark = Dixy()
- var patterns = Dixy()
- var options = Dixy()
- var order = [String]()
+ var colors = [String: Any]()
+ var styles = [String: Any]()
+ var stylesDark = [String: Any]()
+ var patterns = [String: Any]()
+ var options = [String: Any]()
+ var order = [String]()
var colorTextLite = NSColor("333333")
var colorBackLite = NSColor("FFFFFF")
var colorTextDark = NSColor("EEEEEE")
var colorBackDark = NSColor("333333")
-
- func load(_ syntax: Dixy) {
+ func load(_ syntax: [String: Any]) {
// User defined
- colors = Dixy() // reset
+ colors = [String: Any]() // reset
if syntax["colors"] != nil {
- for (key, val) in syntax["colors"]! as! Dixy {
+ for (key, val) in syntax["colors"]! as! [String: Any] {
let hex = val as! String
colors[key] = NSColor(hex)
}
}
- patterns = Dixy() // reset
+ patterns = [String: Any]() // reset
if syntax["patterns"] != nil {
- patterns = syntax["patterns"]! as! Dixy
+ patterns = syntax["patterns"]! as! [String: Any]
}
if syntax["options"] != nil {
- options = syntax["options"]! as! Dixy
+ options = syntax["options"]! as! [String: Any]
}
if syntax["styles"] != nil {
- styles = syntax["styles"]! as! Dixy
+ styles = syntax["styles"]! as! [String: Any]
if let fore = styles["foreground"] {
colorTextLite = colors[fore as! String] as! NSColor
}
@@ -55,7 +53,7 @@ class SyntaxFormatter {
}
if syntax["styles-dark"] != nil {
- stylesDark = syntax["styles-dark"]! as! Dixy
+ stylesDark = syntax["styles-dark"]! as! [String: Any]
if let fore = stylesDark["foreground"] {
colorTextDark = colors[fore as! String] as! NSColor
}
@@ -72,10 +70,10 @@ class SyntaxFormatter {
}
class SyntaxColorizer {
- var textView : NSTextView?
- var fileExt : String = "swift"
- var format : String = "swift"
- var formatter : SyntaxFormatter?
+ var textView: NSTextView?
+ var fileExt: String = "swift"
+ var format: String = "swift"
+ var formatter: SyntaxFormatter?
var isDark = false
var isColorizable = false
@@ -90,11 +88,11 @@ class SyntaxColorizer {
isColorizable = false
let app = NSApp.delegate as! AppDelegate
- isDark = app.settings.isDarkTheme
+ isDark = Settings.shared.isDarkTheme
// Get syntax file
var name = ""
- if let syntax = app.settings.syntaxList[ext] {
+ if let syntax = Settings.shared.syntaxList[ext] {
name = syntax
format = syntax
} else {
@@ -118,7 +116,7 @@ class SyntaxColorizer {
}
if !filer.fileExists(atPath: url!.path) {
- print("WARN: Syntax file for \(ext) not found")
+ print("WARN: Syntax file for \(ext) not found at \(url!.path)")
return
}
@@ -138,7 +136,7 @@ class SyntaxColorizer {
func colorize() {
guard isColorizable else { return }
guard let textView = textView else { return }
- guard let all = textView.string else { return }
+ let all = textView.string // Non-optional, so no guard
let range = NSString(string: all).range(of: all)
colorize(range)
@@ -148,11 +146,11 @@ class SyntaxColorizer {
func colorize(_ range: NSRange) {
guard isColorizable else { return }
guard let textView = textView else { return }
- guard let text = textView.string else { return }
+ let text = textView.string // Non-optional, so no guard
guard let formatter = formatter else { return }
guard !text.isEmpty else { return }
- var styles = Dixy()
+ var styles = [String: Any]()
if isDark {
styles = formatter.stylesDark
@@ -185,7 +183,7 @@ class SyntaxColorizer {
let pattern = patterns[style] as? String,
let color = colors[colorName as! String] as? NSColor
{
- let attribute = [NSForegroundColorAttributeName: color]
+ let attribute = [NSAttributedString.Key.foregroundColor: color]
var option: NSRegularExpression.Options = []
let styleopt = options[style] as? String
if let multi = styleopt, multi == "multiline" {
@@ -197,16 +195,16 @@ class SyntaxColorizer {
}
}
- func applyStyles(_ range: NSRange, _ pattern: String, _ options: NSRegularExpression.Options, _ attribute: [String: Any]) {
+ func applyStyles(_ range: NSRange, _ pattern: String, _ options: NSRegularExpression.Options, _ attribute: [NSAttributedString.Key: Any]) {
guard let textView = textView else { return }
- let colorNormal = [NSForegroundColorAttributeName: getColorNormal()]
+ let colorNormal = [NSAttributedString.Key.foregroundColor: getColorNormal()]
let regex = try? NSRegularExpression(pattern: pattern, options: options)
- regex?.enumerateMatches(in: textView.string!, options: [], range: range) {
+ regex?.enumerateMatches(in: textView.string, options: [], range: range) {
match, flags, stop in
- let matchRange = match?.rangeAt(1)
+ let matchRange = match?.range(at: 1)
textView.textStorage?.addAttributes(attribute, range: matchRange!)
let maxRange = matchRange!.location + matchRange!.length
diff --git a/CodeEditor/Utils.swift b/CodeEditor/Utils.swift
old mode 100644
new mode 100755
index 352ec65..e2dbfdf
--- a/CodeEditor/Utils.swift
+++ b/CodeEditor/Utils.swift
@@ -8,32 +8,66 @@
import Cocoa
import Foundation
+import Darwin
-
-typealias Dixy = [String: Any]
+class Utils {
+ /*
+ Use:
+ Utils.shell(launchPath: "/usr/bin/env", arguments: ["make", "-C", viewController.filer.root.path])
+ */
+ static func shell(launchPath path: String, arguments args: [String]) -> String {
+ let task = Process()
+ task.launchPath = path
+ task.arguments = args
+
+ let pipe = Pipe()
+ task.standardOutput = pipe
+ task.standardError = pipe
+ task.launch()
+
+ let data = pipe.fileHandleForReading.readDataToEndOfFile()
+ let output = String(data: data, encoding: .utf8)
+ task.waitUntilExit()
+
+ return(output!)
+ }
+
+ static func runCommand(_ cmd: String) -> Int32 {
+ var pid: Int32 = 0
+ let args = ["/bin/sh", "-c", cmd]
+ let argv: [UnsafeMutablePointer?] = args.map{ $0.withCString(strdup) }
+ defer { for case let arg? in argv { free(arg) } }
+ if posix_spawn(&pid, argv[0], nil, nil, argv + [nil], environ) < 0 {
+ print("ERROR: Unable to spawn")
+ return 1
+ }
+ var status: Int32 = 0
+ _ = waitpid(pid, &status, 0)
+ return status
+ }
+}
extension String {
-
func subtext(from pos: Int) -> String {
guard pos >= 0 else { return "" }
- if pos > self.characters.count { return "" }
+ if pos > self.count { return "" }
let first = self.index(self.startIndex, offsetBy: pos)
- let text = self.substring(from: first)
+ let text = self[first...]
- return text
+ return String(text)
}
func subtext(to pos: Int) -> String {
var end = pos
- if pos > self.characters.count { end = self.characters.count }
+ if pos > self.count { end = self.count }
let last = self.index(self.startIndex, offsetBy: end)
- let text = self.substring(to: last)
+ let text = self[...last]
- return text
+ return String(text)
}
func subtext(from ini: Int, to end: Int) -> String {
@@ -42,15 +76,15 @@ extension String {
var fin = end
- if ini > self.characters.count { return "" }
- if end > self.characters.count { fin = self.characters.count }
+ if ini > self.count { return "" }
+ if end > self.count { fin = self.count }
let first = self.index(self.startIndex, offsetBy: ini)
let last = self.index(self.startIndex, offsetBy: fin)
let range = first ..< last
- let text = self.substring(with: range)
+ let text = self[range]
- return text
+ return String(text)
}
}
@@ -65,7 +99,6 @@ extension Bundle {
}
extension NSColor {
-
// Use: NSColor("ffffff")
convenience init(_ hex: String) {
if let hexInt = Int(hex.lowercased(), radix: 16) {
@@ -125,8 +158,6 @@ class Default {
}
}
-
-
/*
Use:
@@ -196,10 +227,9 @@ class Toast {
/*
Use:
-
+
Dialog("Everything is OK?").show()
- Dialog(title:"Warning", info:"The file will be deleted!").show()
-
+ Dialog(title: "Warning", info: "The file will be deleted!").show()
*/
class Dialog {
var title :String = "Message"
@@ -222,11 +252,15 @@ class Dialog {
alert.informativeText = info
alert.addButton(withTitle: "NO")
alert.addButton(withTitle: "YES")
- ok = (alert.runModal() == NSAlertSecondButtonReturn)
+ ok = (alert.runModal() == NSApplication.ModalResponse.alertSecondButtonReturn)
return ok
}
}
+extension Notification.Name {
+ static let AppleInterfaceThemeChangedNotification = Notification.Name("AppleInterfaceThemeChangedNotification")
+ static let updateTheme = NSNotification.Name(rawValue: "updateTheme")
+}
// End
diff --git a/CodeEditor/ViewController.swift b/CodeEditor/ViewController.swift
old mode 100644
new mode 100755
index 9bed8b0..cce2273
--- a/CodeEditor/ViewController.swift
+++ b/CodeEditor/ViewController.swift
@@ -7,48 +7,101 @@
//
import Cocoa
+import Quartz
-class ViewController: NSViewController, NSTextViewDelegate, NSTextStorageDelegate {
-
- let app = NSApp.delegate as! AppDelegate
- var filer = FileController()
+class ViewController: NSViewController, NSTextViewDelegate, NSTextStorageDelegate, QLPreviewPanelDataSource, QLPreviewPanelDelegate {
+ /// Appdelegate
+ let app = NSApp.delegate as! AppDelegate
+
+ /// File Controller
+ var filer = FileController()
+
+ /// Syntax highlighter
var syntax = SyntaxColorizer()
+
+ /// Is the system loading?
var isLoading = false
- let hugeFileSize = 9999999 // 10 mbs ?
-
- @IBOutlet weak var mainSplitter : NSSplitView!
- @IBOutlet weak var fileSplitter : NSSplitView!
+ /// Maximum file size.
+ let hugeFileSize = 9999999 // 10 mb
+
+ /// main screen splitter
+ @IBOutlet weak var mainSplitter: NSSplitView!
+
+ /// File splitter
+ @IBOutlet weak var fileSplitter: NSSplitView!
- @IBOutlet weak var mainArea : NSView!
- @IBOutlet weak var fileArea : NSView!
+ /// Main View
+ @IBOutlet weak var mainArea: NSView!
- @IBOutlet weak var consoleArea : NSView!
- @IBOutlet weak var editorArea : NSView!
- @IBOutlet weak var editorTitle : NSTextField!
+ /// Filetree view
+ @IBOutlet weak var fileArea: NSView!
- @IBOutlet var textEditor : EditorController!
- @IBOutlet var outlineView : NSOutlineView!
+ /// Console view
+ @IBOutlet weak var consoleArea: NSView!
- @IBOutlet weak var buttonMenu : NSButton!
- @IBOutlet weak var buttonNew : NSButton!
- @IBOutlet weak var buttonOpen : NSButton!
- @IBOutlet weak var buttonTheme : NSButton!
- @IBOutlet weak var buttonSave : NSButton!
- @IBOutlet weak var buttonTrash : NSButton!
+ /// Console text view
+ @IBOutlet weak var consoleTextView: NSTextView!
+ /// Editor view
+ @IBOutlet weak var editorArea: NSView!
- @IBAction func onOptionsShow(_ sender: AnyObject) { showOptions() }
- @IBAction func onFileNew(_ sender: AnyObject) { fileNew() }
- @IBAction func onFileOpen(_ sender: AnyObject) { fileOpen() }
- @IBAction func onFileOpenInBrowser(_ sender: AnyObject) { fileOpenInBrowser() }
- @IBAction func onFileSave(_ sender: AnyObject) { fileSave() }
- @IBAction func onFileDelete(_ sender: AnyObject) { fileDelete() }
- @IBAction func onSidebarToggle(_ sender: AnyObject) { sidebarToggle(sender) }
- @IBAction func onConsoleToggle(_ sender: AnyObject) { consoleToggle(sender) }
- @IBAction func onThemeToggle(_ sender: AnyObject) { themeToggle() }
+ /// Editor title
+ @IBOutlet weak var editorTitle: NSTextField!
+ /// Text Editor
+ @IBOutlet var textEditor: EditorController!
+ /// Outline view
+ @IBOutlet var outlineView: NSOutlineView!
+
+ /// New file button
+ @IBOutlet weak var buttonNew: NSButton!
+
+ /// Open (file) button
+ @IBOutlet weak var buttonOpen: NSButton!
+
+ /// Save file button
+ @IBOutlet weak var buttonSave: NSButton!
+
+ /// Trash file button
+ @IBOutlet weak var buttonTrash: NSButton!
+
+ /// Show options
+ @IBAction func onOptionsShow(_ sender: AnyObject) {
+ showOptions()
+ }
+
+ /// on File -> New (click)
+ @IBAction func onFileNew(_ sender: AnyObject) {
+ fileNew()
+ }
+
+ /// on File -> Opem (click)
+ @IBAction func onFileOpen(_ sender: AnyObject) {
+ fileOpen()
+ }
+
+ /// on File -> Save (click)
+ @IBAction func onFileSave(_ sender: AnyObject) {
+ fileSave()
+ }
+
+ /// on File -> Delete (click)
+ @IBAction func onFileDelete(_ sender: AnyObject) {
+ fileDelete()
+ }
+
+ /// on Sidebar -> toggle (click)
+ @IBAction func onSidebarToggle(_ sender: AnyObject) {
+ sidebarToggle(sender)
+ }
+
+ /// on Sidebar -> console (click)
+ @IBAction func onConsoleToggle(_ sender: AnyObject) {
+ consoleToggle(sender)
+ }
+
override func viewDidLoad() {
super.viewDidLoad()
initialize()
@@ -60,24 +113,38 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextStorageDelegat
}
override func viewWillDisappear() {
- //print("Window: ", self.view.window?.frame)
if filer.currentDocument.hasChanged {
_ = filer.save()
}
filer.saveDefaults()
}
- func setTheme() {
- if let window = self.view.window {
- let goDark = app.settings.isDarkTheme
- window.appearance = NSAppearance(named: goDark ? NSAppearanceNameVibrantDark : NSAppearanceNameVibrantLight)
- buttonMenu.image = NSImage(named: goDark ? "icon_menu2" : "icon_menu")
- buttonNew.image = NSImage(named: goDark ? "icon_new2" : "icon_new")
- buttonOpen.image = NSImage(named: goDark ? "icon_open2" : "icon_open")
- buttonTheme.image = NSImage(named: goDark ? "icon_dark2" : "icon_dark")
- buttonSave.image = NSImage(named: goDark ? "icon_save2" : "icon_save")
- buttonTrash.image = NSImage(named: goDark ? "icon_trash2" : "icon_trash")
+ func numberOfPreviewItems(in panel: QLPreviewPanel!) -> Int {
+ return 1
+ }
+
+ func previewPanel(_ panel: QLPreviewPanel!, previewItemAt index: Int) -> QLPreviewItem! {
+ return filer.currentDocument.url! as QLPreviewItem
+ }
+
+ @objc func setTheme() {
+ let goDark = Settings.shared.isDarkTheme
+ if #available(OSX 10.14, *) {
+ NSApp.appearance = NSAppearance(named: goDark ? .darkAqua : .aqua)
+ } else {
+ // Fallback on earlier versions
+ for window in NSApp.windows {
+ window.appearance = NSAppearance(named: goDark ? NSAppearance.Name.vibrantDark : NSAppearance.Name.vibrantLight)
+ }
}
+ buttonNew.image = NSImage(named: goDark ? "icon_new2" : "icon_new")
+ buttonOpen.image = NSImage(named: goDark ? "icon_open2" : "icon_open")
+ buttonSave.image = NSImage(named: goDark ? "icon_save2" : "icon_save")
+ buttonTrash.image = NSImage(named: goDark ? "icon_trash2" : "icon_trash")
+
+ // Fix textview color.
+ textEditor.textColor = Settings.shared.textColor
+ textEditor.backgroundColor = Settings.shared.backgroundColor
}
func sidebarToggle(_ sender: AnyObject) {
@@ -86,11 +153,8 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextStorageDelegat
// Change mark in menu item
if let menuItem = sender as? NSMenuItem {
- menuItem.state = fileArea.isHidden ? 0 : 1
+ menuItem.state = NSControl.StateValue(rawValue: fileArea.isHidden ? 0 : 1)
}
-
- // FIX: Repaint view to remove buggy vertical line
- // WTF?
}
func consoleToggle(_ sender: AnyObject) {
@@ -99,23 +163,51 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextStorageDelegat
// Change mark in menu item
if let menuItem = sender as? NSMenuItem {
- menuItem.state = consoleArea.isHidden ? 0 : 1
+ menuItem.state = NSControl.StateValue(rawValue: consoleArea.isHidden ? 0 : 1)
}
}
+
+ func appendToConsole(_ text: String) {
+ if consoleArea.isHidden {
+ self.consoleToggle(self)
+ }
+
+ // make it not editable.
+ consoleTextView.isEditable = false
+
+ // get the user's calendar
+ let userCalendar = Calendar.current
+
+ // choose which date and time components are needed
+ let requestedComponents: Set = [
+ .year,
+ .month,
+ .day,
+ .hour,
+ .minute,
+ .second
+ ]
+
+ // get the components
+ let dateTimeComponents = userCalendar.dateComponents(
+ requestedComponents,
+ from: Date()
+ )
- func themeToggle() {
- app.settings.isDarkTheme = !app.settings.isDarkTheme
- setTheme()
- // set cursor in prev position, scroll if necessary
- // or do not reload just repaint syntax
- selectedFile(filer.currentDocument)
+ if consoleTextView.string == "" {
+ consoleTextView.string = "Welcome to Macaw!\n"
+ }
+
+ consoleTextView.string = "\(consoleTextView.string)[\(dateTimeComponents.day!)/\(dateTimeComponents.month!)/\(dateTimeComponents.year!) \(dateTimeComponents.hour!):\(dateTimeComponents.minute!).\(dateTimeComponents.second!)] \(text)"
+ consoleTextView.scrollToEndOfDocument(self)
}
-
+
func initialize() {
+ NotificationCenter.default.addObserver(self, selector: #selector(setTheme), name: .updateTheme, object: nil);
consoleArea.isHidden = true
syntax.assignView(textEditor)
- syntax.setFormat(app.settings.syntaxDefault)
+ syntax.setFormat(Settings.shared.syntaxDefault)
let lastFile = filer.start()
filer.assignTree(outlineView)
@@ -131,29 +223,24 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextStorageDelegat
}
func resetEditor() {
- textEditor.font = NSFont(name: "Menlo", size: 14) // TODO: Get from defaults
+ textEditor.font = NSFont(name: Settings.shared.fontFamily, size: Settings.shared.fontSize)
textEditor.isAutomaticQuoteSubstitutionEnabled = false
- textEditor.isAutomaticDashSubstitutionEnabled = false
+ textEditor.isAutomaticDashSubstitutionEnabled = false
textEditor.isAutomaticSpellingCorrectionEnabled = false
- textEditor.isAutomaticLinkDetectionEnabled = false
- textEditor.textStorage?.font = NSFont(name: "Menlo", size: 14)
+ textEditor.isAutomaticLinkDetectionEnabled = false
+ textEditor.textStorage?.font = NSFont(name: Settings.shared.fontFamily, size: Settings.shared.fontSize)
textEditor.textStorage?.delegate = self
// Horizontal scroll
textEditor.enclosingScrollView?.hasHorizontalScroller = true
textEditor.isHorizontallyResizable = true
- textEditor.autoresizingMask = [.viewWidthSizable, .viewHeightSizable]
+ textEditor.autoresizingMask = [NSView.AutoresizingMask.width, NSView.AutoresizingMask.height]
textEditor.textContainer?.containerSize = NSSize(width: Int.max, height: Int.max)
textEditor.textContainer?.widthTracksTextView = false
// Default colors
- if app.settings.isDarkTheme {
- textEditor.backgroundColor = NSColor("333333")
- textEditor.textColor = NSColor("EEEEEE")
- } else {
- textEditor.backgroundColor = NSColor("FFFFFF")
- textEditor.textColor = NSColor("333333")
- }
+ textEditor.textColor = Settings.shared.textColor
+ textEditor.backgroundColor = Settings.shared.backgroundColor
}
func textStorage(_ textStorage: NSTextStorage, didProcessEditing editedMask: NSTextStorageEditActions, range editedRange: NSRange, changeInLength delta: Int) {
@@ -190,9 +277,7 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextStorageDelegat
// Remove old attributes
let old = NSRange(location: 0, length: textEditor.textStorage?.length ?? 0)
- textEditor.textStorage?.removeAttribute(NSForegroundColorAttributeName, range: old)
- //textEditor.textStorage?.setAttributes([:], range: all)
- //textEditor.textStorage?.setAttributedString(NSAttributedString(string: ""))
+ textEditor.textStorage?.removeAttribute(NSAttributedString.Key.foregroundColor, range: old)
textEditor.string = ""
// Assign new text
@@ -206,8 +291,16 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextStorageDelegat
syntax.setFormat(file.ext)
syntax.colorize()
} catch {
- print("Error loading file ", file.url)
+ print("Error loading file ", file.url ?? "No file")
textEditor.string = "[\(file.name) is not editable]"
+
+ // Preview with Quickview
+ if let sharedPanel = QLPreviewPanel.shared() {
+ sharedPanel.delegate = self
+ sharedPanel.dataSource = self
+ sharedPanel.makeKeyAndOrderFront(self)
+ }
+
resetEditor()
}
@@ -247,13 +340,6 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextStorageDelegat
app.filename = "" // reset
}
- func fileOpenInBrowser() {
- if let url = filer.currentDocument.url {
- //print("Open in Browser: ", url)
- NSWorkspace.shared().open(url)
- }
- }
-
func fileSave() {
let result = filer.save()
@@ -273,12 +359,12 @@ class ViewController: NSViewController, NSTextViewDelegate, NSTextStorageDelegat
let timer2: DispatchTime = .now() + .milliseconds(4000)
DispatchQueue.main.asyncAfter(deadline: timer1) {
- self.buttonSave.image = NSImage(named: (self.app.settings.isDarkTheme ? "icon_saved2" : "icon_saved"))
+ self.buttonSave.image = NSImage(named: (Settings.shared.isDarkTheme ? "icon_saved2" : "icon_saved"))
self.buttonSave.title = "Saved"
}
DispatchQueue.main.asyncAfter(deadline: timer2) {
- self.buttonSave.image = NSImage(named: (self.app.settings.isDarkTheme ? "icon_save2" : "icon_save"))
+ self.buttonSave.image = NSImage(named: (Settings.shared.isDarkTheme ? "icon_save2" : "icon_save"))
self.buttonSave.title = "Save"
}
diff --git a/CodeEditor/WindowController.swift b/CodeEditor/WindowController.swift
new file mode 100644
index 0000000..bcc4842
--- /dev/null
+++ b/CodeEditor/WindowController.swift
@@ -0,0 +1,132 @@
+//
+// WindowController.swift
+// Macaw
+//
+// Created by Gaëtan Dezeiraud on 10/05/2019.
+// Copyright © 2019 Armonia. All rights reserved.
+//
+
+import Cocoa
+
+class WindowController: NSWindowController {
+ /// Build file button
+ @IBOutlet weak var buttonBuild: NSButton!
+
+ /// Can we build?
+ func canBuild() -> Bool {
+ if let viewController = self.contentViewController as? ViewController {
+ if viewController.filer.root.isFolder {
+ let filePath = viewController.filer.root.path
+
+ // C & C++ Makefile
+ if FileManager.default.fileExists(
+ atPath: filePath + "/Makefile"
+ ) {
+ return true;
+ }
+
+ // Rust - cargo
+ else if FileManager.default.fileExists(
+ atPath: filePath + "/Cargo.toml"
+ ) {
+ return true;
+ }
+ // NodeJS - npm
+ else if FileManager.default.fileExists(
+ atPath: filePath + "/package.json"
+ ) {
+ return true;
+ }
+ }
+ }
+
+ return false
+ }
+
+ override func windowDidLoad() {
+ super.windowDidLoad()
+
+ /// Check if we can build
+ buttonBuild.isEnabled = canBuild()
+
+ /// Set a timer for every 5 seconds.
+ Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { (timer) in
+ /// Check if we can build
+ self.buttonBuild.isEnabled = self.canBuild()
+ }
+ }
+
+ @IBAction func onBuild(_ sender: Any)
+ {
+ build()
+ }
+
+ func build() {
+ if let viewController = self.contentViewController as? ViewController {
+ if viewController.filer.root.isFolder {
+ let filePath = viewController.filer.root.path
+
+ // C & C++ Makefile
+ if FileManager.default.fileExists(
+ atPath: filePath + "/Makefile"
+ ) {
+ let retVal = Utils.shell(
+ launchPath: "/usr/bin/env",
+ arguments: ["make", "-C", viewController.filer.root.path]
+ )
+
+ viewController.appendToConsole(retVal)
+ }
+ // Rust - cargo
+ else if FileManager.default.fileExists(
+ atPath: filePath + "/Cargo.toml"
+ ) {
+ let retVal = Utils.shell(
+ launchPath: "~/.cargo/bin/cargo",
+ arguments: [
+ "build",
+ "--manifest-path",
+ viewController.filer.root.path + "/Cargo.toml"
+ ]
+ )
+
+ viewController.appendToConsole(retVal)
+ }
+ // NodeJS - npm
+ else if FileManager.default.fileExists(
+ atPath: filePath + "/package.json"
+ ) {
+ let retVal = Utils.shell(
+ launchPath: "/usr/bin/env",
+ arguments: [
+ // Open bash (the trick to remove the "env: node: No such file or directory." error)
+ "/bin/bash",
+ // Force path to npm (hopefully everyone installs it using homebrew.
+ "/usr/local/bin/npm",
+ // @Brouilles original code.
+ "-v",
+ "install",
+ "-C",
+ viewController.filer.root.path
+ ]
+ )
+
+ /*
+ [17/5/2019 19:35.48] /usr/local/bin/npm: line 2: syntax error near unexpected token `;'
+ /usr/local/bin/npm: line 2: `;(function () { // wrapper in case we're in module_context mode'
+ */
+
+ viewController.appendToConsole(retVal)
+ }
+ else {
+ let alert = NSAlert()
+ alert.messageText = "We can not build."
+ alert.informativeText = "Sorry, but we don't detect a supported build system.\n\nif you think this is a mistake please report it on\nhttps://github.com/wdg/CodeEditor"
+ alert.alertStyle = .informational
+ alert.addButton(withTitle: "OK")
+ alert.runModal()
+ }
+ }
+ }
+ }
+}
diff --git a/CodeEditor/appicon.png b/CodeEditor/appicon.png
old mode 100644
new mode 100755
diff --git a/LICENCE.md b/LICENCE.md
new file mode 100644
index 0000000..3157bdd
--- /dev/null
+++ b/LICENCE.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Wesley de Groot, OSS@WesleyDeGroot.nl
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Macaw.entitlements b/Macaw.entitlements
new file mode 100644
index 0000000..0c67376
--- /dev/null
+++ b/Macaw.entitlements
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/CodeEditor.xcodeproj/project.pbxproj b/Macaw.xcodeproj/project.pbxproj
old mode 100644
new mode 100755
similarity index 73%
rename from CodeEditor.xcodeproj/project.pbxproj
rename to Macaw.xcodeproj/project.pbxproj
index 7ace4ec..60c1669
--- a/CodeEditor.xcodeproj/project.pbxproj
+++ b/Macaw.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@@ -26,6 +26,11 @@
3DD010EA1E392595006DE3EF /* yaml.default.yaml in Resources */ = {isa = PBXBuildFile; fileRef = 3DD010E41E392595006DE3EF /* yaml.default.yaml */; };
3DE47FEF1E3406B700BC06D1 /* Settings.yaml in Resources */ = {isa = PBXBuildFile; fileRef = 3DE47FEE1E3406B700BC06D1 /* Settings.yaml */; };
3DEBA8071E32DA1300933697 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DEBA8061E32DA1300933697 /* Utils.swift */; };
+ BC07E07C2285A38200BEDA2C /* WindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC07E07B2285A38200BEDA2C /* WindowController.swift */; };
+ BC59EB402274715900880767 /* Preferences.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BC59EB3F2274715900880767 /* Preferences.storyboard */; };
+ BC59EB42227472DB00880767 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC59EB41227472DB00880767 /* PreferencesViewController.swift */; };
+ BC59EB442274741F00880767 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC59EB432274741F00880767 /* PreferencesWindowController.swift */; };
+ DEB9CCF61F9D250F00559ED4 /* php.default.yaml in Resources */ = {isa = PBXBuildFile; fileRef = DE4AB1AB1F9D1E76006B16FA /* php.default.yaml */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -33,7 +38,7 @@
3D0170791E3252080051E778 /* html.default.yaml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = html.default.yaml; sourceTree = ""; wrapsLines = 0; };
3D01707C1E3252080051E778 /* swift.default.yaml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = swift.default.yaml; sourceTree = ""; wrapsLines = 0; };
3D0E322B1E36DFB900C9F71B /* Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; };
- 3D106F321E29BFDF0081E0EC /* CodeEditor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CodeEditor.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 3D106F321E29BFDF0081E0EC /* Macaw.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Macaw.app; sourceTree = BUILT_PRODUCTS_DIR; };
3D106F351E29BFDF0081E0EC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; wrapsLines = 0; };
3D106F371E29BFDF0081E0EC /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; wrapsLines = 0; };
3D106F391E29BFDF0081E0EC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
@@ -52,6 +57,13 @@
3DD010E41E392595006DE3EF /* yaml.default.yaml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = yaml.default.yaml; sourceTree = ""; };
3DE47FEE1E3406B700BC06D1 /* Settings.yaml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Settings.yaml; sourceTree = ""; };
3DEBA8061E32DA1300933697 /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; wrapsLines = 0; };
+ BC07E07B2285A38200BEDA2C /* WindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowController.swift; sourceTree = ""; };
+ BC59EB3F2274715900880767 /* Preferences.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Preferences.storyboard; sourceTree = ""; };
+ BC59EB41227472DB00880767 /* PreferencesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; sourceTree = ""; };
+ BC59EB432274741F00880767 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = ""; };
+ BCDD662722A1A65900A6A5C4 /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = System/Library/Frameworks/QuickLook.framework; sourceTree = SDKROOT; };
+ DE4AB1AB1F9D1E76006B16FA /* php.default.yaml */ = {isa = PBXFileReference; lastKnownFileType = text; path = php.default.yaml; sourceTree = ""; };
+ DE500211228F1B5E00A31EFF /* Macaw.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Macaw.entitlements; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -69,6 +81,7 @@
isa = PBXGroup;
children = (
3D0170771E3252070051E778 /* css.default.yaml */,
+ DE4AB1AB1F9D1E76006B16FA /* php.default.yaml */,
3D0170791E3252080051E778 /* html.default.yaml */,
3DD010E01E392595006DE3EF /* js.default.yaml */,
3DD010E21E392595006DE3EF /* json.default.yaml */,
@@ -82,17 +95,20 @@
3D106F291E29BFDD0081E0EC = {
isa = PBXGroup;
children = (
+ DE500211228F1B5E00A31EFF /* Macaw.entitlements */,
3D28D9251E31C3970014C41E /* Readme.md */,
3D106F441E29C4380081E0EC /* ToDo.txt */,
+ BC59EB3E2274713800880767 /* PreferencesWindow */,
3D106F341E29BFDF0081E0EC /* CodeEditor */,
3D106F331E29BFDF0081E0EC /* Products */,
+ BCDD662622A1A65900A6A5C4 /* Frameworks */,
);
sourceTree = "";
};
3D106F331E29BFDF0081E0EC /* Products */ = {
isa = PBXGroup;
children = (
- 3D106F321E29BFDF0081E0EC /* CodeEditor.app */,
+ 3D106F321E29BFDF0081E0EC /* Macaw.app */,
);
name = Products;
sourceTree = "";
@@ -104,6 +120,7 @@
3DE47FEE1E3406B700BC06D1 /* Settings.yaml */,
3D0E322B1E36DFB900C9F71B /* Settings.swift */,
3D106F351E29BFDF0081E0EC /* AppDelegate.swift */,
+ BC07E07B2285A38200BEDA2C /* WindowController.swift */,
3D106F371E29BFDF0081E0EC /* ViewController.swift */,
3D1A8B3A1E2FEE070053EB1A /* SyntaxColorizer.swift */,
3D2FFB671E33A04200C309A8 /* EditorController.swift */,
@@ -118,24 +135,43 @@
path = CodeEditor;
sourceTree = "";
};
+ BC59EB3E2274713800880767 /* PreferencesWindow */ = {
+ isa = PBXGroup;
+ children = (
+ BC59EB3F2274715900880767 /* Preferences.storyboard */,
+ BC59EB432274741F00880767 /* PreferencesWindowController.swift */,
+ BC59EB41227472DB00880767 /* PreferencesViewController.swift */,
+ );
+ path = PreferencesWindow;
+ sourceTree = "";
+ };
+ BCDD662622A1A65900A6A5C4 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ BCDD662722A1A65900A6A5C4 /* QuickLook.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
- 3D106F311E29BFDE0081E0EC /* CodeEditor */ = {
+ 3D106F311E29BFDE0081E0EC /* Macaw */ = {
isa = PBXNativeTarget;
- buildConfigurationList = 3D106F411E29BFDF0081E0EC /* Build configuration list for PBXNativeTarget "CodeEditor" */;
+ buildConfigurationList = 3D106F411E29BFDF0081E0EC /* Build configuration list for PBXNativeTarget "Macaw" */;
buildPhases = (
3D106F2E1E29BFDE0081E0EC /* Sources */,
3D106F2F1E29BFDE0081E0EC /* Frameworks */,
+ DEB9CCF71F9D25A000559ED4 /* ShellScript */,
3D106F301E29BFDE0081E0EC /* Resources */,
);
buildRules = (
);
dependencies = (
);
- name = CodeEditor;
+ name = Macaw;
productName = CodeEditor;
- productReference = 3D106F321E29BFDF0081E0EC /* CodeEditor.app */;
+ productReference = 3D106F321E29BFDF0081E0EC /* Macaw.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@@ -145,18 +181,24 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0800;
- LastUpgradeCheck = 0800;
- ORGANIZATIONNAME = Armonia;
+ LastUpgradeCheck = 1020;
+ ORGANIZATIONNAME = WDGWV;
TargetAttributes = {
3D106F311E29BFDE0081E0EC = {
CreatedOnToolsVersion = 8.0;
+ LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
+ SystemCapabilities = {
+ com.apple.Sandbox = {
+ enabled = 0;
+ };
+ };
};
};
};
- buildConfigurationList = 3D106F2D1E29BFDE0081E0EC /* Build configuration list for PBXProject "CodeEditor" */;
- compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ buildConfigurationList = 3D106F2D1E29BFDE0081E0EC /* Build configuration list for PBXProject "Macaw" */;
+ compatibilityVersion = "Xcode 10.0";
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
@@ -167,7 +209,7 @@
projectDirPath = "";
projectRoot = "";
targets = (
- 3D106F311E29BFDE0081E0EC /* CodeEditor */,
+ 3D106F311E29BFDE0081E0EC /* Macaw */,
);
};
/* End PBXProject section */
@@ -180,9 +222,11 @@
3D106F3A1E29BFDF0081E0EC /* Assets.xcassets in Resources */,
3D18F6DB1E3A95B60090F499 /* xml.default.yaml in Resources */,
3D106F3D1E29BFDF0081E0EC /* Main.storyboard in Resources */,
+ BC59EB402274715900880767 /* Preferences.storyboard in Resources */,
3D01707D1E3252080051E778 /* css.default.yaml in Resources */,
3D0170821E3252080051E778 /* swift.default.yaml in Resources */,
3DD010EA1E392595006DE3EF /* yaml.default.yaml in Resources */,
+ DEB9CCF61F9D250F00559ED4 /* php.default.yaml in Resources */,
3D01707F1E3252080051E778 /* html.default.yaml in Resources */,
3DE47FEF1E3406B700BC06D1 /* Settings.yaml in Resources */,
3DD010E61E392595006DE3EF /* js.default.yaml in Resources */,
@@ -192,16 +236,35 @@
};
/* End PBXResourcesBuildPhase section */
+/* Begin PBXShellScriptBuildPhase section */
+ DEB9CCF71F9D25A000559ED4 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "buildNumber=$(/usr/libexec/PlistBuddy -c \"Print CFBundleVersion\" \"${PROJECT_DIR}/${INFOPLIST_FILE}\")\nbuildNumber=$(($buildNumber + 1))\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $buildNumber\" \"${PROJECT_DIR}/${INFOPLIST_FILE}\"";
+ };
+/* End PBXShellScriptBuildPhase section */
+
/* Begin PBXSourcesBuildPhase section */
3D106F2E1E29BFDE0081E0EC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3D28D9241E31643D0014C41E /* FileController.swift in Sources */,
+ BC07E07C2285A38200BEDA2C /* WindowController.swift in Sources */,
+ BC59EB442274741F00880767 /* PreferencesWindowController.swift in Sources */,
3D2E8ADE1E3538C900AF14FC /* FileNode.swift in Sources */,
3D126D2A1E32962600929E24 /* QuickYaml.swift in Sources */,
3D2FFB681E33A04200C309A8 /* EditorController.swift in Sources */,
3DEBA8071E32DA1300933697 /* Utils.swift in Sources */,
+ BC59EB42227472DB00880767 /* PreferencesViewController.swift in Sources */,
3D1A8B3B1E2FEE070053EB1A /* SyntaxColorizer.swift in Sources */,
3D0E322C1E36DFB900C9F71B /* Settings.swift in Sources */,
3D106F381E29BFDF0081E0EC /* ViewController.swift in Sources */,
@@ -227,20 +290,30 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -269,6 +342,7 @@
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_SWIFT3_OBJC_INFERENCE = Default;
};
name = Debug;
};
@@ -276,20 +350,30 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -309,7 +393,9 @@
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_SWIFT3_OBJC_INFERENCE = Default;
};
name = Release;
};
@@ -319,10 +405,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = CodeEditor/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = Armonia.CodeEditor;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = wdgwv.Macaw;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -332,17 +421,20 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = CodeEditor/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = Armonia.CodeEditor;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = wdgwv.Macaw;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 5.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
- 3D106F2D1E29BFDE0081E0EC /* Build configuration list for PBXProject "CodeEditor" */ = {
+ 3D106F2D1E29BFDE0081E0EC /* Build configuration list for PBXProject "Macaw" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3D106F3F1E29BFDF0081E0EC /* Debug */,
@@ -351,7 +443,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 3D106F411E29BFDF0081E0EC /* Build configuration list for PBXNativeTarget "CodeEditor" */ = {
+ 3D106F411E29BFDF0081E0EC /* Build configuration list for PBXNativeTarget "Macaw" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3D106F421E29BFDF0081E0EC /* Debug */,
diff --git a/CodeEditor.xcodeproj/xcuserdata/mini.xcuserdatad/xcschemes/CodeEditor.xcscheme b/Macaw.xcodeproj/xcshareddata/xcschemes/CodeEditor.xcscheme
similarity index 80%
rename from CodeEditor.xcodeproj/xcuserdata/mini.xcuserdatad/xcschemes/CodeEditor.xcscheme
rename to Macaw.xcodeproj/xcshareddata/xcschemes/CodeEditor.xcscheme
index 06e9a0f..8fd1b86 100644
--- a/CodeEditor.xcodeproj/xcuserdata/mini.xcuserdatad/xcschemes/CodeEditor.xcscheme
+++ b/Macaw.xcodeproj/xcshareddata/xcschemes/CodeEditor.xcscheme
@@ -1,6 +1,6 @@
+ BuildableName = "Macaw.app"
+ BlueprintName = "Macaw"
+ ReferencedContainer = "container:Macaw.xcodeproj">
@@ -33,9 +33,9 @@
+ BuildableName = "Macaw.app"
+ BlueprintName = "Macaw"
+ ReferencedContainer = "container:Macaw.xcodeproj">
@@ -56,9 +56,9 @@
+ BuildableName = "Macaw.app"
+ BlueprintName = "Macaw"
+ ReferencedContainer = "container:Macaw.xcodeproj">
@@ -75,9 +75,9 @@
+ BuildableName = "Macaw.app"
+ BlueprintName = "Macaw"
+ ReferencedContainer = "container:Macaw.xcodeproj">
diff --git a/Package.swift b/Package.swift
old mode 100644
new mode 100755
diff --git a/PreferencesWindow/Preferences.storyboard b/PreferencesWindow/Preferences.storyboard
new file mode 100644
index 0000000..71c1915
--- /dev/null
+++ b/PreferencesWindow/Preferences.storyboard
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PreferencesWindow/PreferencesViewController.swift b/PreferencesWindow/PreferencesViewController.swift
new file mode 100644
index 0000000..7286b78
--- /dev/null
+++ b/PreferencesWindow/PreferencesViewController.swift
@@ -0,0 +1,35 @@
+//
+// PreferencesViewController.swift
+// CodeEditor
+//
+// Created by Gaëtan Dezeiraud on 27/04/2019.
+// Copyright © 2019 Dezeiraud. All rights reserved.
+//
+
+import Cocoa
+
+class PreferencesViewController: NSViewController {
+
+ @IBOutlet weak var menuTheme: NSMenu!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ // Set the size for each views
+ self.preferredContentSize = NSMakeSize(self.view.frame.size.width, self.view.frame.size.height)
+ }
+
+ override func viewDidAppear() {
+ super.viewDidAppear()
+
+ // Update window title with the active TabView Title
+ self.parent?.view.window?.title = self.title!
+ }
+
+ @IBAction func changeTheme(_ sender: NSPopUpButtonCell) {
+ Settings.shared.theme = sender.titleOfSelectedItem!.lowercased()
+ UserDefaults.standard.set(Settings.shared.theme, forKey: "theme")
+
+ NotificationCenter.default.post(name: .updateTheme, object: nil)
+ }
+}
diff --git a/PreferencesWindow/PreferencesWindowController.swift b/PreferencesWindow/PreferencesWindowController.swift
new file mode 100644
index 0000000..c7d35ec
--- /dev/null
+++ b/PreferencesWindow/PreferencesWindowController.swift
@@ -0,0 +1,24 @@
+//
+// PreferencesWindowController.swift
+// CodeEditor
+//
+// Created by Gaëtan Dezeiraud on 27/04/2019.
+// Copyright © 2019 Armonia. All rights reserved.
+//
+
+import Cocoa
+
+class PreferencesWindowController: NSWindowController, NSWindowDelegate {
+
+ override func windowDidLoad() {
+ super.windowDidLoad()
+
+ // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
+ }
+
+ func windowShouldClose(_ sender: NSWindow) -> Bool {
+ // Hide the window instead of closing
+ self.window?.orderOut(sender)
+ return false
+ }
+}
diff --git a/Readme.md b/Readme.md
old mode 100644
new mode 100755
index 086299b..de65cf7
--- a/Readme.md
+++ b/Readme.md
@@ -1,46 +1,36 @@
-
+
# Macaw - Code Editor in Swift
-**Macaw Editor** is a simple code editor for Swift specially designed for ease of use without all the bloat of Xcode, just ten megs instead of four gigs. Ideal for coding server apps in Swift, html, css and js. Of course there is no Interface Builder and all the fancy toys, just an editor for quick hacks.
+**Macaw Editor** is a code editor specially designed for ease of use, without all the bloat of an average IDE.
-### Screenshot:
+A ideal editor which is lightweight and opens fast!
-
+Check out the [Roadmap](https://github.com/wdg/CodeEditor/projects/1) towards a new version.
-### Dark theme
-
-
-
-
-### Version 1.0:
-
-Syntax highlighter needs a little polish, some editor commands are ready.
-
-Editor commands implemented:
+### Light theme
-- cmd+N New file
-- cmd+O Open folder
-- cmd+B Open in Browser
-- cmd+S Save file
-- cmd+F Find in file
+
-- cmd+D Duplicate line
-- cmd+L Delete line
-- cmd+Bck Delete to Begin of Line
-- cmd+Del Delete to End of Line
-
-- ctl+Up Move line Up
-- ctl+Dn Move line down
-
-### Version Next:
-
-- Enable console
-- Build and Run: call swift build, show progress in console area
-- Show errors and allow user to jump to files and lines
-
-### Available
-
-If you like what you see, [hire me!](mailto:haxapp@gmail.com)
+### Dark theme
-Or donate via [Patreon](https://www.patreon.com/kuyawa) so I can develop more projects you like!
\ No newline at end of file
+
+
+
+### Shortcuts
+
+| Shortcut | Description |
+|----------|-------------|
+| `⌘+N` | New file |
+| `⌘+O` | Open folder |
+| `⌘+B` | Open in Browser |
+| `⌘+S` | Save file |
+| `⌘+F` | Find in file |
+| | |
+| `⌘+D` | Duplicate line |
+| `⌘+L` | Delete line |
+| `⌘+Bck` | Delete to Begin of Line |
+| `⌘+Del` | Delete to End of Line |
+| | |
+| `⌘+Up` | Move line Up |
+| `⌘+Dn` | Move line down |
diff --git a/Screenshots/Screenshot.jpg b/Screenshots/Screenshot.jpg
old mode 100644
new mode 100755
index 3ff64d0..df7ffc9
Binary files a/Screenshots/Screenshot.jpg and b/Screenshots/Screenshot.jpg differ
diff --git a/Screenshots/Screenshot2.jpg b/Screenshots/Screenshot2.jpg
old mode 100644
new mode 100755
index b9bdfcb..b6d7398
Binary files a/Screenshots/Screenshot2.jpg and b/Screenshots/Screenshot2.jpg differ
diff --git a/Test projects/C++ Project/.gitkeep b/Test projects/C++ Project/.gitkeep
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/Test projects/C++ Project/.gitkeep
@@ -0,0 +1 @@
+
diff --git a/Test projects/C++ Project/Makefile b/Test projects/C++ Project/Makefile
new file mode 100644
index 0000000..ccff6ba
--- /dev/null
+++ b/Test projects/C++ Project/Makefile
@@ -0,0 +1,7 @@
+hellomake: hello.c
+ # Compiling application
+ gcc -o helloExecutable hello.c
+ # Running application
+ ./helloExecutable
+ # Delete application
+ rm helloExecutable
\ No newline at end of file
diff --git a/Test projects/C++ Project/hello.c b/Test projects/C++ Project/hello.c
new file mode 100644
index 0000000..258f583
--- /dev/null
+++ b/Test projects/C++ Project/hello.c
@@ -0,0 +1,7 @@
+#include
+
+int main(void) {
+ printf("Hello World\n");
+ printf("Hello Macaw\n");
+ return 0;
+}
\ No newline at end of file
diff --git a/Test projects/Node.js Project/.gitkeep b/Test projects/Node.js Project/.gitkeep
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/Test projects/Node.js Project/.gitkeep
@@ -0,0 +1 @@
+
diff --git a/Test projects/Node.js Project/app.js b/Test projects/Node.js Project/app.js
new file mode 100644
index 0000000..5a0f36c
--- /dev/null
+++ b/Test projects/Node.js Project/app.js
@@ -0,0 +1 @@
+console.log('Hello Macaw!')
diff --git a/Test projects/Node.js Project/package.json b/Test projects/Node.js Project/package.json
new file mode 100644
index 0000000..fb37449
--- /dev/null
+++ b/Test projects/Node.js Project/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "macaw_test",
+ "version": "1.0.0",
+ "license": "MIT",
+ "description": "This is a test package",
+ "keywords": [
+ "test",
+ "Macaw",
+ "Swift"
+ ],
+ "main": "app.js",
+ "scripts": {
+ "build": "node app.js",
+ "test": "standard"
+ }
+}
\ No newline at end of file
diff --git a/ToDo.txt b/ToDo.txt
deleted file mode 100644
index f093a1b..0000000
--- a/ToDo.txt
+++ /dev/null
@@ -1,112 +0,0 @@
-TODO:
-
-- enable more editor commands
- - tab: indent block
- - shf+tab unindent block
-
-- toggling file panel leaves a vertical line visible that disappear on a small resize
-- on multiline patterns, extend range to prev/next caret ie /* */
-
-- on load if empty last file, start with blank file
-- verify new empty file does not crash the app
-- verify syntax file does not crash the app if malformed
-
-------------------------------------------------------------
-
-x allow to delete files
-x Lite buttons for dark theme
-x find better icons just like xcode, thinner, cooler
-x allow to open files, use folder as root
-x enable editable tree to rename files
-x on load, show last file in tree, expanding folders if needed
-x allow to open file from OS, use App.delegate
-x on opening file from OS, set working folder to file's parent
-x rethink syntax naming to have both themes in one file
-x use styles-dark instead of loading a different scheme
-x use syntax files from app folder, if not found use from bundle
-x add black/white icon for dark/light theme selection
-x move line/block up on cmd+up
-x move line/block dn on cmd+dn
-x dark theme
-x extract syntax files from bundle on firstTime
-x show/hide filer panel, add "show file panel" to main menu
-x create syntax templates for yaml, js and json
-x toolbar: project, new, open, save
-x order files folders first
-x save on editor lost focus, at all times
-x load defaults from settings.yaml
-x duplicate line/block
-x delete line
-x on syntax.format("swift") assign template
-x open project (working folder)
-x work on toolbar: new, open, save
-x scan dir, show all dirs, all files, save as default
-x on file select, if folder do nothing, if file editable show in text field
-x on load: get working folder from userDefaults
-x save last selected file in userDefaults
-x if file in userDefaults, select on load
-x save last window position, if maximized restart maximized
-x load only first node and children, load other children on expand
-x keep working folder in fileController as root or selected
-x add NewFile1.{ext} to working folder, if exists autoincrement
-x keep newfile counter in fileController
-
-x remove tabs, use single window interface
-x work on tabs for docs: name, close
-x appicon Macaw
-x edit Readme.md
-
-
-------------------------------------------------------------
-
-SAMPLE PROJECT TO TEST SYNTAXES:
-
-source
- main.swift
- index.swift
- forums.swift
- utils.swift
-views
- index.html
- data.xml
-public
- logo.png
- script.js
- theme.css
-info.plist
-todo.txt
-readme.md
-
-------------------------------------------------------------
-
-EDITOR COMMANDS:
-
-N x new file
-O x open file
-B open in browser
-S x save file
-R build and run
-F x find and replace
-
-tab if block selected, indent/unindent, else default
-D x duplicate line/block
-L x delete line/block
-del x delete to end of line
-bck x delete to begin of line
-up x move line/block up
-dn x move line/block dn
-U toggle selected case upper/lower/camel
-
-
-------------------------------------------------------------
-
-VERSION 2:
-
-- enable console
-- build: call swift build, show progress in output area
-- on errors show errors and allow user to jump to files and lines
-- show images in image viewer
-- show pdf in pdf viewer
-- research quick view functionality
-
-END.