Skip to content

Commit 32fba79

Browse files
authored
Add files via upload
1 parent a9cd510 commit 32fba79

File tree

20 files changed

+662
-0
lines changed

20 files changed

+662
-0
lines changed

build.sbt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
ThisBuild / scalaVersion := "3.2.1"
2+
3+
lazy val hello = (project in file("."))
4+
.enablePlugins(ScalaJSPlugin, ScalablyTypedConverterPlugin)
5+
.settings(
6+
name := "Scala.js Tutorial",
7+
scalaJSUseMainModuleInitializer := true,
8+
libraryDependencies += "org.rogach" %%% "scallop" % "4.1.0",
9+
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.8.1" % "test",
10+
testFrameworks += new TestFramework("utest.runner.Framework"),
11+
Compile / npmDependencies ++= Seq(
12+
"@types/node" -> "18.11.18"
13+
),
14+
stOutputPackage := "typings"
15+
)
16+
17+
18+
// This is an application with a main method
19+
20+
//
21+
22+
// Add support for the DOM in `run` and `test`
23+
//jsEnv := new org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv()
24+
25+
// uTest settings

project/build.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sbt.version=1.8.0

project/metals.sbt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// DO NOT EDIT! This file is auto-generated.
2+
3+
// This file enables sbt-bloop to create bloop config files.
4+
5+
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.6")
6+

project/plugins.sbt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.12.0")
2+
addSbtPlugin("org.scalablytyped.converter" % "sbt-converter" % "1.0.0-beta40")
3+
4+
//libraryDependencies += "org.scala-js" %% "scalajs-env-jsdom-nodejs" % "1.1.0"

project/project/metals.sbt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// DO NOT EDIT! This file is auto-generated.
2+
3+
// This file enables sbt-bloop to create bloop config files.
4+
5+
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.6")
6+

project/project/project/metals.sbt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// DO NOT EDIT! This file is auto-generated.
2+
3+
// This file enables sbt-bloop to create bloop config files.
4+
5+
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.6")
6+
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package tutorial.webapp
2+
3+
import java.util.Locale
4+
import tutorial.webapp.StringExtensions.substringAfterLast
5+
import tutorial.webapp.StringExtensions.substringAfterFirst
6+
import tutorial.webapp.StringExtensions.substringBeforeFirst
7+
import tutorial.webapp.ExtractionStrategy
8+
9+
object DebFiles {
10+
11+
def getExecFromDesktop(desktopFileContents: String): Option[String] =
12+
val i1 =
13+
desktopFileContents.linesIterator
14+
.filter(line => line.substringBeforeFirst("=").trim.equalsIgnoreCase("Exec"))
15+
.map(execLine => execLine.substringAfterFirst("="))
16+
i1.nextOption()
17+
18+
def getNameFromDesktop(desktopFileContents: String): Option[String] =
19+
val i1 =
20+
desktopFileContents.linesIterator
21+
.filter(line => line.contains("Name"))
22+
.map(nameLine => nameLine.replace("Name", "").replace('=', ' ').trim)
23+
i1.nextOption()
24+
25+
def processExistingDesktop(desktopFileContents: String, pkgName: String, eStrategy: ExtractionStrategy): String =
26+
val v1 =
27+
desktopFileContents.linesIterator
28+
.map(line =>
29+
val eqSignIdx = line.indexOf("=")
30+
if (eqSignIdx != -1) {
31+
val beforeSign = line.substringBeforeFirst("=").trim()
32+
if (beforeSign.equalsIgnoreCase("Exec")) {
33+
val afterSign = line.substringAfterFirst("=").trim()
34+
val cmd = buildExecCmd(eStrategy, pkgName, Some(afterSign))
35+
s"Exec=${cmd}"
36+
} else if (beforeSign.equalsIgnoreCase("Icon")) {
37+
s"Icon=${pkgName}"
38+
} else {
39+
line
40+
}
41+
} else {
42+
line
43+
}
44+
).mkString("\n")
45+
v1
46+
47+
def buildExecCmd(eStrategy: ExtractionStrategy, pkgName: String, existingCommand: Option[String]): String =
48+
eStrategy match {
49+
case ExtractionStrategy.Preserve =>
50+
s"/opt/${pkgName}/${pkgName}.AppImage"
51+
case ExtractionStrategy.Unpack =>
52+
if (existingCommand.count(cmd => cmd.contains("AppRun")) == 1) {
53+
s"/opt/${pkgName}/${existingCommand.get}"
54+
} else {
55+
s"/opt/${pkgName}/AppRun"
56+
}
57+
}
58+
59+
def buildDesktopFile(appImageFileName: String, visibleAppName: Option[String], dirNameInOpt: String): String =
60+
val appImageFileNoExtension = appImageFileName.substring(0, appImageFileName.lastIndexOf("."))
61+
Seq(
62+
"[Desktop Entry]",
63+
s"Name=${visibleAppName.getOrElse(appImageFileNoExtension)}",
64+
s"Exec=gnome-terminal -e /opt/${dirNameInOpt}/AppRun --no-sandbox %U",
65+
"Terminal=true",
66+
"Type=Application",
67+
).mkString("\n")
68+
69+
def buildControlFile(pkgName: String, installedSize: Int, pkgVersion: String): String =
70+
Seq(
71+
s"Package: ${pkgName}",
72+
s"Version: ${pkgVersion}",
73+
"Architecture: all",
74+
"Maintainer: appimage2deb",
75+
s"Installed-Size: ${installedSize}",
76+
"Section: Miscellaneous",
77+
"Priority: optional",
78+
"Description: Converted from AppImage",
79+
" Application archive converted from AppImage",
80+
"" // without this: end of file during value of field 'Description' (missing final newline)
81+
).mkString("\n")
82+
83+
84+
def buildPostInst(): String =
85+
Seq(
86+
"#!/bin/sh",
87+
"update-desktop-database",
88+
).mkString("\n")
89+
90+
def buildPostRm(): String =
91+
buildPostInst()
92+
93+
def buildExecFile(execCmd: String): String =
94+
Seq(
95+
"#!/bin/sh",
96+
execCmd + " " +" \"$@\"",
97+
).mkString("\n")
98+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package tutorial.webapp
2+
3+
enum ExtractionStrategy:
4+
case Preserve, Unpack
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package tutorial.webapp
2+
3+
import scala.scalajs.js
4+
5+
object Interop {
6+
7+
def toScalaArray(input: js.typedarray.Uint8Array): Array[Byte] =
8+
input.view.map(_.toByte).toArray
9+
10+
def toScalaArray(input: js.Array[Double]): Array[Byte] =
11+
input.view.map(_.toByte).toArray
12+
13+
def toScalaArray(input: js.Array[String]): Array[String] =
14+
input.view.toArray
15+
16+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package tutorial.webapp
2+
3+
import typings.node.childProcessMod as node_child_process
4+
import typings.node.utilMod as node_util
5+
import typings.node.fsMod as node_fs
6+
import typings.node.osMod as node_os
7+
import typings.node.pathMod as node_path
8+
import typings.node.bufferMod.global.BufferEncoding
9+
10+
object Node {
11+
12+
def readFile(filePath: String): String =
13+
val opts = BufferEncoding.utf8
14+
val read = node_fs.readFileSync(filePath, opts)
15+
read
16+
17+
def writeFile(filePath: String, contents: String): Unit =
18+
node_fs.writeFileSync(filePath, contents)
19+
20+
def rename(oldPath: String, newPath: String): Unit =
21+
node_fs.renameSync(oldPath, newPath)
22+
23+
def cp(filePath1: String, filePath2: String): Unit =
24+
node_fs.copyFileSync(filePath1, filePath2)
25+
26+
def makeDir(dirPath: String): Unit =
27+
try {
28+
if (!node_fs.existsSync(dirPath)) {
29+
val opts = node_fs.MakeDirectoryOptions()
30+
opts.recursive = true
31+
node_fs.mkdirSync(dirPath, opts)
32+
}
33+
} catch {
34+
case e: Exception =>
35+
throw Exception(s"Couldn't create a new directory: ${dirPath}", e)
36+
}
37+
38+
def makeTmpDir(): String =
39+
try {
40+
val tmpDir = node_fs.mkdtempSync(node_path.join(node_os.tmpdir(), "appimage2deb-"));
41+
tmpDir
42+
} catch {
43+
case e: Exception =>
44+
throw Exception(s"Couldn't create a new temporary directory", e)
45+
}
46+
47+
def chmod(filePath: String, mode: Int): Unit =
48+
try {
49+
node_fs.chmodSync(filePath, mode.toDouble);
50+
} catch {
51+
case e: Exception =>
52+
throw Exception(s"Couldn't chmod ${filePath} on ${filePath}")
53+
}
54+
55+
def filesInDir(dirPath: String): Array[String] =
56+
val res = node_fs.readdirSync(dirPath)
57+
Interop.toScalaArray(res)
58+
59+
def filesInDirRecursive(dirPath: String): List[String] =
60+
val filesInDirectory = node_fs.readdirSync(dirPath);
61+
val a1 =
62+
filesInDirectory
63+
.flatMap(file =>
64+
val nextPath = node_path.resolve(dirPath, file);
65+
val stats = node_fs.statSync(nextPath).getOrElse(scala.sys.error(s"Couldn't read directory ${nextPath}"))
66+
if (stats.isDirectory()) {
67+
filesInDirRecursive(nextPath);
68+
} else {
69+
List(nextPath);
70+
}
71+
)
72+
.toList
73+
a1
74+
75+
// private def filesInDirRecursiveAux(directory: String, collected: ArrayBuffer[String]): Unit =
76+
// val filesInDirectory = node_fs.readdirSync(directory);
77+
// filesInDirectory.foreach(file =>
78+
// val absolute = node_path.join(directory, file);
79+
// if (node_fs.statSync(absolute).isDirectory()) {
80+
// filesInDirRecursiveAux(absolute, collected);
81+
// } else {
82+
// collected.push(absolute);
83+
// }
84+
// )
85+
86+
def desktopFileInDir(dirPath: String): Option[String] =
87+
filesInDir(dirPath)
88+
.filter(path => path.endsWith(".desktop"))
89+
.map(node_path.resolve(dirPath, _))
90+
.headOption
91+
92+
def appIconInDir(dirPath: String): Option[String] =
93+
try {
94+
val linkVal = node_fs.readlinkSync(node_path.resolve(dirPath, ".DirIcon"))
95+
Some(node_path.resolve(dirPath, linkVal))
96+
} catch {
97+
case e: Exception =>
98+
filesInDir(dirPath)
99+
.filter(path => path.endsWith(".png") || path.endsWith(".svg"))
100+
.map(node_path.resolve(dirPath, _))
101+
.headOption
102+
}
103+
104+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package tutorial.webapp
2+
3+
object StringExtensions {
4+
extension (str: String) {
5+
6+
def substringAfterFirst(part: String) =
7+
str.indexOf(part) match {
8+
case -1 => "";
9+
case i => str.substring(i + part.length)
10+
}
11+
12+
def substringAfterLast(part: String) =
13+
str.lastIndexOf(part) match {
14+
case -1 => "";
15+
case i => str.substring(i + part.length)
16+
}
17+
18+
def substringBeforeFirst(part: String) =
19+
str.indexOf(part) match {
20+
case -1 => "";
21+
case i => str.substring(0, i)
22+
}
23+
24+
def substringBeforeLast(part: String) =
25+
str.lastIndexOf(part) match {
26+
case -1 => "";
27+
case i => str.substring(0, i)
28+
}
29+
30+
}
31+
}

0 commit comments

Comments
 (0)