#using Gtk @Base.kwdef mutable struct Lines reminant::Union{String, Nothing} = nothing lines::Vector{String} = String[] end function Base.push!(ls::Lines, s::String) if ls.reminant != nothing s = ls.reminant * s ls.reminant = nothing end lines = split(s, '\n', keepempty=false) if s[end] == '\n' for l in lines push!(ls.lines, l) end return end ls.reminant = String(lines[end]) for l in lines[1:end - 1] push!(ls.lines, l) end end function launch_process(running::Function, cmd::Cmd; start::Function=()->begin end, stop::Function=()->begin end) Threads.@spawn begin lines = Lines() buf = IOBuffer() process = run(pipeline(ignorestatus(cmd), stdout=buf), wait=false) start() while process_running(process) sleep(1) push!(lines, String(take!(buf))) if length(lines.lines) > 0 running(lines.lines) empty!(lines.lines) end end stop() end end launch_process(`./a.out`; start=()->println("Start"), stop=()->println("Stop")) do strings for s in strings println("Running: $s") end end sleep(60) #win = GtkWindow("Hello", 800, 600) # #function createMenuBar() # mb = GtkMenuBar() # # # file menu # begin # fileMenu = GtkMenuItem("_File") # fileSub = GtkMenu(fileMenu) # push!(fileSub, GtkMenuItem("_New")) # push!(fileSub, GtkMenuItem("_Open")) # push!(fileSub, GtkSeparatorMenuItem()) # fileExit = GtkMenuItem("E_xit") # signal_connect(fileExit, :activate) do widget # Gtk.destroy(win) # end # push!(fileSub, fileExit) # push!(mb, fileMenu) # end # return mb #end # # #vbox = GtkBox(:v) #tv = GtkTextView() #push!(vbox, createMenuBar()) #push!(vbox, GtkScrolledWindow(tv)) #push!(win, vbox) #showall(win) # #if !isinteractive() # @async Gtk.gtk_main() # Gtk.waitforsignal(win, :destroy) #end