Skip to content

Commit e263de5

Browse files
committedOct 8, 2024·
Split own package manager into separate files
1 parent cfb79be commit e263de5

File tree

6 files changed

+387
-377
lines changed

6 files changed

+387
-377
lines changed
 

‎ownlang-desktop/src/main/resources/scripts/own.own

Lines changed: 7 additions & 377 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
use std, files, http, json, functional, downloader, robot, java
1+
use std
22

3-
PB = newClass("java.lang.ProcessBuilder")
3+
include "own/Registry.own"
4+
include "own/Config.own"
5+
include "own/Packages.own"
6+
include "own/Projects.own"
7+
include "own/Own.own"
48

5-
DEBUG=getenv("OWN_DEBUG", false) == "true"
9+
DEBUG=getenv("OWN_DEBUG", "false") == "true"
610
logger = {}
711
logger.color = def(num = 0) = sprintf("%s[0%sm", toChar(27), num > 0 ? (";" + num) : "")
812
logger.error = def(a = "", b = "", c = "") = echo(logger.color(31) + a, b, c + logger.color())
@@ -13,380 +17,6 @@ logger.debug = match(DEBUG) {
1317
case _: def(a = "", b = "", c = "") = 0
1418
}
1519

16-
class Registry {
17-
GLOBAL_URL = "https://raw.githubusercontent.com/aNNiMON/Own-Programming-Language-Tutorial/registry/registry.json"
18-
19-
def Registry(ctx) {
20-
this.ctx = ctx
21-
this.registry = {}
22-
this.registryPackages = {}
23-
this.registryCacheFile = ctx.TMPDIR + "/ownlang-registry.json"
24-
}
25-
26-
def isRegistryLoaded() = length(this.registry) > 0
27-
28-
def getPackages() {
29-
this.ctx.logger.debug("Registry.getPackages")
30-
if !this.isRegistryLoaded() {
31-
this.loadRegistry()
32-
}
33-
return this.registryPackages
34-
}
35-
36-
def loadRegistry() {
37-
this.ctx.logger.debug("Registry.loadRegistry")
38-
if (!this.loadFromCache()) {
39-
this.loadFromHttp()
40-
}
41-
}
42-
43-
def loadFromCache() {
44-
this.ctx.logger.debug("Registry.loadFromCache")
45-
if exists(this.registryCacheFile) {
46-
f = fopen(this.registryCacheFile, "r")
47-
this.registry = jsondecode(readText(f))
48-
this.registryPackages = this.registry.packages ?? {}
49-
fclose(f)
50-
return true
51-
}
52-
return false
53-
}
54-
55-
def loadFromHttp() {
56-
this.ctx.logger.debug("Registry.loadFromHttp")
57-
extract(ok, content) = httpSync(this.GLOBAL_URL)
58-
this.registry = ok ? jsondecode(content) : {}
59-
this.registryPackages = this.registry.packages ?? {}
60-
if (ok) this.updateCache()
61-
return ok
62-
}
63-
64-
def updateCache() {
65-
this.ctx.logger.debug("Registry.updateCache")
66-
f = fopen(this.registryCacheFile, "w")
67-
writeText(f, jsonencode(this.registry, 0))
68-
flush(f)
69-
fclose(f)
70-
}
71-
}
72-
73-
class Config {
74-
def Config(ctx) {
75-
this.ctx = ctx
76-
this.configName = "own-package.json"
77-
this.config = {}
78-
}
79-
80-
def createNewConfig() = {"dependencies": {}}
81-
82-
def getConfig() {
83-
this.ctx.logger.debug("Config.getConfig")
84-
if length(this.config) == 0 {
85-
f = fopen(this.configName, "i")
86-
this.config = exists(f)
87-
? this.loadConfig()
88-
: this.createNewConfig()
89-
fclose(f)
90-
}
91-
return this.config
92-
}
93-
94-
def loadConfig() {
95-
this.ctx.logger.debug("Config.loadConfig")
96-
f = fopen(this.configName, "r")
97-
config = jsondecode(readText(f))
98-
fclose(f)
99-
return config
100-
}
101-
102-
def saveConfig(config) {
103-
this.ctx.logger.debug("Config.saveConfig")
104-
f = fopen(this.configName, "w")
105-
writeText(f, jsonencode(config, 2))
106-
flush(f)
107-
fclose(f)
108-
}
109-
110-
def mergeConfig(config) {
111-
this.ctx.logger.debug("Config.mergeConfig")
112-
mapping = {
113-
"name": def() = this.getDefaultProjectName(),
114-
"version": def() = this.getDefaultVersion(),
115-
"author": def() = this.getDefaultAuthor(),
116-
"program": def() = this.getDefaultProgram(),
117-
"scripts": def() = {
118-
"default": ["$ownlang$", "-f", "$program$"]
119-
},
120-
"dependencies": def() = {},
121-
}
122-
for property, defaultValue : mapping {
123-
if !arrayKeyExists(property, config)
124-
config[property] = defaultValue()
125-
}
126-
return config
127-
}
128-
129-
def getDefaultProjectName() {
130-
this.ctx.logger.debug("Config.getDefaultProjectName")
131-
parts = getprop("user.dir").replace("\\", "/").split("/")
132-
name = parts[parts.length - 1]
133-
.toLowerCase()
134-
.replace("\\s+", "_")
135-
.replaceAll("[^a-z\\-_]", "")
136-
return match(length(name)) {
137-
case 0: "project"
138-
case x if x > 20: substring(name, 0, 20)
139-
case _: name
140-
}
141-
}
142-
143-
def getDefaultVersion() = "1.0.0"
144-
def getDefaultAuthor() = getprop("user.name", "unknown")
145-
def getDefaultProgram() = "main.own"
146-
}
147-
148-
class Packages {
149-
def Packages(ctx) {
150-
this.ctx = ctx
151-
this.packagesDir = "own-modules"
152-
this.usageFile = ".usage.own"
153-
}
154-
155-
def addDependencies(packages) {
156-
this.ctx.logger.debug("Packages.addDependencies", packages)
157-
if packages.isEmpty() {
158-
this.ctx.logger.error("No package names provided. Try: own add telegram-bot")
159-
return false
160-
}
161-
res = true
162-
config = this.ctx.config.getConfig()
163-
for package : packages {
164-
res = res && this.addDependency(package, config)
165-
}
166-
return res
167-
}
168-
169-
def addDependency(packageName, config) {
170-
this.ctx.logger.debug("Packages.addDependency", packageName)
171-
if packageName == "" {
172-
this.ctx.logger.error("No package name provided. Try: own add telegram-bot")
173-
return false
174-
}
175-
// Check in global registry
176-
registryPackages = this.ctx.registry.getPackages()
177-
if !arrayKeyExists(packageName, registryPackages) {
178-
this.ctx.logger.error("Unknown package " + packageName + ". Check if the name specified correctly")
179-
return false
180-
}
181-
dep = registryPackages[packageName]
182-
// Check if exists in config
183-
if arrayKeyExists(packageName, config.dependencies ?? {}) {
184-
// Exists, check version match
185-
if dep.version == config.dependencies[packageName] {
186-
this.ctx.logger.info("Package " + packageName + " is up to date")
187-
return true
188-
}
189-
}
190-
// Install this dependency
191-
dep.name = packageName
192-
config.dependencies[packageName] = dep.version
193-
downloaded = this.ctx.packages.downloadPackage(dep)
194-
logText = "Installing " + packageName + " " + dep.version
195-
if downloaded {
196-
this.ctx.logger.success(logText + " [success]")
197-
} else {
198-
this.ctx.logger.error(logText + " [failure]")
199-
}
200-
return downloaded
201-
}
202-
203-
def downloadDependencies(dependencies) {
204-
this.ctx.logger.debug("Packages.downloadDependencies")
205-
if length(dependencies) == 0 {
206-
this.ctx.logger.error("No dependency packages provided, or own-package.json is missing")
207-
return false
208-
}
209-
registryPackages = this.ctx.registry.getPackages()
210-
for name, version : dependencies {
211-
logText = "Installing " + name + " " + version
212-
dep = registryPackages[name] ?? {"downloaded": 0}
213-
if !(dep.downloaded ?? 0) {
214-
dep.name = name
215-
dep.downloaded = this.ctx.packages.downloadPackage(dep)
216-
}
217-
if dep.downloaded {
218-
this.ctx.logger.success(logText + " [success]")
219-
} else {
220-
this.ctx.logger.error(logText + " [failure]")
221-
}
222-
}
223-
return true
224-
}
225-
226-
def getPackageFiles(dep) = match (dep.type ?? 0) {
227-
case "gist": {
228-
this.ctx.logger.debug("Packages.getPackageFiles for gist")
229-
extract(ok, content) = httpSync("https://api.github.com/gists/" + dep.id)
230-
return match ok {
231-
case false: []
232-
case true: stream(jsondecode(content).files)
233-
.map(def(r) = [r[0], r[1].raw_url])
234-
.toArray()
235-
}
236-
}
237-
case _: []
238-
}
239-
240-
def getPackagePath(package) {
241-
this.ctx.logger.debug("Packages.getPackagePath", package)
242-
dir = this.packagesDir + "/" + package
243-
stream([this.packagesDir, dir])
244-
.filterNot(::exists)
245-
.forEach(::mkdir)
246-
return dir
247-
}
248-
249-
def downloadPackage(dep) {
250-
this.ctx.logger.debug("Packages.downloadPackage", dep.name)
251-
files = this.getPackageFiles(dep)
252-
dir = this.getPackagePath(dep.name)
253-
result = 0
254-
for mf : files {
255-
extract(name, url) = mf
256-
result += downloader(url, dir + "/" + name)
257-
}
258-
return result > 0
259-
}
260-
261-
def showUsages(packages) {
262-
this.ctx.logger.debug("Packages.showUsages", packages)
263-
if packages.isEmpty() {
264-
this.ctx.logger.error("No package names provided")
265-
return false
266-
}
267-
config = this.ctx.config.getConfig()
268-
for package : packages {
269-
this.showUsage(package, config)
270-
}
271-
return true
272-
}
273-
274-
def showUsage(package, config) {
275-
file = this.packagesDir + "/" + package + "/" + this.usageFile
276-
exists = arrayKeyExists(package, config.dependencies ?? {})
277-
&& exists(file)
278-
if !exists {
279-
this.ctx.logger.error("[" + package + "] "
280-
+ "Error: no .usage.own file provided in the package,"
281-
+ " or the package is not installed")
282-
return false
283-
}
284-
this.ctx.logger.success("\n[" + package + "]")
285-
f = fopen(file, "r")
286-
this.ctx.logger.info(readText(f))
287-
fclose(f)
288-
return true
289-
}
290-
}
291-
292-
class Projects {
293-
def Projects(ctx) {
294-
this.ctx = ctx
295-
this.defaultPrograms = {
296-
"main.own" : "use std\n\necho(\"Hello, world!\", ARGS)"
297-
}
298-
}
299-
300-
def savePrograms() {
301-
this.ctx.logger.debug("Projects.savePrograms")
302-
for name, content : this.defaultPrograms {
303-
if exists(name) continue
304-
f = fopen(name, "w")
305-
writeText(f, content)
306-
flush(f)
307-
fclose(f)
308-
}
309-
}
310-
}
311-
312-
class Own {
313-
def Own(ctx) {
314-
this.ctx = ctx
315-
}
316-
317-
def init() {
318-
this.ctx.logger.debug("Own.init")
319-
config = this.ctx.config.getConfig()
320-
config = this.ctx.config.mergeConfig(config)
321-
this.ctx.config.saveConfig(config)
322-
this.ctx.projects.savePrograms()
323-
this.ctx.logger.success("Project created")
324-
}
325-
326-
def install() {
327-
this.ctx.logger.debug("Own.install")
328-
config = this.ctx.config.getConfig()
329-
this.ctx.packages.downloadDependencies(config.dependencies ?? {})
330-
}
331-
332-
def addDependencies() {
333-
packages = this.nonEmptyArgs()
334-
this.ctx.logger.debug("Own.addDependencies", packages)
335-
this.ctx.packages.addDependencies(packages)
336-
this.ctx.config.saveConfig(this.ctx.config.getConfig())
337-
}
338-
339-
def showUsages() {
340-
packages = this.nonEmptyArgs()
341-
this.ctx.logger.debug("Own.showUsages", packages)
342-
this.ctx.packages.showUsages(packages)
343-
}
344-
345-
def runScript(script) {
346-
this.ctx.logger.debug("Own.runScript", script)
347-
config = this.ctx.config.getConfig()
348-
vars = {
349-
"$ownlang$": "ownlang" + (this.ctx.OSNAME.startsWith("win") ? ".cmd" : ""),
350-
"$program$": config.program ?? "",
351-
"$dir$": getprop("user.dir").replace("\\", "/")
352-
}
353-
if (script == "") script = "default"
354-
if arrayKeyExists(script, config.scripts ?? {}) {
355-
commands = []
356-
for c : config.scripts[script] {
357-
commands += arrayKeyExists(c, vars) ? vars[c] : c
358-
}
359-
this.ctx.logger.debug("Own.runScript run:", commands)
360-
pb = new PB(commands)
361-
pb.inheritIO()
362-
p = pb.start()
363-
} else {
364-
this.ctx.logger.error("No script '%s' found in config's scripts section".sprintf(script))
365-
}
366-
}
367-
368-
def usage() {
369-
this.ctx.logger.info("own package manager v1.0.0")
370-
this.ctx.logger.info("")
371-
this.ctx.logger.info("
372-
|Usage: own [options]
373-
| options:
374-
| init initialize new project
375-
| add [package] add new package dependency to own-package.json
376-
| usage [package] display the package usage (from .usage.own) if exists
377-
| install install packages defined in own-package.json
378-
| run run program defined in the config program section
379-
| run [script] run script defined in the config scripts section
380-
".stripMargin())
381-
}
382-
383-
def nonEmptyArgs(skip = 1) = stream(ARGS)
384-
.skip(skip)
385-
.filter(def(s) = !s.isEmpty())
386-
.toArray()
387-
}
388-
389-
39020
ctx = {}
39121
ctx.DEBUG = DEBUG
39222
ctx.TMPDIR = getenv("TEMP", getenv("TMP", "."))
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use std, files, json
2+
3+
class Config {
4+
def Config(ctx) {
5+
this.ctx = ctx
6+
this.configName = "own-package.json"
7+
this.config = {}
8+
}
9+
10+
def createNewConfig() = {"dependencies": {}}
11+
12+
def getConfig() {
13+
this.ctx.logger.debug("Config.getConfig")
14+
if length(this.config) == 0 {
15+
f = fopen(this.configName, "i")
16+
this.config = exists(f)
17+
? this.loadConfig()
18+
: this.createNewConfig()
19+
fclose(f)
20+
}
21+
return this.config
22+
}
23+
24+
def loadConfig() {
25+
this.ctx.logger.debug("Config.loadConfig")
26+
f = fopen(this.configName, "r")
27+
config = jsondecode(readText(f))
28+
fclose(f)
29+
return config
30+
}
31+
32+
def saveConfig(config) {
33+
this.ctx.logger.debug("Config.saveConfig")
34+
f = fopen(this.configName, "w")
35+
writeText(f, jsonencode(config, 2))
36+
flush(f)
37+
fclose(f)
38+
}
39+
40+
def mergeConfig(config) {
41+
this.ctx.logger.debug("Config.mergeConfig")
42+
mapping = {
43+
"name": def() = this.getDefaultProjectName(),
44+
"version": def() = this.getDefaultVersion(),
45+
"author": def() = this.getDefaultAuthor(),
46+
"program": def() = this.getDefaultProgram(),
47+
"scripts": def() = {
48+
"default": ["$ownlang$", "-f", "$program$"]
49+
},
50+
"dependencies": def() = {},
51+
}
52+
for property, defaultValue : mapping {
53+
if !arrayKeyExists(property, config)
54+
config[property] = defaultValue()
55+
}
56+
return config
57+
}
58+
59+
def getDefaultProjectName() {
60+
this.ctx.logger.debug("Config.getDefaultProjectName")
61+
parts = getprop("user.dir").replace("\\", "/").split("/")
62+
name = parts[parts.length - 1]
63+
.toLowerCase()
64+
.replace("\\s+", "_")
65+
.replaceAll("[^a-z\\-_]", "")
66+
return match(length(name)) {
67+
case 0: "project"
68+
case x if x > 20: substring(name, 0, 20)
69+
case _: name
70+
}
71+
}
72+
73+
def getDefaultVersion() = "1.0.0"
74+
def getDefaultAuthor() = getprop("user.name", "unknown")
75+
def getDefaultProgram() = "main.own"
76+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use std, java, robot
2+
3+
PB = newClass("java.lang.ProcessBuilder")
4+
5+
class Own {
6+
def Own(ctx) {
7+
this.ctx = ctx
8+
}
9+
10+
def init() {
11+
this.ctx.logger.debug("Own.init")
12+
config = this.ctx.config.getConfig()
13+
config = this.ctx.config.mergeConfig(config)
14+
this.ctx.config.saveConfig(config)
15+
this.ctx.projects.savePrograms()
16+
this.ctx.logger.success("Project created")
17+
}
18+
19+
def install() {
20+
this.ctx.logger.debug("Own.install")
21+
config = this.ctx.config.getConfig()
22+
this.ctx.packages.downloadDependencies(config.dependencies ?? {})
23+
}
24+
25+
def addDependencies() {
26+
packages = this.nonEmptyArgs()
27+
this.ctx.logger.debug("Own.addDependencies", packages)
28+
this.ctx.packages.addDependencies(packages)
29+
this.ctx.config.saveConfig(this.ctx.config.getConfig())
30+
}
31+
32+
def showUsages() {
33+
packages = this.nonEmptyArgs()
34+
this.ctx.logger.debug("Own.showUsages", packages)
35+
this.ctx.packages.showUsages(packages)
36+
}
37+
38+
def runScript(script) {
39+
this.ctx.logger.debug("Own.runScript", script)
40+
config = this.ctx.config.getConfig()
41+
vars = {
42+
"$ownlang$": "ownlang" + (this.ctx.OSNAME.startsWith("win") ? ".cmd" : ""),
43+
"$program$": config.program ?? "",
44+
"$dir$": getprop("user.dir").replace("\\", "/")
45+
}
46+
if (script == "") script = "default"
47+
if arrayKeyExists(script, config.scripts ?? {}) {
48+
commands = []
49+
for c : config.scripts[script] {
50+
commands += arrayKeyExists(c, vars) ? vars[c] : c
51+
}
52+
this.ctx.logger.debug("Own.runScript run:", commands)
53+
pb = new PB(commands)
54+
pb.inheritIO()
55+
p = pb.start()
56+
} else {
57+
this.ctx.logger.error("No script '%s' found in config's scripts section".sprintf(script))
58+
}
59+
}
60+
61+
def usage() {
62+
this.ctx.logger.info("own package manager v1.0.0")
63+
this.ctx.logger.info("")
64+
this.ctx.logger.info("
65+
|Usage: own [options]
66+
| options:
67+
| init initialize new project
68+
| add [package] add new package dependency to own-package.json
69+
| usage [package] display the package usage (from .usage.own) if exists
70+
| install install packages defined in own-package.json
71+
| run run program defined in the config program section
72+
| run [script] run script defined in the config scripts section
73+
".stripMargin())
74+
}
75+
76+
def nonEmptyArgs(skip = 1) = stream(ARGS)
77+
.skip(skip)
78+
.filter(def(s) = !s.isEmpty())
79+
.toArray()
80+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
use std, files, json, functional, http, downloader
2+
3+
class Packages {
4+
def Packages(ctx) {
5+
this.ctx = ctx
6+
this.packagesDir = "own-modules"
7+
this.usageFile = ".usage.own"
8+
}
9+
10+
def addDependencies(packages) {
11+
this.ctx.logger.debug("Packages.addDependencies", packages)
12+
if packages.isEmpty() {
13+
this.ctx.logger.error("No package names provided. Try: own add telegram-bot")
14+
return false
15+
}
16+
res = true
17+
config = this.ctx.config.getConfig()
18+
for package : packages {
19+
res = res && this.addDependency(package, config)
20+
}
21+
return res
22+
}
23+
24+
def addDependency(packageName, config) {
25+
this.ctx.logger.debug("Packages.addDependency", packageName)
26+
if packageName == "" {
27+
this.ctx.logger.error("No package name provided. Try: own add telegram-bot")
28+
return false
29+
}
30+
// Check in global registry
31+
registryPackages = this.ctx.registry.getPackages()
32+
if !arrayKeyExists(packageName, registryPackages) {
33+
this.ctx.logger.error("Unknown package " + packageName + ". Check if the name specified correctly")
34+
return false
35+
}
36+
dep = registryPackages[packageName]
37+
// Check if exists in config
38+
if arrayKeyExists(packageName, config.dependencies ?? {}) {
39+
// Exists, check version match
40+
if dep.version == config.dependencies[packageName] {
41+
this.ctx.logger.info("Package " + packageName + " is up to date")
42+
return true
43+
}
44+
}
45+
// Install this dependency
46+
dep.name = packageName
47+
config.dependencies[packageName] = dep.version
48+
downloaded = this.ctx.packages.downloadPackage(dep)
49+
logText = "Installing " + packageName + " " + dep.version
50+
if downloaded {
51+
this.ctx.logger.success(logText + " [success]")
52+
} else {
53+
this.ctx.logger.error(logText + " [failure]")
54+
}
55+
return downloaded
56+
}
57+
58+
def downloadDependencies(dependencies) {
59+
this.ctx.logger.debug("Packages.downloadDependencies")
60+
if length(dependencies) == 0 {
61+
this.ctx.logger.error("No dependency packages provided, or own-package.json is missing")
62+
return false
63+
}
64+
registryPackages = this.ctx.registry.getPackages()
65+
for name, version : dependencies {
66+
logText = "Installing " + name + " " + version
67+
dep = registryPackages[name] ?? {"downloaded": 0}
68+
if !(dep.downloaded ?? 0) {
69+
dep.name = name
70+
dep.downloaded = this.ctx.packages.downloadPackage(dep)
71+
}
72+
if dep.downloaded {
73+
this.ctx.logger.success(logText + " [success]")
74+
} else {
75+
this.ctx.logger.error(logText + " [failure]")
76+
}
77+
}
78+
return true
79+
}
80+
81+
def getPackageFiles(dep) = match (dep.type ?? 0) {
82+
case "gist": {
83+
this.ctx.logger.debug("Packages.getPackageFiles for gist")
84+
extract(ok, content) = httpSync("https://api.github.com/gists/" + dep.id)
85+
return match ok {
86+
case false: []
87+
case true: stream(jsondecode(content).files)
88+
.map(def(r) = [r[0], r[1].raw_url])
89+
.toArray()
90+
}
91+
}
92+
case _: []
93+
}
94+
95+
def getPackagePath(package) {
96+
this.ctx.logger.debug("Packages.getPackagePath", package)
97+
dir = this.packagesDir + "/" + package
98+
stream([this.packagesDir, dir])
99+
.filterNot(::exists)
100+
.forEach(::mkdir)
101+
return dir
102+
}
103+
104+
def downloadPackage(dep) {
105+
this.ctx.logger.debug("Packages.downloadPackage", dep.name)
106+
files = this.getPackageFiles(dep)
107+
dir = this.getPackagePath(dep.name)
108+
result = 0
109+
for mf : files {
110+
extract(name, url) = mf
111+
result += downloader(url, dir + "/" + name)
112+
}
113+
return result > 0
114+
}
115+
116+
def showUsages(packages) {
117+
this.ctx.logger.debug("Packages.showUsages", packages)
118+
if packages.isEmpty() {
119+
this.ctx.logger.error("No package names provided")
120+
return false
121+
}
122+
config = this.ctx.config.getConfig()
123+
for package : packages {
124+
this.showUsage(package, config)
125+
}
126+
return true
127+
}
128+
129+
def showUsage(package, config) {
130+
file = this.packagesDir + "/" + package + "/" + this.usageFile
131+
exists = arrayKeyExists(package, config.dependencies ?? {})
132+
&& exists(file)
133+
if !exists {
134+
this.ctx.logger.error("[" + package + "] "
135+
+ "Error: no .usage.own file provided in the package,"
136+
+ " or the package is not installed")
137+
return false
138+
}
139+
this.ctx.logger.success("\n[" + package + "]")
140+
f = fopen(file, "r")
141+
this.ctx.logger.info(readText(f))
142+
fclose(f)
143+
return true
144+
}
145+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use files
2+
3+
class Projects {
4+
def Projects(ctx) {
5+
this.ctx = ctx
6+
this.defaultPrograms = {
7+
"main.own" : "use std\n\necho(\"Hello, world!\", ARGS)"
8+
}
9+
}
10+
11+
def savePrograms() {
12+
this.ctx.logger.debug("Projects.savePrograms")
13+
for name, content : this.defaultPrograms {
14+
if exists(name) continue
15+
f = fopen(name, "w")
16+
writeText(f, content)
17+
flush(f)
18+
fclose(f)
19+
}
20+
}
21+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use files, json, http
2+
3+
class Registry {
4+
GLOBAL_URL = "https://raw.githubusercontent.com/aNNiMON/Own-Programming-Language-Tutorial/registry/registry.json"
5+
6+
def Registry(ctx) {
7+
this.ctx = ctx
8+
this.registry = {}
9+
this.registryPackages = {}
10+
this.registryCacheFile = ctx.TMPDIR + "/ownlang-registry.json"
11+
}
12+
13+
def isRegistryLoaded() = length(this.registry) > 0
14+
15+
def getPackages() {
16+
this.ctx.logger.debug("Registry.getPackages")
17+
if !this.isRegistryLoaded() {
18+
this.loadRegistry()
19+
}
20+
return this.registryPackages
21+
}
22+
23+
def loadRegistry() {
24+
this.ctx.logger.debug("Registry.loadRegistry")
25+
if (!this.loadFromCache()) {
26+
this.loadFromHttp()
27+
}
28+
}
29+
30+
def loadFromCache() {
31+
this.ctx.logger.debug("Registry.loadFromCache")
32+
if exists(this.registryCacheFile) {
33+
f = fopen(this.registryCacheFile, "r")
34+
this.registry = jsondecode(readText(f))
35+
this.registryPackages = this.registry.packages ?? {}
36+
fclose(f)
37+
return true
38+
}
39+
return false
40+
}
41+
42+
def loadFromHttp() {
43+
this.ctx.logger.debug("Registry.loadFromHttp")
44+
extract(ok, content) = httpSync(this.GLOBAL_URL)
45+
this.registry = ok ? jsondecode(content) : {}
46+
this.registryPackages = this.registry.packages ?? {}
47+
if (ok) this.updateCache()
48+
return ok
49+
}
50+
51+
def updateCache() {
52+
this.ctx.logger.debug("Registry.updateCache")
53+
f = fopen(this.registryCacheFile, "w")
54+
writeText(f, jsonencode(this.registry, 0))
55+
flush(f)
56+
fclose(f)
57+
}
58+
}

0 commit comments

Comments
 (0)
Please sign in to comment.