Skip to content

Instantly share code, notes, and snippets.

@samfiechter
Forked from tib/swiftui-script.swift
Last active June 20, 2021 15:20
Show Gist options
  • Save samfiechter/2b4161ad4d3bee42dd9e65e5cbb54690 to your computer and use it in GitHub Desktop.
Save samfiechter/2b4161ad4d3bee42dd9e65e5cbb54690 to your computer and use it in GitHub Desktop.
Edited Tibor Bödecs's swiftui-script to allow for some GNUPlot automation...
#! /usr/bin/swift
// to compile: swiftc -o window window.swift
// Forked from from https://gist.github.com/tib/183b2f5e4ac1d5afba5d69155ec11025
// Making a 3d graph with GNUPlot... Idea is to use w/ an automator service script to add a 3d plot to Numbers
import Foundation
import AppKit
import SwiftUI
@available(OSX 10.15, *)
class AppDelegate: NSObject, NSApplicationDelegate {
var inpFN : String
var pngFN : String
init (inp: String, png : String){
inpFN = inp
pngFN = png
}
let window = NSWindow(contentRect: NSMakeRect(0, 0, 800, 600),
styleMask: [.titled, .closable, .miniaturizable],
backing: .buffered,
defer: false)
let windowDelegate = WindowDelegate()
func applicationDidFinishLaunching(_ notification: Notification) {
let contentSize = NSSize(width:800, height:600)
window.setContentSize(contentSize)
window.delegate = windowDelegate
window.title = "iGNUPlot"
let graph = NSHostingView(rootView: rootView())
graph.frame = NSRect(origin: NSPoint(x:0, y:0), size: contentSize)
graph.autoresizingMask = [.height, .width]
window.contentView!.addSubview(graph)
window.center()
window.makeKeyAndOrderFront(self)
}
class WindowDelegate: NSObject, NSWindowDelegate {
func windowWillClose(_ notification: Notification) {
NSApplication.shared.terminate(0)
}
}
}
struct rootView: View {
@State private var img : NSImage = NSImage()
@State private var data : String
@State private var title : String = ""
@State private var xlbl : String = ""
@State private var ylbl : String = ""
@State private var zlbl : String = ""
@State private var angle : String = "45"
private var cmd : String {
return """
set xlabel \"\(xlbl)\"
set ylabel \"\(ylbl)\"
set zlabel \"\(zlbl)\"
set title \"\(title)\"
set terminal png size 1024,768
set view ,\(angle),1
set autoscale
unset key
$grid << EOD
\(data)
EOD
set grid
set hidden3d
set pm3d
set term png
set output \"\(pngFN)\"
splot '$grid' matrix rowheaders columnheaders with lines
"""
}
private var pngFN : String
private var inpFN : String
init() {
pngFN = (NSApplication.shared.delegate as! AppDelegate).pngFN
inpFN = (NSApplication.shared.delegate as! AppDelegate).inpFN
img = NSImage()
do {
var enc : UInt = 0
let str : String = try NSString(contentsOfFile: inpFN, usedEncoding: &enc) as String? ?? "Read Error"
print(str)
data = str
runGNUPlot()
} catch {
data = "File read error \(inpFN)"
}
}
func runGNUPlot(){
let gp : String = "/usr/local/bin/gnuplot"
print(cmd)
let cmdout = shellCMD( gp, input: cmd)
img = NSImage(byReferencingFile: pngFN) ?? NSImage()
}
var body: some View {
VStack {
Text("3-D Chart").font(.headline)
HStack{
Button(action: self.runGNUPlot){
Text("Run GNUPlot")
}
Image(nsImage: img).resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 512, height: 300)
}
TextField("Title:",text: $title)
TextField("X Label",text:$xlbl)
TextField("Y Label",text:$ylbl)
TextField("Z Label",text:$zlbl)
TextField("Angle",text: $angle)
}.padding(10)
}
}
func shellCMD(_ command: String, input: String) -> String {
let task = Process()
let pipe = Pipe()
let inp = Pipe()
inp.fileHandleForWriting.write(input.data(using: .utf8)!)
inp.fileHandleForWriting.closeFile()
task.standardInput = inp
task.standardOutput = pipe
task.standardError = pipe
task.arguments = ["-c", command]
task.launchPath = "/bin/zsh"
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)!
return output
}
let args = CommandLine.arguments
if (args.count == 3 ) {
let del = AppDelegate(inp: args[1], png: args[2])
let application = NSApplication.shared
application.setActivationPolicy(NSApplication.ActivationPolicy.regular)
application.delegate = del
application.activate(ignoringOtherApps: true)
application.run()
} else {
print("iGNUPlot <inputFN.tsv> <GraphFN.png>")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment