all repos — min @ e935a28de37d136b6a44ee1841a09e606096ea85

A small but practical concatenative programming language.

Merge branch 'next' of github.com:h3rald/min into next
h3rald h3rald@h3rald.com
Wed, 16 Dec 2020 20:45:52 +0100
commit

e935a28de37d136b6a44ee1841a09e606096ea85

parent

1dd3d8eb69536b437fba1a78f3a515a96838233c

D core/consts.nim

@@ -1,20 +0,0 @@

-import - strutils - -const ymlconfig = "../min.yml".slurp - -var pkgName* {.threadvar.}: string -var pkgVersion* {.threadvar.}: string -var pkgAuthor* {.threadvar.}: string -var pkgDescription* {.threadvar.}: string - -for line in ymlconfig.split("\n"): - let pair = line.split(":") - if pair[0].strip == "name": - pkgName = pair[1].strip - if pair[0].strip == "version": - pkgVersion = pair[1].strip - if pair[0].strip == "author": - pkgAuthor = pair[1].strip - if pair[0].strip == "description": - pkgDescription = pair[1].strip
M core/env.nimcore/env.nim

@@ -1,5 +1,8 @@

when not defined(mini): - import os + import + os, + ../packages/nimline/nimline + var HOME*: string if defined(windows): HOME = getenv("USERPROFILE")

@@ -14,6 +17,9 @@ var MINHISTORY* {.threadvar.}: string

MINHISTORY = HOME / ".min_history" var MINLIBS* {.threadvar.} : string MINLIBS = HOME / ".minlibs" + + var EDITOR* {.threadvar.}: LineEditor + EDITOR = initEditor(historyFile = MINHISTORY) var MINCOMPILED* {.threadvar.}: bool MINCOMPILED = false
M core/interpreter.nimcore/interpreter.nim

@@ -69,7 +69,7 @@ i.scope = origScope

proc newMinInterpreter*(filename = "input", pwd = ""): MinInterpreter {.extern:"min_exported_symbol_$1".}= var path = pwd - when not defined(mini): #TODO investigate impact + when not defined(mini): if not pwd.isAbsolute: path = joinPath(getCurrentDir(), pwd) var stack:MinStack = newSeq[MinValue](0)
A core/meta.nim

@@ -0,0 +1,20 @@

+import + strutils + +const ymlconfig = "../min.yml".slurp + +var pkgName* {.threadvar.}: string +var pkgVersion* {.threadvar.}: string +var pkgAuthor* {.threadvar.}: string +var pkgDescription* {.threadvar.}: string + +for line in ymlconfig.split("\n"): + let pair = line.split(":") + if pair[0].strip == "name": + pkgName = pair[1].strip + if pair[0].strip == "version": + pkgVersion = pair[1].strip + if pair[0].strip == "author": + pkgAuthor = pair[1].strip + if pair[0].strip == "description": + pkgDescription = pair[1].strip
M lib/min_crypto.nimlib/min_crypto.nim

@@ -1,79 +1,48 @@

import - base64, - strutils, - openssl, - times + base64 import ../core/parser, ../core/value, ../core/interpreter, ../core/utils -import - ../vendor/aes/aes -{.compile: "../vendor/aes/libaes.c".} -when defined(windows): - {.passL: "-static -Lvendor/openssl/windows -lssl -lcrypto -lws2_32".} -elif defined(linux): - {.passL: "-static -Lvendor/openssl/linux -lssl -lcrypto".} -elif defined(macosx): - {.passL: "-Bstatic -Lvendor/openssl/macosx -lssl -lcrypto -Bdynamic".} +when defined(ssl): + import + strutils, + openssl, + times, + ../vendor/aes/aes + + {.compile: "../vendor/aes/libaes.c".} + + when defined(windows): + {.passL: "-static -Lvendor/openssl/windows -lssl -lcrypto -lws2_32".} + elif defined(linux): + {.passL: "-static -Lvendor/openssl/linux -lssl -lcrypto".} + elif defined(macosx): + {.passL: "-Bstatic -Lvendor/openssl/macosx -lssl -lcrypto -Bdynamic".} -proc EVP_MD_CTX_new*(): EVP_MD_CTX {.cdecl, importc: "EVP_MD_CTX_new".} -proc EVP_MD_CTX_free*(ctx: EVP_MD_CTX) {.cdecl, importc: "EVP_MD_CTX_free".} + proc EVP_MD_CTX_new*(): EVP_MD_CTX {.cdecl, importc: "EVP_MD_CTX_new".} + proc EVP_MD_CTX_free*(ctx: EVP_MD_CTX) {.cdecl, importc: "EVP_MD_CTX_free".} -proc hash(s: string, kind: EVP_MD, size: int): string = - var hash_length: cuint = 0 - var hash = alloc[ptr cuchar](size) - let ctx = EVP_MD_CTX_new() - discard EVP_DigestInit_ex(ctx, kind, nil) - discard EVP_DigestUpdate(ctx, unsafeAddr s[0], s.len.cuint) - discard EVP_DigestFinal_ex(ctx, hash, cast[ptr cuint](hash_length)) - EVP_MD_CTX_free(ctx) - var hashStr = newString(size) - copyMem(addr(hashStr[0]), hash, size) - dealloc(hash) - return hashStr.toHex.toLowerAscii[0..size-1] + proc hash(s: string, kind: EVP_MD, size: int): string = + var hash_length: cuint = 0 + var hash = alloc[ptr cuchar](size) + let ctx = EVP_MD_CTX_new() + discard EVP_DigestInit_ex(ctx, kind, nil) + discard EVP_DigestUpdate(ctx, unsafeAddr s[0], s.len.cuint) + discard EVP_DigestFinal_ex(ctx, hash, cast[ptr cuint](hash_length)) + EVP_MD_CTX_free(ctx) + var hashStr = newString(size) + copyMem(addr(hashStr[0]), hash, size) + dealloc(hash) + return hashStr.toHex.toLowerAscii[0..size-1] proc crypto_module*(i: In)= let def = i.define() - def.symbol("md5") do (i: In): - let vals = i.expect("'sym") - let s = vals[0].getString - i.push hash(s, EVP_md5(), 32).newVal - - def.symbol("md4") do (i: In): - let vals = i.expect("'sym") - let s = vals[0].getString - i.push hash(s, EVP_md4(), 32).newVal - - def.symbol("sha1") do (i: In): - let vals = i.expect("'sym") - var s = vals[0].getString - i.push hash(s, EVP_sha1(), 40).newVal - - def.symbol("sha224") do (i: In): - let vals = i.expect("'sym") - let s = vals[0].getString - i.push hash(s, EVP_sha224(), 56).newVal - - def.symbol("sha256") do (i: In): - let vals = i.expect("'sym") - let s = vals[0].getString - i.push hash(s, EVP_sha256(), 64).newVal - - def.symbol("sha384") do (i: In): - let vals = i.expect("'sym") - let s = vals[0].getString - i.push hash(s, EVP_sha384(), 96).newVal - - def.symbol("sha512") do (i: In): - let vals = i.expect("'sym") - let s = vals[0].getString - i.push hash(s, EVP_sha512(), 128).newVal - + def.symbol("encode") do (i: In): let vals = i.expect("'sym") let s = vals[0]

@@ -83,18 +52,55 @@ def.symbol("decode") do (i: In):

let vals = i.expect("'sym") let s = vals[0] i.push s.getString.decode.newVal - - def.symbol("aes") do (i: In): - let vals = i.expect("'sym", "'sym") - let k = vals[0] - let s = vals[1] - var text = s.getString - var key = hash(k.getString, EVP_sha1(), 40) - var iv = hash((key & $getTime().toUnix), EVP_sha1(), 40) - var ctx = cast[ptr AES_ctx](alloc0(sizeof(AES_ctx))) - AES_init_ctx_iv(ctx, cast[ptr uint8](key[0].addr), cast[ptr uint8](iv[0].addr)); - var input = cast[ptr uint8](text[0].addr) - AES_CTR_xcrypt_buffer(ctx, input, text.len.uint32); - i.push text.newVal + + when defined(ssl): + + def.symbol("md5") do (i: In): + let vals = i.expect("'sym") + let s = vals[0].getString + i.push hash(s, EVP_md5(), 32).newVal + + def.symbol("md4") do (i: In): + let vals = i.expect("'sym") + let s = vals[0].getString + i.push hash(s, EVP_md4(), 32).newVal + + def.symbol("sha1") do (i: In): + let vals = i.expect("'sym") + var s = vals[0].getString + i.push hash(s, EVP_sha1(), 40).newVal + + def.symbol("sha224") do (i: In): + let vals = i.expect("'sym") + let s = vals[0].getString + i.push hash(s, EVP_sha224(), 56).newVal + + def.symbol("sha256") do (i: In): + let vals = i.expect("'sym") + let s = vals[0].getString + i.push hash(s, EVP_sha256(), 64).newVal + + def.symbol("sha384") do (i: In): + let vals = i.expect("'sym") + let s = vals[0].getString + i.push hash(s, EVP_sha384(), 96).newVal + + def.symbol("sha512") do (i: In): + let vals = i.expect("'sym") + let s = vals[0].getString + i.push hash(s, EVP_sha512(), 128).newVal + + def.symbol("aes") do (i: In): + let vals = i.expect("'sym", "'sym") + let k = vals[0] + let s = vals[1] + var text = s.getString + var key = hash(k.getString, EVP_sha1(), 40) + var iv = hash((key & $getTime().toUnix), EVP_sha1(), 40) + var ctx = cast[ptr AES_ctx](alloc0(sizeof(AES_ctx))) + AES_init_ctx_iv(ctx, cast[ptr uint8](key[0].addr), cast[ptr uint8](iv[0].addr)); + var input = cast[ptr uint8](text[0].addr) + AES_CTR_xcrypt_buffer(ctx, input, text.len.uint32); + i.push text.newVal def.finalize("crypto")
M lib/min_dict.nimlib/min_dict.nim

@@ -6,7 +6,6 @@ ../core/value,

../core/interpreter, ../core/utils -# Operations on dictionaries proc dict_module*(i: In)= let def = i.define()
M lib/min_http.nimlib/min_http.nim

@@ -1,12 +1,12 @@

import httpclient, asynchttpserver, asyncdispatch, strutils, uri, critbits import ../core/parser, - ../core/consts, + ../core/meta, ../core/value, ../core/interpreter, ../core/utils -when defined(amd64): +when defined(ssl) and defined(amd64): when defined(windows): {.passL: "-static -Lvendor/openssl/windows -lssl -lcrypto -lws2_32".} elif defined(linux):

@@ -26,8 +26,6 @@ for k, v in headers:

result = i.dset(result, k, v.newVal) type MinServerExit = ref object of CatchableError - -# Http proc http_module*(i: In)= let def = i.define()

@@ -138,6 +136,5 @@ server.close()

def.symbol("stop-server") do (i: In): raise MinServerExit() - def.finalize("http")
M lib/min_io.nimlib/min_io.nim

@@ -1,6 +1,8 @@

import strutils, - logging + logging, + critbits, + terminal import ../packages/nimline/nimline, ../packages/nim-sgregex/sgregex,

@@ -9,11 +11,37 @@ ../core/value,

../core/interpreter, ../core/utils -# I/O - +var ORIGKEYMAP {.threadvar.}: CritBitTree[KeyCallback] +for key, value in KEYMAP.pairs: + ORIGKEYMAP[key] = value proc io_module*(i: In) = let def = i.define() + + def.symbol("clear") do (i: In): + stdout.eraseScreen + stdout.setCursorPos(0, 0) + + def.symbol("unmapkey") do (i: In): + let vals = i.expect("'sym") + let key = vals[0].getString.toLowerAscii + if not KEYNAMES.contains(key) and not KEYSEQS.contains(key): + raiseInvalid("Unrecognized key: " & key) + if KEYMAP.hasKey(key): + if ORIGKEYMAP.hasKey(key): + KEYMAP[key] = ORIGKEYMAP[key] + else: + KEYMAP.excl(key) + + def.symbol("mapkey") do (i: In): + let vals = i.expect("'sym", "quot") + let key = vals[0].getString.toLowerAscii + var q = vals[1] + if not KEYNAMES.contains(key) and not KEYSEQS.contains(key): + raiseInvalid("Unrecognized key: " & key) + var ic = i.copy(i.filename) + KEYMAP[key] = proc (ed: var LineEditor) {.gcsafe.} = + ic.apply(q) def.symbol("newline") do (i: In): echo ""
M lib/min_lang.nimlib/min_lang.nim

@@ -18,7 +18,7 @@ ../packages/nimline/nimline,

../packages/nim-sgregex/sgregex import ../core/env, - ../core/consts, + ../core/meta, ../core/parser, ../core/value, ../core/interpreter,

@@ -27,6 +27,121 @@ ../core/scope

proc lang_module*(i: In) = let def = i.scope + + when not defined(mini): + + def.symbol("from-json") do (i: In): + let vals = i.expect("string") + let s = vals[0] + i.push i.fromJson(s.getString.parseJson) + + def.symbol("to-json") do (i: In): + let vals = i.expect "a" + let q = vals[0] + i.push(($((i%q).pretty)).newVal) + + # Save/load symbols + + def.symbol("save-symbol") do (i: In) {.gcsafe.}: + let vals = i.expect("'sym") + let s = vals[0] + let sym = s.getString + let op = i.scope.getSymbol(sym) + if op.kind == minProcOp: + raiseInvalid("Symbol '$1' cannot be serialized." % sym) + let json = MINSYMBOLS.readFile.parseJson + json[sym] = i%op.val + MINSYMBOLS.writeFile(json.pretty) + + def.symbol("load-symbol") do (i: In): + let vals = i.expect("'sym") + let s = vals[0] + let sym = s.getString + let json = MINSYMBOLS.readFile.parseJson + if not json.hasKey(sym): + raiseUndefined("Symbol '$1' not found." % sym) + let val = i.fromJson(json[sym]) + i.scope.symbols[sym] = MinOperator(kind: minValOp, val: val, quotation: true) + + def.symbol("saved-symbols") do (i: In): + var q = newSeq[MinValue](0) + let json = MINSYMBOLS.readFile.parseJson + for k,v in json.pairs: + q.add k.newVal + i.push q.newVal + + def.symbol("remove-symbol") do (i: In): + let vals = i.expect("'sym") + let s = vals[0] + let sym = s.getString + var json = MINSYMBOLS.readFile.parseJson + if not json.hasKey(sym): + raiseUndefined("Symbol '$1' not found." % sym) + json.delete(sym) + MINSYMBOLS.writeFile(json.pretty) + + def.symbol("load") do (i: In): + let vals = i.expect("'sym") + let s = vals[0] + var file = s.getString + if not file.endsWith(".min"): + file = file & ".min" + info("[load] File: ", file) + if MINCOMPILED: + var compiledFile = strutils.replace(strutils.replace(file, "\\", "/"), "./", "") + if MINCOMPILEDFILES.hasKey(compiledFile): + MINCOMPILEDFILES[compiledFile](i) + return + file = i.pwd.joinPath(file) + if not file.fileExists: + raiseInvalid("File '$1' does not exist." % file) + i.load file + + def.symbol("read") do (i: In): + let vals = i.expect("'sym") + let s = vals[0] + var file = s.getString + if not file.endsWith(".min"): + file = file & ".min" + info("[read] File: ", file) + if not file.fileExists: + raiseInvalid("File '$1' does not exist." % file) + i.push i.read file + + def.symbol("raw-args") do (i: In): + var args = newSeq[MinValue](0) + for par in commandLineParams(): + args.add par.newVal + i.push args.newVal + + def.symbol("with") do (i: In): + let vals = i.expect("dict", "quot") + var qscope = vals[0] + var qprog = vals[1] + i.withDictScope(qscope.scope): + for v in qprog.qVal: + i.push v + + def.symbol("publish") do (i: In): + let vals = i.expect("dict", "'sym") + let qscope = vals[0] + let str = vals[1] + let sym = str.getString + if qscope.scope.symbols.hasKey(sym) and qscope.scope.symbols[sym].sealed: + raiseUndefined("Attempting to redefine sealed symbol '$1'" % [sym]) + let scope = i.scope + info("[publish] Symbol: $2" % [sym]) + let op = proc(i: In) {.closure.} = + let origscope = i.scope + i.scope = scope + i.evaluating = true + i.push sym.newSym + i.evaluating = false + i.scope = origscope + qscope.scope.symbols[sym] = MinOperator(kind: minProcOp, prc: op) + + ### End of symbols not present in minimin + def.symbol("exit") do (i: In): let vals = i.expect("int") quit(vals[0].intVal.int)

@@ -269,118 +384,6 @@ def.symbol("parse") do (i: In):

let vals = i.expect("string") let s = vals[0] i.push i.parse s.strVal - - when not defined(mini): - - def.symbol("from-json") do (i: In): - let vals = i.expect("string") - let s = vals[0] - i.push i.fromJson(s.getString.parseJson) - - def.symbol("to-json") do (i: In): - let vals = i.expect "a" - let q = vals[0] - i.push(($((i%q).pretty)).newVal) - - # Save/load symbols - - def.symbol("save-symbol") do (i: In) {.gcsafe.}: - let vals = i.expect("'sym") - let s = vals[0] - let sym = s.getString - let op = i.scope.getSymbol(sym) - if op.kind == minProcOp: - raiseInvalid("Symbol '$1' cannot be serialized." % sym) - let json = MINSYMBOLS.readFile.parseJson - json[sym] = i%op.val - MINSYMBOLS.writeFile(json.pretty) - - def.symbol("load-symbol") do (i: In): - let vals = i.expect("'sym") - let s = vals[0] - let sym = s.getString - let json = MINSYMBOLS.readFile.parseJson - if not json.hasKey(sym): - raiseUndefined("Symbol '$1' not found." % sym) - let val = i.fromJson(json[sym]) - i.scope.symbols[sym] = MinOperator(kind: minValOp, val: val, quotation: true) - - def.symbol("saved-symbols") do (i: In): - var q = newSeq[MinValue](0) - let json = MINSYMBOLS.readFile.parseJson - for k,v in json.pairs: - q.add k.newVal - i.push q.newVal - - def.symbol("remove-symbol") do (i: In): - let vals = i.expect("'sym") - let s = vals[0] - let sym = s.getString - var json = MINSYMBOLS.readFile.parseJson - if not json.hasKey(sym): - raiseUndefined("Symbol '$1' not found." % sym) - json.delete(sym) - MINSYMBOLS.writeFile(json.pretty) - - def.symbol("load") do (i: In): - let vals = i.expect("'sym") - let s = vals[0] - var file = s.getString - if not file.endsWith(".min"): - file = file & ".min" - info("[load] File: ", file) - if MINCOMPILED: - var compiledFile = strutils.replace(strutils.replace(file, "\\", "/"), "./", "") - if MINCOMPILEDFILES.hasKey(compiledFile): - MINCOMPILEDFILES[compiledFile](i) - return - file = i.pwd.joinPath(file) - if not file.fileExists: - raiseInvalid("File '$1' does not exist." % file) - i.load file - - def.symbol("read") do (i: In): - let vals = i.expect("'sym") - let s = vals[0] - var file = s.getString - if not file.endsWith(".min"): - file = file & ".min" - info("[read] File: ", file) - if not file.fileExists: - raiseInvalid("File '$1' does not exist." % file) - i.push i.read file - - def.symbol("raw-args") do (i: In): - var args = newSeq[MinValue](0) - for par in commandLineParams(): - args.add par.newVal - i.push args.newVal - - def.symbol("with") do (i: In): - let vals = i.expect("dict", "quot") - var qscope = vals[0] - var qprog = vals[1] - i.withDictScope(qscope.scope): - for v in qprog.qVal: - i.push v - - def.symbol("publish") do (i: In): - let vals = i.expect("dict", "'sym") - let qscope = vals[0] - let str = vals[1] - let sym = str.getString - if qscope.scope.symbols.hasKey(sym) and qscope.scope.symbols[sym].sealed: - raiseUndefined("Attempting to redefine sealed symbol '$1'" % [sym]) - let scope = i.scope - info("[publish] Symbol: $2" % [sym]) - let op = proc(i: In) {.closure.} = - let origscope = i.scope - i.scope = scope - i.evaluating = true - i.push sym.newSym - i.evaluating = false - i.scope = origscope - qscope.scope.symbols[sym] = MinOperator(kind: minProcOp, prc: op) def.symbol("source") do (i: In): let vals = i.expect("'sym")
M lib/min_logic.nimlib/min_logic.nim

@@ -6,8 +6,6 @@ ../core/value,

../core/interpreter, ../core/utils -# Comparison operators - proc floatCompare(n1, n2: MinValue): bool = let a:float = if n1.kind != minFloat: n1.intVal.float else: n1.floatVal

@@ -112,8 +110,6 @@ n2 = vals[1]

if (n1.kind == minFloat or n2.kind == minFloat) and n1.isNumber and n2.isNumber: i.push newVal(not floatCompare(n1, n2)) i.push newVal(not (n1 == n2)) - - # Boolean Logic def.symbol("not") do (i: In): let vals = i.expect("bool")
M lib/min_math.nimlib/min_math.nim

@@ -8,8 +8,6 @@ ../core/value,

../core/interpreter, ../core/utils - # Math - proc math_module*(i: In)= let def = i.define()
M lib/min_net.nimlib/min_net.nim

@@ -5,11 +5,8 @@ ../core/value,

../core/interpreter, ../core/utils -# Net - proc toSocket(q: MinValue): Socket = return cast[Socket](q.obj) - proc net_module*(i: In)= let def = i.define()
M lib/min_num.nimlib/min_num.nim

@@ -6,8 +6,6 @@ ../core/value,

../core/interpreter, ../core/utils - # Arithmetic - proc num_module*(i: In)= let def = i.define()
M lib/min_seq.nimlib/min_seq.nim

@@ -7,7 +7,6 @@ ../core/value,

../core/interpreter, ../core/utils -# Operations on sequences (data quotations) proc seq_module*(i: In)= let def = i.define()
M lib/min_stack.nimlib/min_stack.nim

@@ -4,7 +4,6 @@ ../core/value,

../core/interpreter, ../core/utils -# Operations on the whole stack proc stack_module*(i: In)= let def = i.define()
M lib/min_str.nimlib/min_str.nim

@@ -12,7 +12,6 @@ when not defined(mini):

import ../packages/nim-sgregex/sgregex - proc str_module*(i: In) = let def = i.define()
M lib/min_time.nimlib/min_time.nim

@@ -6,9 +6,6 @@ ../core/value,

../core/interpreter, ../core/utils -# Time - - proc time_module*(i: In)= let def = i.define()
M min.nimmin.nim

@@ -36,8 +36,8 @@

when not defined(mini): import packages/nimline/nimline, - lib/min_io, lib/min_sys, + lib/min_io, lib/min_fs when not defined(lite) and not defined(mini):

@@ -53,8 +53,9 @@ parser,

interpreter, utils, value, - scope#, - #min_lang + scope, + min_lang + when defined(mini): export minilogger else:

@@ -89,9 +90,9 @@ if words.len == 0:

word = ed.lineText else: word = words[words.len-1] - if word.startsWith("’"): - return symbols.mapIt("’" & $it) - elif word.startsWith("~"): + if word.startsWith("'"): + return symbols.mapIt("'" & $it) + if word.startsWith("~"): return symbols.mapIt("~" & $it) if word.startsWith("@"): return symbols.mapIt("@" & $it)

@@ -109,6 +110,14 @@ if word.startsWith("$"):

return toSeq(envPairs()).mapIt("$" & $it[0]) if word.startsWith("!"): return getExecs().mapIt("!" & $it) + if word.startsWith("!!"): + return getExecs().mapIt("!!" & $it) + if word.startsWith("!\""): + return getExecs().mapIt("!\"" & $it) + if word.startsWith("!!\""): + return getExecs().mapIt("!!\"" & $it) + if word.startsWith("&\""): + return getExecs().mapIt("&\"" & $it) if word.startsWith("&"): return getExecs().mapIt("&" & $it) if word.startsWith("\""):

@@ -305,7 +314,7 @@ when isMainModule:

import parseopt, - core/consts + core/meta var REPL = false var SIMPLEREPL = false

@@ -373,23 +382,23 @@ if $line != "":

i.printResult(r) when not defined(mini): + proc minRepl*(i: var MinInterpreter) = i.stdLib() i.dynLib() var s = newStringStream("") i.open(s, "<repl>") var line: string - var ed = initEditor(historyFile = MINHISTORY) while true: let symbols = toSeq(i.scope.symbols.keys) - ed.completionCallback = proc(ed: LineEditor): seq[string] = + EDITOR.completionCallback = proc(ed: LineEditor): seq[string] = return ed.getCompletions(symbols) # evaluate prompt i.push("prompt".newSym) let vals = i.expect("string") let v = vals[0] let prompt = v.getString() - line = ed.readLine(prompt) + line = EDITOR.readLine(prompt) let r = i.interpret($line) if $line != "": i.printResult(r)
M min.nimblemin.nimble

@@ -1,5 +1,5 @@

import - core/consts + core/meta # Package

@@ -8,7 +8,7 @@ author = pkgAuthor

description = pkgDescription license = "MIT" bin = @[pkgName] -installFiles = @["core/consts.nim"] +installFiles = @["core/meta.nim"] # Dependencies
M min.nimsmin.nims

@@ -12,7 +12,7 @@ switch("amd64.linux.gcc.linkerexe", "x86_64-linux-musl-gcc")

switch("opt", "size") -when not defined(mini): +when defined(ssl) and not defined(mini): switch("define", "ssl") switch("threads", "on") when defined(windows):
M next-release.mdnext-release.md

@@ -4,3 +4,6 @@ * Added **define-sigil**, **delete-sigil**, **seal-sigil**, **unseal-sigil**, **defined-sigil?**.

* Fixed behavior of **semver-inc-mahor** and **semver-inc-minor** to set lower digits to zero. * Now using OpenSSL for all hashing symbols in the crypto module. * Added **md4** symbol. +* Re-added the possibility to exclude OpenSSL by not defining the **ssl** flag. +* Added **clear** symbol to clear the screen. +* Added the **mapkey** and the **unmapkey** symbols to configure key mappings.
M site/assets/images/logo.svgsite/assets/images/logo.svg

@@ -1,13 +1,9 @@

<svg width="588" height="588" xmlns="http://www.w3.org/2000/svg"> <!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ --> <g> - <title>background</title> - <rect fill="#fff" id="canvas_background" height="590" width="590" y="-1" x="-1"/> - </g> - <g> <title>Layer 1</title> <g id="widget" transform="rotate(-0.0926624983549118 294.3764648437568,302.3101196289116) matrix(7.224760791089692,0,0,7.224760791089692,1091.8911354197558,1091.8773791888611) "> - <path d="m-66.986304,-65.886277l-86.8,0l0,-86.8l86.8,0l0,86.8z" fill="#2B4737" id="svg_1"/> + <path d="m-110.235944,-85.470377l-36.91286,6.2079l36.91286,6.1644l36.61214,-6.1644l-36.61214,-6.2079z" fill="#36a631" id="svg_2"/> <path d="m-110.235944,-91.847177l-36.91286,6.2079l36.91286,6.1644l36.61214,-6.1644l-36.61214,-6.2079z" fill="#6bbc57" id="svg_3"/> <path d="m-110.235944,-97.842677l-36.91286,6.2079l36.91286,6.1644l36.61214,-6.1644l-36.61214,-6.2079z" fill="#8dd97f" id="svg_4"/>
M site/contents/get-started.mdsite/contents/get-started.md

@@ -38,6 +38,17 @@ 7. Run **nim c -d:release min.nim**.

### Additional build options +#### -d:ssl + +If the **-d:ssl** flag is specified when compiling, min will be built with SSL support, so it will be possible to: +* perform HTTPS requests with the {#link-module||http#}. +* use the cryptographic symbols defined in the {#link-module||crypto#}. + +> %note% +> Note +> +> By default, this flag is enabled when compiling the executable files included with official releases. + #### -d:lite If the **d:lite** flag is specified, a more minimal executable file will be generated (typically, it should be called "litemin"), however the following functionalities will not be available:
M site/contents/learn-shell.mdsite/contents/learn-shell.md

@@ -28,21 +28,26 @@

Context | Result ---------------------------------------------------------------|-------------- ...a string | Auto-completes the current word using file and directory names. -...a word starting with `!` or `&` | Auto-completes the current word using executable file names. +...a word starting with `!`, `!!`, `!"` `!!"`, `&`, `&"` | Auto-completes the current word using executable file names. ...a word starting with `$` | Auto-completes the current word using environment variable names. ...a word starting with `'`, `~`, `@`, `#`, `>`, `<`, `*`, `(` | Auto-completes the current word using symbol names. -Additionally, at least some of the following systems should also be available, depending on your operating system: +Additionally, the following common shortcuts are also available: Key | Effect ---------------|------------------------ `INSERT` | Switches between insert and replace mode. `UP` | Displays the previous history entry. `DOWN` | Displays the next history entry. -`CTRL+c` | Terminates min shell. -`CTRL+x` | Clears the current line. +`CTRL+d` | Terminates the min shell. +`CTRL+u` | Clears the current line. `CTRL+b` | Goes to the beginning of the line. `CTRL+e` | Goes to the end of the line. + +> %tip% +> Tip +> +> If you want, you can define your own keyboard shortcuts using the {#link-operator||io||mapkey#} operator. ## Shell configuration files
M site/contents/reference-io.mdsite/contents/reference-io.md

@@ -11,6 +11,9 @@ {#op||choose||(({{s1}} {{q1}}){{1p}}) {{s2}}||{{a0p}}||

> Prints {{s2}}, then prints all {{s1}} included in the quotation prepended with a number, and waits from valid input from the user. > > If the user enters a number that matches one of the choices, then the corresponding quotation {{q1}} is executed, otherwise the choice menu is displayed again until a valid choice is made. #} + +{#op||clear||{{null}}||{{null}}|| +Clears the screen.#} {#op||column-print||{{q}} {{i}}||{{any}}|| Prints all elements of {{q}} to STDOUT, in {{i}} columns.#}

@@ -46,6 +49,23 @@

{#op||info||{{any}}||{{any}}|| Prints {{any}} and a new line to STDOUT, if logging level is set to [info](class:kwd) or lower.#} +{#op||mapkey||{{q}} {{sl}}||{{null}}|| +> Maps the named key/key combination {{sl}} to the quotation {{q}}, so that {{q}} is executed when key {{sl}} is pressed. +> +> > %note% +> > Note +> > +> > At present, only the key names and sequences defined in the [nimline](https://h3rald.com/nimline/nimline.html) library are supported. +> +> > %sidebar% +> > Example +> > +> > The following program: +> > +> > (clear) 'ctrl+l keymap +> > +> > causes the `CTRL+L` key to clear the screen. #} + {#op||newline||{{null}}||{{null}}|| Prints a new line to STDOUT.#}

@@ -66,6 +86,16 @@ Prints {{s}} to STDOUT without printing a new line ({{s}} must contain only one character).#}

{#op||type||{{any}}||{{s}}|| Puts the data type of {{any}} on the stack. In cased of typed dictionaries, the type name is prefixed by `dict:`, e.g. `dict:module`, `dict:socket`, etc.#} + +{#op||unmapkey||{{sl}}||{{null}}|| +> Unmaps a previously-mapped key or key-combination {{sl}}, restoring the default mapping if available. +> +> > %note% +> > Notes +> > +> > * At present, only the key names and sequences defined in the [nimline](https://h3rald.com/nimline/nimline.html) library are supported. +> > * At present, all the default mappings of min are those provided by the [nimline](https://h3rald.com/nimline/nimline.html) library. +#} {#op||warning||{{any}}||{{any}}|| Prints {{any}} and a new line to STDERR, if logging level is set to [warning](class:kwd) or lower.#}
M site/contents/reference-num.mdsite/contents/reference-num.md

@@ -43,10 +43,10 @@

{#op||random||{{i1}}||{{i2}}|| > Returns a random number {{i2}} between 0 and {{i1}}-1. > -> %note% -> Note -> -> You must call `randomize` to initialize the random number generator, otherwise the same sequence of numbers will be returned.#} +> > %note% +> > Note +> > +> > You must call `randomize` to initialize the random number generator, otherwise the same sequence of numbers will be returned.#} {#op||randomize||{{null}}||{{null}|| Initializes the random number generator using a seed based on the current timestamp. #}
M tasks/build.mintasks/build.min

@@ -14,7 +14,7 @@ "$#min" (variant) =% @o-variant

) when "nim" required "Building $# - $# (x64)" (o-variant target-os) =% notice - "nim c -d:release --cpu:amd64 --os:$# $#-o:$# min" (target-os d-variant o-variant) =% puts ! + "nim c -d:release -d:ssl --cpu:amd64 --os:$# $#-o:$# min" (target-os d-variant o-variant) =% puts ! {} target-os %os config /version %version