From a3166ea3984c2b59336e0f029b4c796ff232c0b4 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 9 Oct 2017 11:39:12 +0000 Subject: new tlcockpit git-svn-id: svn://tug.org/texlive/trunk@45504 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/support/tlcockpit/NEWS | 11 + .../support/tlcockpit/screenshots/pkg-details.png | Bin 64148 -> 155022 bytes Master/texmf-dist/scripts/tlcockpit/tlcockpit.jar | Bin 11667993 -> 11688515 bytes .../texmf-dist/source/support/tlcockpit/build.sbt | 2 +- .../src/main/scala/TLCockpit/ApplicationMain.scala | 340 +++++++++++++++------ .../tlcockpit/src/main/scala/TeXLive/OsInfo.scala | 8 - .../tlcockpit/src/main/scala/TeXLive/OsTools.scala | 40 +++ .../src/main/scala/TeXLive/TLUpdate.scala | 2 +- .../src/main/scala/TeXLive/TlmgrProcess.scala | 8 +- 9 files changed, 308 insertions(+), 103 deletions(-) create mode 100644 Master/texmf-dist/doc/support/tlcockpit/NEWS delete mode 100644 Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsInfo.scala create mode 100644 Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsTools.scala (limited to 'Master') diff --git a/Master/texmf-dist/doc/support/tlcockpit/NEWS b/Master/texmf-dist/doc/support/tlcockpit/NEWS new file mode 100644 index 00000000000..c1dca4d41ad --- /dev/null +++ b/Master/texmf-dist/doc/support/tlcockpit/NEWS @@ -0,0 +1,11 @@ +NEWS for tlcockpit + +version 0.5 +----------- +- better pkg info display +- try to open doc files from pkg info window +- dynamic updates of the update screen during updates + +version 0.4 +----------- +First half-way usable version diff --git a/Master/texmf-dist/doc/support/tlcockpit/screenshots/pkg-details.png b/Master/texmf-dist/doc/support/tlcockpit/screenshots/pkg-details.png index 3bdbec16eb5..0b385b81169 100644 Binary files a/Master/texmf-dist/doc/support/tlcockpit/screenshots/pkg-details.png and b/Master/texmf-dist/doc/support/tlcockpit/screenshots/pkg-details.png differ diff --git a/Master/texmf-dist/scripts/tlcockpit/tlcockpit.jar b/Master/texmf-dist/scripts/tlcockpit/tlcockpit.jar index 844cae67c47..ac6b87c2777 100644 Binary files a/Master/texmf-dist/scripts/tlcockpit/tlcockpit.jar and b/Master/texmf-dist/scripts/tlcockpit/tlcockpit.jar differ diff --git a/Master/texmf-dist/source/support/tlcockpit/build.sbt b/Master/texmf-dist/source/support/tlcockpit/build.sbt index e125b4563d0..a054c933ca8 100644 --- a/Master/texmf-dist/source/support/tlcockpit/build.sbt +++ b/Master/texmf-dist/source/support/tlcockpit/build.sbt @@ -1,6 +1,6 @@ name := "tlcockpit" -version := "0.4" +version := "0.5" scalaVersion := "2.12.3" diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala index 3caada0d9ea..d7b7162107e 100644 --- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala +++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala @@ -6,20 +6,34 @@ package TLCockpit +import javafx.collections.ObservableList +import javafx.scene.control + import TLCockpit.ApplicationMain.getClass -import TeXLive.{TLBackup, TLPackage, TLUpdate, TlmgrProcess} +import TeXLive._ +// import java.io.File +import scalafx.beans.property.StringProperty import scala.collection.mutable.ArrayBuffer import scala.concurrent.{Future, SyncVar} import scala.concurrent.ExecutionContext.Implicits.global +// import scala.reflect.io +// import scala.reflect.io.File import scala.util.{Failure, Success} +import scalafx.beans.property.ObjectProperty import scalafx.geometry.{HPos, Pos, VPos} +import scalafx.scene.Cursor import scalafx.scene.control.Alert.AlertType import scalafx.scene.image.{Image, ImageView} -import scalafx.scene.input.{KeyCode, KeyEvent} +import scalafx.scene.input.{KeyCode, KeyEvent, MouseEvent} +import scalafx.scene.paint.Color // needed see https://github.com/scalafx/scalafx/issues/137 import scalafx.scene.control.TableColumn._ +import scalafx.scene.control.TreeTableColumn._ +import scalafx.scene.control.TreeItem import scalafx.scene.control.Menu._ +import scalafx.scene.control.cell._ +import scalafx.scene.text.Text import scalafx.Includes._ import scalafx.application.{JFXApp, Platform} import scalafx.application.JFXApp.PrimaryStage @@ -32,8 +46,13 @@ import scala.sys.process._ import scalafx.collections.ObservableBuffer import scalafx.collections.ObservableMap +// import java.awt.Desktop + // TODO TreeTableView indentation is lazy -// TODO pkg info - access to doc files +// TODO pkg info - allow opening (maybe preview) of doc files +// use WebView and pdf.js: https://stackoverflow.com/questions/18207116/displaying-pdf-in-javafx +// see https://github.com/scalafx/scalafx-ensemble/blob/master/src/main/scala/scalafx/ensemble/example/web/EnsembleWebView.scala +// TODO better layout of pkg info object ApplicationMain extends JFXApp { @@ -47,9 +66,9 @@ object ApplicationMain extends JFXApp { val iconImage = new Image(getClass.getResourceAsStream("tlcockpit-48.jpg")) val logoImage = new Image(getClass.getResourceAsStream("tlcockpit-128.jpg")) - val pkgs = ObservableMap[String, TLPackage]() - val upds = ObservableMap[String, TLUpdate]() - val bkps = ObservableMap[String, Map[String,TLBackup]]() // pkgname -> (version -> TLBackup)* + val pkgs: ObservableMap[String, TLPackage] = ObservableMap[String, TLPackage]() + val upds: ObservableMap[String, TLUpdate] = ObservableMap[String, TLUpdate]() + val bkps: ObservableMap[String, Map[String, TLBackup]] = ObservableMap[String, Map[String,TLBackup]]() // pkgname -> (version -> TLBackup)* val errorText: ObservableBuffer[String] = ObservableBuffer[String]() val outputText: ObservableBuffer[String] = ObservableBuffer[String]() @@ -120,7 +139,7 @@ object ApplicationMain extends JFXApp { (s: String) => { // errorText.clear() errorText.append(s) - if (s != "") { + if (s.trim != "") { outerrpane.expanded = true outerrtabs.selectionModel().select(1) } @@ -175,7 +194,7 @@ object ApplicationMain extends JFXApp { }.showAndWait() } - val OutputBuffer = ObservableBuffer[String]() + val OutputBuffer: ObservableBuffer[String] = ObservableBuffer[String]() var OutputBufferIndex:Int = 0 val OutputFlushLines = 100 OutputBuffer.onChange { @@ -242,23 +261,49 @@ object ApplicationMain extends JFXApp { } def callback_update(s: String): Unit = { + var prevUpdName = "" + var prevUpdPkg = new TLUpdate("","","","","","") lineUpdateFunc = (l:String) => { // println("line update: " + l + "=") l match { case u if u.startsWith("location-url") => None case u if u.startsWith("total-bytes") => None case u if u.startsWith("end-of-header") => None - case u if u.startsWith("end-of-updates") => None + // case u if u.startsWith("end-of-updates") => None case u if u == "OK" => None case u if u.startsWith("tlmgr>") => None case u => - val foo = parse_one_update_line(l) - upds.remove(foo.name.value) - val op = pkgs(foo.name.value) - pkgs(foo.name.value) = new TLPackage(foo.name.value, op.rrev.value.toString, op.rrev.value.toString, foo.shortdesc.value, op.size.value.toString, "Installed") - Platform.runLater { - trigger_update("upds") - trigger_update("pkgs") + if (prevUpdName != "") { + // println("Removing " + prevUpdName + " from list!") + upds.remove(prevUpdName) + val op = pkgs(prevUpdName) + pkgs(prevUpdName) = new TLPackage(prevUpdPkg.name.value, op.rrev.value.toString, op.rrev.value.toString, + prevUpdPkg.shortdesc.value, op.size.value.toString, "Installed") + Platform.runLater { + trigger_update("upds") + trigger_update("pkgs") + } + } + if (u.startsWith("end-of-updates")) { + // nothing to be done, all has been done above + // println("got end of updates") + } else { + // println("getting update line") + val foo = parse_one_update_line(l) + val pkgname = foo.name.value + val PkgTreeItemOption = updateTable.root.value.children.find(_.value.value.name.value == pkgname) + PkgTreeItemOption match { + case Some(p) => + prevUpdName = pkgname + prevUpdPkg = p.getValue + // println("Setting status to Updating ... for " + pkgname) + prevUpdPkg.status = StringProperty("Updating ...") + Platform.runLater { + // println("calling updateTable refresh") + updateTable.refresh() + } + case None => println("Very strange: Cannot find TreeItem for upd package" + pkgname) + } } } } @@ -484,7 +529,7 @@ object ApplicationMain extends JFXApp { def callback_show_pkg_info(pkg: String): Unit = { - tlmgr_async_command(s"info $pkg", pkginfo => { + tlmgr_async_command(s"info --list $pkg", pkginfo => { // need to call runLater to go back to main thread! Platform.runLater { val dialog = new Dialog() { @@ -500,20 +545,180 @@ object ApplicationMain extends JFXApp { padding = Insets(20) } var crow = 0 + val runFiles = ArrayBuffer[String]() + val docFiles = ArrayBuffer[String]() + val binFiles = ArrayBuffer[String]() + val srcFiles = ArrayBuffer[String]() + var whichFiles = "run" // we assume run files if not found! pkginfo.foreach((line: String) => { - val keyval = line.split(":", 2).map(_.trim) - if (keyval.length == 2) { - val keylabel = new Label(keyval(0)) - val vallabel = new Label(keyval(1)) - vallabel.wrapText = true - grid.add(keylabel, 0, crow) - grid.add(vallabel, 1, crow) - crow += 1 + if (line.startsWith(" ")) { + // files are listed with two spaces in the beginning + whichFiles match { + case "run" => runFiles += line.trim + case "doc" => docFiles += line.trim + case "bin" => binFiles += line.trim + case "src" => srcFiles += line.trim + case _ => println("Don't know what to do?!?!") + } + } else { + val keyval = line.split(":", 2).map(_.trim) + whichFiles = if (keyval(0).startsWith("run files")) "run" else + if (keyval(0).startsWith("doc files")) "doc" else + if (keyval(0).startsWith("source files")) "src" else + if (keyval(0).startsWith("bin files (all platforms)")) "bin" else + "unknown" + if (keyval.length == 2) { + if (keyval(0) == "doc files" || keyval(0) == "source files" || keyval(0) == "run files" || + keyval(0).startsWith("bin files (all platforms)") || keyval(0).startsWith("Included files, by type")) { + // do nothing + } else { + val keylabel = new Label(keyval(0)) + val vallabel = new Label(keyval(1)) + vallabel.wrapText = true + grid.add(keylabel, 0, crow) + grid.add(vallabel, 1, crow) + crow += 1 + } + } } }) + // add files section + if (runFiles.nonEmpty) { + grid.add(new Label("run files"), 0, crow) + grid.add(new Label(runFiles.mkString("\n")) { wrapText = true },1, crow) + crow += 1 + } + if (docFiles.nonEmpty) { + grid.add(new Label("doc files"), 0, crow) + val vb = new VBox() + vb.children = docFiles.map { f => + val fields = f.split(" ") + new Label(fields(0)) { + textFill = Color.Blue + onMouseClicked = { me: MouseEvent => + println("Do something with " + fields(0)) + // TODO while does gio return immediately on bash prompt but not here? + // ("gio open " + tlmgr.tlroot + "/" + fields(0)).! + //Desktop.getDesktop().open((tlmgr.tlroot + "/" + fields(0))) + OsTools.openFile(tlmgr.tlroot + "/" + fields(0)) + println("done") + } + cursor = Cursor.Hand + } + } + //grid.add(new Label(docFiles.mkString("\n")) { wrapText = true },1, crow) + grid.add(vb,1,crow) + crow += 1 + } + if (srcFiles.nonEmpty) { + grid.add(new Label("src files"), 0, crow) + grid.add(new Label(srcFiles.mkString("\n")) { wrapText = true },1, crow) + crow += 1 + } + if (binFiles.nonEmpty) { + grid.add(new Label("bin files"), 0, crow) + grid.add(new Label(binFiles.mkString("\n")) { wrapText = true },1, crow) + crow += 1 + } grid.columnConstraints = Seq(new ColumnConstraints(100, 150, 200), new ColumnConstraints(100, 300, 5000, Priority.Always, new HPos(HPos.Left), true)) dialog.dialogPane().content = grid - dialog.width = 500 + // dialog.width = 500 + // dialog.height = 800 + dialog.showAndWait() + } + }) + } + def callback_show_pkg_info_dev(pkg: String): Unit = { + tlmgr_async_command(s"info --list $pkg", pkginfo => { + // need to call runLater to go back to main thread! + Platform.runLater { + val dialog = new Dialog() { + initOwner(stage) + title = s"Package Information for $pkg" + // headerText = s"Package Information for $pkg" + resizable = true + } + dialog.dialogPane().buttonTypes = Seq(ButtonType.OK) + val keyCol = new TreeTableColumn[(String,String), String] { + text = "Package" + cellValueFactory = { p => StringProperty(p.value.value.value._1) } + } + val valCol = new TreeTableColumn[(String,String), String] { + text = pkg + cellValueFactory = { p => StringProperty(p.value.value.value._2) } + } + val infoTable = new TreeTableView[(String, String)]( + new TreeItem[(String, String)](("","")) { + expanded = false + }) { + columns ++= List(keyCol, valCol) + } + valCol.prefWidth.bind(infoTable.width - keyCol.width - 15) + infoTable.prefHeight = 300 + infoTable.vgrow = Priority.Always + infoTable.showRoot = false + infoTable.fixedCellSize = Region.USE_COMPUTED_SIZE + val runFiles = ArrayBuffer[String]() + val docFiles = ArrayBuffer[String]() + val binFiles = ArrayBuffer[String]() + val srcFiles = ArrayBuffer[String]() + val kids = ArrayBuffer[TreeItem[(String,String)]]() + var whichFiles = "run" // we assume run files if not found! + pkginfo.foreach((line: String) => { + if (line.startsWith(" ")) { + // files are listed with two spaces in the beginning + whichFiles match { + case "run" => runFiles += line.trim + case "doc" => docFiles += line.trim + case "bin" => binFiles += line.trim + case "src" => srcFiles += line.trim + case _ => println("Don't know what to do?!?!") + } + } else { + val keyval = line.split(":", 2).map(_.trim) + whichFiles = if (keyval(0).startsWith("run files")) "run" else + if (keyval(0).startsWith("doc files")) "doc" else + if (keyval(0).startsWith("source files")) "src" else + if (keyval(0).startsWith("bin files (all platforms)")) "bin" else + "unknown" + if (keyval.length == 2) { + if (keyval(0) == "doc files" || keyval(0) == "source files" || keyval(0) == "run files" || + keyval(0).startsWith("bin files (all platforms)")) { + // do nothing + } else { + kids += new TreeItem[(String,String)]((keyval(0), keyval(1))) + } + } + } + }) + // add files section + if (docFiles.nonEmpty) { + kids += new TreeItem[(String,String)](("Doc files","")) { + children = docFiles.map { p => new TreeItem[(String,String)](("",p)) } + } + } + if (runFiles.nonEmpty) { + kids += new TreeItem[(String,String)](("Run files","")) { + children = runFiles.map { p => new TreeItem[(String,String)](("",p)) } + } + } + if (srcFiles.nonEmpty) { + kids += new TreeItem[(String,String)](("Source files","")) { + children = srcFiles.map { p => new TreeItem[(String,String)](("",p)) } + } + } + if (binFiles.nonEmpty) { + kids += new TreeItem[(String,String)](("Bin files","")) { + children = binFiles.map { p => new TreeItem[(String,String)](("",p)) } + } + } + infoTable.root = new TreeItem[(String, String)](("","")) { + expanded = true + children = kids + } + dialog.dialogPane().content = infoTable + // dialog.width = 500 + // dialog.height = 800 dialog.showAndWait() } }) @@ -533,7 +738,7 @@ object ApplicationMain extends JFXApp { f"${fileSize/Math.pow(1024, digitGroup)}%3.1f ${units(digitGroup)}" } - val mainMenu = new Menu("TLCockpit") { + val mainMenu: Menu = new Menu("TLCockpit") { items = List( update_all_menu, update_self_menu, @@ -571,33 +776,18 @@ object ApplicationMain extends JFXApp { onAction = (ae: ActionEvent) => callback_quit() }) } - val optionsMenu = new Menu("Options") { - items = List( - new MenuItem("General ...") { - disable = true; onAction = (ae) => not_implemented_info() - }, - new MenuItem("Paper ...") { - disable = true; onAction = (ae) => not_implemented_info() - }, - new MenuItem("Platforms ...") { - disable = true; onAction = (ae) => not_implemented_info() - }, + val optionsMenu: Menu = new Menu("Options") { + items = List( new MenuItem("General ...") { disable = true; onAction = (ae) => not_implemented_info() }, + new MenuItem("Paper ...") { disable = true; onAction = (ae) => not_implemented_info() }, + new MenuItem("Platforms ...") { disable = true; onAction = (ae) => not_implemented_info() }, new SeparatorMenuItem, - new CheckMenuItem("Expert options") { - disable = true - }, - new CheckMenuItem("Enable debugging options") { - disable = true - }, - new CheckMenuItem("Disable auto-install of new packages") { - disable = true - }, - new CheckMenuItem("Disable auto-removal of server-deleted packages") { - disable = true - } + new CheckMenuItem("Expert options") { disable = true }, + new CheckMenuItem("Enable debugging options") { disable = true }, + new CheckMenuItem("Disable auto-install of new packages") { disable = true }, + new CheckMenuItem("Disable auto-removal of server-deleted packages") { disable = true } ) } - val helpMenu = new Menu("Help") { + val helpMenu: Menu = new Menu("Help") { items = List( /* new MenuItem("Manual") { @@ -609,10 +799,10 @@ object ApplicationMain extends JFXApp { }, ) } - val statusMenu = new Menu("Status: Idle") { + val statusMenu: Menu = new Menu("Status: Idle") { disable = true } - val expertPane = new TitledPane { + val expertPane: TitledPane = new TitledPane { text = "Experts only" collapsible = true expanded = false @@ -630,31 +820,11 @@ object ApplicationMain extends JFXApp { onAction = (event: ActionEvent) => callback_run_cmdline() } ) - }, - /* new HBox { - spacing = 10 - children = List( - new Button { - text = "Show updates" - onAction = (e: ActionEvent) => callback_show_updates() - }, - new Button { - text = "Show installed" - onAction = (e: ActionEvent) => callback_show_installed() - }, - new Button { - text = "Show all" - onAction = (e: ActionEvent) => callback_show_all() - }, - update_self_button, - update_all_button - ) } - */ ) } } - val updateTable = { + val updateTable: TreeTableView[TLUpdate] = { val colName = new TreeTableColumn[TLUpdate, String] { text = "Package" cellValueFactory = { _.value.value.value.name } @@ -720,24 +890,12 @@ object ApplicationMain extends JFXApp { } table } - val packageTable = { + val packageTable: TreeTableView[TLPackage] = { val colName = new TreeTableColumn[TLPackage, String] { text = "Package" cellValueFactory = { _.value.value.value.name } prefWidth = 150 } - /* - val colLRev = new TableColumn[TLPackage, String] { - text = "Local rev" - cellValueFactory = { _.value.lrev } - prefWidth = 100 - } - val colRRev = new TableColumn[TLPackage, String] { - text = "Remote rev" - cellValueFactory = { _.value.rrev } - prefWidth = 100 - } - */ val colDesc = new TreeTableColumn[TLPackage, String] { text = "Description" cellValueFactory = { _.value.value.value.shortdesc } @@ -776,7 +934,7 @@ object ApplicationMain extends JFXApp { } table } - val backupTable = { + val backupTable: TreeTableView[TLBackup] = { val colName = new TreeTableColumn[TLBackup, String] { text = "Package" cellValueFactory = { _.value.value.value.name } @@ -817,7 +975,7 @@ object ApplicationMain extends JFXApp { } table } - val pkgstabs = new TabPane { + val pkgstabs: TabPane = new TabPane { minWidth = 400 vgrow = Priority.Always tabs = Seq( @@ -850,7 +1008,7 @@ object ApplicationMain extends JFXApp { } } ) - val menuBar = new MenuBar { + val menuBar: MenuBar = new MenuBar { useSystemMenuBar = true // menus.addAll(mainMenu, optionsMenu, helpMenu) menus.addAll(mainMenu, statusMenu) @@ -899,7 +1057,7 @@ object ApplicationMain extends JFXApp { } */ - var lineUpdateFunc = { (l: String) => } // println(s"DEBUG: got ==$l== from tlmgr") } + var lineUpdateFunc: String => Unit = { (l: String) => } // println(s"DEBUG: got ==$l== from tlmgr") } val bar = Future { while (true) { diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsInfo.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsInfo.scala deleted file mode 100644 index 3b5ad20864f..00000000000 --- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsInfo.scala +++ /dev/null @@ -1,8 +0,0 @@ -package TeXLive - -object OsInfo { - val OS = System.getProperty("os.name") - def isWindows: Boolean = { - OS.startsWith("Windows") - } -} diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsTools.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsTools.scala new file mode 100644 index 00000000000..38d0c334d99 --- /dev/null +++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsTools.scala @@ -0,0 +1,40 @@ +package TeXLive + +import scala.concurrent.Future +import scala.concurrent.ExecutionContext.Implicits.global +import sys.process._ + +object OsTools { + val OS = System.getProperty("os.name").map(_.toLower) + def isWindows: Boolean = { + OS.startsWith("windows") + } + def isApple: Boolean = { + OS.startsWith("mac os") + } + def isUnix: Boolean = { + !(isWindows || isApple) + } + + def openFileCmd(f: String): Seq[String] = { + val absf = new java.io.File(f).getCanonicalPath + if (isWindows) { + Seq("cmd", "start", absf) + } else if (isApple) { + Seq("open", absf) + } else { + Seq("xdg-open", absf) + } + } + + def openFile(f: String): Unit = { + val cmd = openFileCmd(f) + val bar = Future { + try { + cmd.! + } catch { + case e: Exception => println("Cannot run command: " + cmd + " -- " + e + "\n") + } + } + } +} diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLUpdate.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLUpdate.scala index 427ad722ceb..43623a523dd 100644 --- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLUpdate.scala +++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLUpdate.scala @@ -5,7 +5,7 @@ import scalafx.beans.property.{ObjectProperty, StringProperty} // Note!!! we have to use ObjectProperty[Int] here instead of IntegerProperty // since IntegerProperty does NOT implement Observable[Int,Int] // see https://github.com/scalafx/scalafx/issues/243 -case class TLUpdate(name: StringProperty, status: StringProperty, lrev: StringProperty, rrev: StringProperty, +case class TLUpdate(name: StringProperty, var status: StringProperty, lrev: StringProperty, rrev: StringProperty, shortdesc: StringProperty, size: StringProperty) { def this(_name: String, _status: String, _lrev: String, _rrev: String, _shortdesc: String, _size: String) = this( diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala index c65058e169a..33c76d6708c 100644 --- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala +++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala @@ -2,17 +2,21 @@ package TeXLive import java.io._ -import OsInfo._ +import OsTools._ import scala.collection.mutable.ArrayBuffer import scala.concurrent.SyncVar -import scala.sys.process.{Process, ProcessBuilder, ProcessIO} +// import scala.sys.process.{Process, ProcessBuilder, ProcessIO} +import scala.sys.process._ class TlmgrProcess(updout: Array[String] => Unit, upderr: String => Unit, updline: String => Unit) { val inputString = new SyncVar[String] // used for the tlmgr process input val outputString = new SyncVar[String] // used for the tlmgr process output val errorBuffer: StringBuffer = new StringBuffer() // buffer used for both tmgr process error console AND logging + val tlroot = "kpsewhich -var-value SELFAUTOPARENT".!!.trim + // println("tlroot ==" + tlroot + "==") + // set in only one place, in the main thread var process: Process = _ var lastInput: String = "" -- cgit v1.2.3