mirror of
https://github.com/janet-lang/janet
synced 2026-04-04 05:51:27 +00:00
Compare commits
10 Commits
contributi
...
connect-ex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d388f267a | ||
|
|
37a2677ecb | ||
|
|
143ba6ba0f | ||
|
|
0e8c3e3e0a | ||
|
|
4d13437c31 | ||
|
|
b134f5359d | ||
|
|
ce56342168 | ||
|
|
ab86ef09ef | ||
|
|
b8db108702 | ||
|
|
479d846f7a |
@@ -3,8 +3,6 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
## Unreleased - ???
|
||||
- Documentation fixes
|
||||
- ev/thread-chan deadlock bug fixed
|
||||
- Re-add removed support for non-blocking net/connect on windows.
|
||||
|
||||
## 1.41.2 - 2026-02-18
|
||||
- Fix regressions in `put` for arrays and buffers.
|
||||
|
||||
@@ -37,12 +37,6 @@ may require changes before being merged.
|
||||
do this indentation, or approximate as close as possible. There is a janet formatter
|
||||
in [spork](https://github.com/janet-lang/spork.git) that can be used to format code as well.
|
||||
|
||||
Bot pull requests will not be accepted, and anonymous submissions, including
|
||||
new accounts, unknown emails, and first time contributors will be subjected
|
||||
to greater scrutiny and code reivew. Automatically generated and filed bug
|
||||
reports MAY be ok, if they are of consistent and good quality, such as
|
||||
OSSFuzz or well constructed CI pipelines.
|
||||
|
||||
## C style
|
||||
|
||||
For changes to the VM and Core code, you will probably need to know C. Janet is programmed with
|
||||
@@ -96,18 +90,3 @@ timely manner. In short, if you want extra functionality now, then build it.
|
||||
|
||||
* Include a good description of the problem that is being solved
|
||||
* Include descriptions of potential solutions if you have some in mind.
|
||||
|
||||
## LLMs, Tool Usage, and Transparency
|
||||
|
||||
All usage of Large Language Models (LLMs), Neural Networks, "AI" tools, and
|
||||
other tools such as software fuzzers or static analyzers must be disclosed.
|
||||
This applies to pull requests, email patches, bug reports, and any other
|
||||
meaningful contribution to Janet's source code. Please also refrain from using
|
||||
generative AI for code that will be embedded in the Janet runtime, which include
|
||||
all C source files as well as boot.janet. All code should be well
|
||||
and completely understood by the human author, including test cases. Large and
|
||||
obviously AI-driven changes will be rejected. Be mindful and transparent on the
|
||||
copyright implications of any submitted code. We will use discretion when
|
||||
accepting generated test cases for bug reproductions, one-line bug
|
||||
fixes, or typo fixes. Often, these can be trivially rewritten by a human to
|
||||
avoid the problem.
|
||||
|
||||
@@ -443,36 +443,11 @@
|
||||
(def ,binding ,ctor)
|
||||
,(defer-impl :with [(or dtor :close) binding] body)))
|
||||
|
||||
# declare ahead of time
|
||||
(var- macexvar nil)
|
||||
|
||||
(defmacro if-let
|
||||
``Make multiple bindings, and if all are truthy,
|
||||
evaluate the `tru` form. If any are false or nil, evaluate
|
||||
the `fal` form. Bindings have the same syntax as the `let` macro.``
|
||||
[bindings tru &opt fal]
|
||||
(def len (length bindings))
|
||||
(if (= 0 len) (error "expected at least 1 binding"))
|
||||
(if (odd? len) (error "expected an even number of bindings"))
|
||||
(def fal2 (if macexvar (macexvar fal) fal))
|
||||
(defn aux [i]
|
||||
(if (>= i len)
|
||||
tru
|
||||
(do
|
||||
(def bl (in bindings i))
|
||||
(def br (in bindings (+ 1 i)))
|
||||
(if (symbol? bl)
|
||||
~(if (def ,bl ,br) ,(aux (+ 2 i)) ,fal2)
|
||||
~(if (def ,(def sym (gensym)) ,br)
|
||||
(do (def ,bl ,sym) ,(aux (+ 2 i)))
|
||||
,fal2)))))
|
||||
(aux 0))
|
||||
|
||||
(defmacro when-with
|
||||
``Similar to with, but if binding is false or nil, returns
|
||||
nil without evaluating the body. Otherwise, the same as `with`.``
|
||||
[[binding ctor dtor] & body]
|
||||
~(as-macro ,if-let [,binding ,ctor]
|
||||
~(if-let [,binding ,ctor]
|
||||
,(defer-impl :when-with [(or dtor :close) binding] body)))
|
||||
|
||||
(defmacro if-with
|
||||
@@ -480,7 +455,7 @@
|
||||
the falsey path. Otherwise, evaluates the truthy path. In both cases,
|
||||
`ctor` is bound to binding.``
|
||||
[[binding ctor dtor] truthy &opt falsey]
|
||||
~(as-macro ,if-let [,binding ,ctor]
|
||||
~(if-let [,binding ,ctor]
|
||||
,(defer-impl :if-with [(or dtor :close) binding] [truthy])
|
||||
,falsey))
|
||||
|
||||
@@ -564,13 +539,13 @@
|
||||
(case binding
|
||||
:until ~(do (if ,verb (break) nil) ,rest)
|
||||
:while ~(do (if ,verb nil (break)) ,rest)
|
||||
:let ~(as-macro ,let ,verb (do ,rest))
|
||||
:let ~(let ,verb (do ,rest))
|
||||
:after ~(do ,rest ,verb nil)
|
||||
:before ~(do ,verb ,rest nil)
|
||||
:repeat (with-syms [iter]
|
||||
~(do (var ,iter ,verb) (while (,> ,iter 0) ,rest (as-macro ,-- ,iter))))
|
||||
:when ~(as-macro ,when ,verb ,rest)
|
||||
:unless ~(as-macro ,unless ,verb ,rest)
|
||||
~(do (var ,iter ,verb) (while (> ,iter 0) ,rest (-- ,iter))))
|
||||
:when ~(when ,verb ,rest)
|
||||
:unless ~(unless ,verb ,rest)
|
||||
(error (string "unexpected loop modifier " binding))))))
|
||||
|
||||
# 3 term expression
|
||||
@@ -612,7 +587,7 @@
|
||||
"Evaluate body n times. If n is negative, body will be evaluated 0 times. Evaluates to nil."
|
||||
[n & body]
|
||||
(with-syms [iter]
|
||||
~(do (var ,iter ,n) (while (,> ,iter 0) ,;body (as-macro ,-- ,iter)))))
|
||||
~(do (var ,iter ,n) (while (> ,iter 0) ,;body (-- ,iter)))))
|
||||
|
||||
(defmacro forever
|
||||
"Evaluate body forever in a loop, or until a break statement."
|
||||
@@ -708,7 +683,7 @@
|
||||
[head & body]
|
||||
(def $accum (gensym))
|
||||
(check-empty-body body)
|
||||
~(do (def ,$accum @[]) (as-macro ,loop ,head (,array/push ,$accum (do ,;body))) ,$accum))
|
||||
~(do (def ,$accum @[]) (loop ,head (,array/push ,$accum (do ,;body))) ,$accum))
|
||||
|
||||
(defmacro catseq
|
||||
``Similar to `loop`, but concatenates each element from the loop body into an array and returns that.
|
||||
@@ -716,21 +691,21 @@
|
||||
[head & body]
|
||||
(def $accum (gensym))
|
||||
(check-empty-body body)
|
||||
~(do (def ,$accum @[]) (as-macro ,loop ,head (,array/concat ,$accum (do ,;body))) ,$accum))
|
||||
~(do (def ,$accum @[]) (loop ,head (,array/concat ,$accum (do ,;body))) ,$accum))
|
||||
|
||||
(defmacro tabseq
|
||||
``Similar to `loop`, but accumulates key value pairs into a table.
|
||||
See `loop` for details.``
|
||||
[head key-body & value-body]
|
||||
(def $accum (gensym))
|
||||
~(do (def ,$accum @{}) (as-macro ,loop ,head (,put ,$accum ,key-body (do ,;value-body))) ,$accum))
|
||||
~(do (def ,$accum @{}) (loop ,head (,put ,$accum ,key-body (do ,;value-body))) ,$accum))
|
||||
|
||||
(defmacro generate
|
||||
``Create a generator expression using the `loop` syntax. Returns a fiber
|
||||
that yields all values inside the loop in order. See `loop` for details.``
|
||||
[head & body]
|
||||
(check-empty-body body)
|
||||
~(,fiber/new (fn :generate [] (as-macro ,loop ,head (,yield (do ,;body)))) :yi))
|
||||
~(,fiber/new (fn :generate [] (loop ,head (yield (do ,;body)))) :yi))
|
||||
|
||||
(defmacro coro
|
||||
"A wrapper for making fibers that may yield multiple values (coroutine). Same as `(fiber/new (fn [] ;body) :yi)`."
|
||||
@@ -779,10 +754,35 @@
|
||||
(each x xs (*= accum x))
|
||||
accum)
|
||||
|
||||
# declare ahead of time
|
||||
(var- macexvar nil)
|
||||
|
||||
(defmacro if-let
|
||||
``Make multiple bindings, and if all are truthy,
|
||||
evaluate the `tru` form. If any are false or nil, evaluate
|
||||
the `fal` form. Bindings have the same syntax as the `let` macro.``
|
||||
[bindings tru &opt fal]
|
||||
(def len (length bindings))
|
||||
(if (= 0 len) (error "expected at least 1 binding"))
|
||||
(if (odd? len) (error "expected an even number of bindings"))
|
||||
(def fal2 (if macexvar (macexvar fal) fal))
|
||||
(defn aux [i]
|
||||
(if (>= i len)
|
||||
tru
|
||||
(do
|
||||
(def bl (in bindings i))
|
||||
(def br (in bindings (+ 1 i)))
|
||||
(if (symbol? bl)
|
||||
~(if (def ,bl ,br) ,(aux (+ 2 i)) ,fal2)
|
||||
~(if (def ,(def sym (gensym)) ,br)
|
||||
(do (def ,bl ,sym) ,(aux (+ 2 i)))
|
||||
,fal2)))))
|
||||
(aux 0))
|
||||
|
||||
(defmacro when-let
|
||||
"Same as `(if-let bindings (do ;body))`."
|
||||
[bindings & body]
|
||||
~(as-macro ,if-let ,bindings (do ,;body)))
|
||||
~(if-let ,bindings (do ,;body)))
|
||||
|
||||
(defn comp
|
||||
`Takes multiple functions and returns a function that is the composition
|
||||
@@ -1432,7 +1432,7 @@
|
||||
(tuple n @[])))
|
||||
(def sym (gensym))
|
||||
(def parts (array/concat @[h sym] t))
|
||||
~(as-macro ,let [,sym ,last] (if ,sym ,(keep-syntax! n parts))))
|
||||
~(let [,sym ,last] (if ,sym ,(keep-syntax! n parts))))
|
||||
(reduce fop x forms))
|
||||
|
||||
(defmacro -?>>
|
||||
@@ -1448,7 +1448,7 @@
|
||||
(tuple n @[])))
|
||||
(def sym (gensym))
|
||||
(def parts (array/concat @[h] t @[sym]))
|
||||
~(as-macro ,let [,sym ,last] (if ,sym ,(keep-syntax! n parts))))
|
||||
~(let [,sym ,last] (if ,sym ,(keep-syntax! n parts))))
|
||||
(reduce fop x forms))
|
||||
|
||||
(defn- walk-ind [f form]
|
||||
@@ -2411,8 +2411,8 @@
|
||||
(dictionary? m) (merge-into metadata m)
|
||||
(error (string "invalid metadata " m))))
|
||||
(with-syms [entry old-entry f]
|
||||
~(as-macro ,let [,old-entry (,dyn ',name)]
|
||||
(def ,entry (as-macro ,or ,old-entry @{:ref @[nil]}))
|
||||
~(let [,old-entry (,dyn ',name)]
|
||||
(def ,entry (or ,old-entry @{:ref @[nil]}))
|
||||
(,setdyn ',name ,entry)
|
||||
(def ,f ,fbody)
|
||||
(,put-in ,entry [:ref 0] ,f)
|
||||
@@ -3953,7 +3953,7 @@
|
||||
``
|
||||
[sec & body]
|
||||
(with-syms [f]
|
||||
~(as-macro ,let [,f (as-macro ,coro ,;body)]
|
||||
~(let [,f (coro ,;body)]
|
||||
(,ev/deadline ,sec nil ,f)
|
||||
(,resume ,f))))
|
||||
|
||||
@@ -4085,15 +4085,15 @@
|
||||
(defn make-ptr []
|
||||
(assertf (ffi/lookup (if lazy (llib) lib) raw-symbol) "failed to find ffi symbol %v" raw-symbol))
|
||||
(if lazy
|
||||
~(as-macro ,defn ,alias ,;meta [,;formal-args]
|
||||
~(defn ,alias ,;meta [,;formal-args]
|
||||
(,ffi/call (,(delay (make-ptr))) (,(delay (make-sig))) ,;formal-args))
|
||||
~(as-macro ,defn ,alias ,;meta [,;formal-args]
|
||||
~(defn ,alias ,;meta [,;formal-args]
|
||||
(,ffi/call ,(make-ptr) ,(make-sig) ,;formal-args))))
|
||||
|
||||
(defmacro ffi/defbind :flycheck
|
||||
"Generate bindings for native functions in a convenient manner."
|
||||
[name ret-type & body]
|
||||
~(as-macro ,ffi/defbind-alias ,name ,name ,ret-type ,;body)))
|
||||
~(ffi/defbind-alias ,name ,name ,ret-type ,;body)))
|
||||
|
||||
###
|
||||
###
|
||||
|
||||
@@ -1110,7 +1110,6 @@ JANET_CORE_FN(cfun_disasm,
|
||||
if (!janet_cstrcmp(kw, "structarg")) return janet_disasm_structarg(f->def);
|
||||
if (!janet_cstrcmp(kw, "namedargs")) return janet_disasm_namedargs(f->def);
|
||||
if (!janet_cstrcmp(kw, "slotcount")) return janet_disasm_slotcount(f->def);
|
||||
if (!janet_cstrcmp(kw, "symbolmap")) return janet_disasm_symbolslots(f->def);
|
||||
if (!janet_cstrcmp(kw, "constants")) return janet_disasm_constants(f->def);
|
||||
if (!janet_cstrcmp(kw, "sourcemap")) return janet_disasm_sourcemap(f->def);
|
||||
if (!janet_cstrcmp(kw, "environments")) return janet_disasm_environments(f->def);
|
||||
|
||||
@@ -1172,7 +1172,7 @@ JanetChannel *janet_channel_make(uint32_t limit) {
|
||||
JanetChannel *janet_channel_make_threaded(uint32_t limit) {
|
||||
janet_assert(limit <= INT32_MAX, "bad limit");
|
||||
JanetChannel *channel = janet_abstract_threaded(&janet_channel_type, sizeof(JanetChannel));
|
||||
janet_chan_init(channel, (int32_t) limit, 1);
|
||||
janet_chan_init(channel, (int32_t) limit, 0);
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
||||
105
src/core/pp.c
105
src/core/pp.c
@@ -72,7 +72,7 @@ static int count_dig10(int32_t x) {
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t integer_to_string_b(JanetBuffer *buffer, int32_t x) {
|
||||
static void integer_to_string_b(JanetBuffer *buffer, int32_t x) {
|
||||
janet_buffer_extra(buffer, BUFSIZE);
|
||||
uint8_t *buf = buffer->data + buffer->count;
|
||||
int32_t neg = 0;
|
||||
@@ -80,7 +80,7 @@ static int32_t integer_to_string_b(JanetBuffer *buffer, int32_t x) {
|
||||
if (x == 0) {
|
||||
buf[0] = '0';
|
||||
buffer->count++;
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
if (x > 0) {
|
||||
x = -x;
|
||||
@@ -96,7 +96,6 @@ static int32_t integer_to_string_b(JanetBuffer *buffer, int32_t x) {
|
||||
x /= 10;
|
||||
}
|
||||
buffer->count += len + neg;
|
||||
return len + neg;
|
||||
}
|
||||
|
||||
#define HEX(i) (((uint8_t *) janet_base64)[(i)])
|
||||
@@ -135,55 +134,43 @@ static void string_description_b(JanetBuffer *buffer, const char *title, void *p
|
||||
#undef POINTSIZE
|
||||
}
|
||||
|
||||
static int janet_escape_string_impl(JanetBuffer *buffer, const uint8_t *str, int32_t len) {
|
||||
static void janet_escape_string_impl(JanetBuffer *buffer, const uint8_t *str, int32_t len) {
|
||||
janet_buffer_push_u8(buffer, '"');
|
||||
int align = 1;
|
||||
for (int32_t i = 0; i < len; ++i) {
|
||||
uint8_t c = str[i];
|
||||
switch (c) {
|
||||
case '"':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\\"", 2);
|
||||
align += 2;
|
||||
break;
|
||||
case '\n':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\n", 2);
|
||||
align += 2;
|
||||
break;
|
||||
case '\r':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\r", 2);
|
||||
align += 2;
|
||||
break;
|
||||
case '\0':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\0", 2);
|
||||
align += 2;
|
||||
break;
|
||||
case '\f':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\f", 2);
|
||||
align += 2;
|
||||
break;
|
||||
case '\v':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\v", 2);
|
||||
align += 2;
|
||||
break;
|
||||
case '\a':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\a", 2);
|
||||
align += 2;
|
||||
break;
|
||||
case '\b':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\b", 2);
|
||||
align += 2;
|
||||
break;
|
||||
case 27:
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\e", 2);
|
||||
align += 2;
|
||||
break;
|
||||
case '\\':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\\\", 2);
|
||||
align += 2;
|
||||
break;
|
||||
case '\t':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\t", 2);
|
||||
align += 2;
|
||||
break;
|
||||
default:
|
||||
if (c < 32 || c > 126) {
|
||||
@@ -193,16 +180,13 @@ static int janet_escape_string_impl(JanetBuffer *buffer, const uint8_t *str, int
|
||||
buf[2] = janet_base64[(c >> 4) & 0xF];
|
||||
buf[3] = janet_base64[c & 0xF];
|
||||
janet_buffer_push_bytes(buffer, buf, 4);
|
||||
align += 4;
|
||||
} else {
|
||||
janet_buffer_push_u8(buffer, c);
|
||||
align++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
janet_buffer_push_u8(buffer, '"');
|
||||
return align + 1;
|
||||
}
|
||||
|
||||
static void janet_escape_string_b(JanetBuffer *buffer, const uint8_t *str) {
|
||||
@@ -374,7 +358,7 @@ const uint8_t *janet_to_string(Janet x) {
|
||||
struct pretty {
|
||||
JanetBuffer *buffer;
|
||||
int depth;
|
||||
int align;
|
||||
int indent;
|
||||
int flags;
|
||||
int32_t bufstartlen;
|
||||
int32_t *keysort_buffer;
|
||||
@@ -466,15 +450,14 @@ static int print_jdn_one(struct pretty *S, Janet x, int depth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_newline(struct pretty *S, int align) {
|
||||
static void print_newline(struct pretty *S, int just_a_space) {
|
||||
int i;
|
||||
S->align = align;
|
||||
if (S->flags & JANET_PRETTY_ONELINE) {
|
||||
if (just_a_space || (S->flags & JANET_PRETTY_ONELINE)) {
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
return;
|
||||
}
|
||||
janet_buffer_push_u8(S->buffer, '\n');
|
||||
for (i = 0; i < S->align; i++) {
|
||||
for (i = 0; i < S->indent; i++) {
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
}
|
||||
}
|
||||
@@ -501,12 +484,14 @@ static const char *janet_pretty_colors[] = {
|
||||
"\x1B[36m"
|
||||
};
|
||||
|
||||
#define JANET_PRETTY_DICT_ONELINE 4
|
||||
#define JANET_PRETTY_IND_ONELINE 10
|
||||
#define JANET_PRETTY_DICT_LIMIT 30
|
||||
#define JANET_PRETTY_DICT_KEYSORT_LIMIT 2000
|
||||
#define JANET_PRETTY_ARRAY_LIMIT 160
|
||||
|
||||
/* Helper for pretty printing */
|
||||
static void janet_pretty_one(struct pretty *S, Janet x) {
|
||||
static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
||||
/* Add to seen */
|
||||
switch (janet_type(x)) {
|
||||
case JANET_NIL:
|
||||
@@ -521,7 +506,7 @@ static void janet_pretty_one(struct pretty *S, Janet x) {
|
||||
janet_buffer_push_cstring(S->buffer, janet_cycle_color);
|
||||
}
|
||||
janet_buffer_push_cstring(S->buffer, "<cycle ");
|
||||
S->align += 8 + integer_to_string_b(S->buffer, janet_unwrap_integer(seenid));
|
||||
integer_to_string_b(S->buffer, janet_unwrap_integer(seenid));
|
||||
janet_buffer_push_u8(S->buffer, '>');
|
||||
if (S->flags & JANET_PRETTY_COLOR) {
|
||||
janet_buffer_push_cstring(S->buffer, "\x1B[0m");
|
||||
@@ -543,11 +528,9 @@ static void janet_pretty_one(struct pretty *S, Janet x) {
|
||||
if (janet_checktype(x, JANET_BUFFER) && janet_unwrap_buffer(x) == S->buffer) {
|
||||
janet_buffer_ensure(S->buffer, S->buffer->count + S->bufstartlen * 4 + 3, 1);
|
||||
janet_buffer_push_u8(S->buffer, '@');
|
||||
S->align += 1 + janet_escape_string_impl(S->buffer, S->buffer->data, S->bufstartlen);
|
||||
janet_escape_string_impl(S->buffer, S->buffer->data, S->bufstartlen);
|
||||
} else {
|
||||
S->align -= S->buffer->count;
|
||||
janet_description_b(S->buffer, x);
|
||||
S->align += S->buffer->count;
|
||||
}
|
||||
if (color && (S->flags & JANET_PRETTY_COLOR)) {
|
||||
janet_buffer_push_cstring(S->buffer, "\x1B[0m");
|
||||
@@ -564,34 +547,35 @@ static void janet_pretty_one(struct pretty *S, Janet x) {
|
||||
const char *startstr = isarray ? "@[" : hasbrackets ? "[" : "(";
|
||||
const char endchar = isarray ? ']' : hasbrackets ? ']' : ')';
|
||||
janet_buffer_push_cstring(S->buffer, startstr);
|
||||
const int align = S->align += strlen(startstr);
|
||||
S->depth--;
|
||||
S->indent += 2;
|
||||
if (S->depth == 0) {
|
||||
janet_buffer_push_cstring(S->buffer, "...");
|
||||
S->align += 3;
|
||||
} else {
|
||||
if (!isarray && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_IND_ONELINE)
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
if (is_dict_value && len >= JANET_PRETTY_IND_ONELINE) print_newline(S, 0);
|
||||
if (len > JANET_PRETTY_ARRAY_LIMIT && !(S->flags & JANET_PRETTY_NOTRUNC)) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (i) print_newline(S, align);
|
||||
janet_pretty_one(S, arr[i]);
|
||||
if (i) print_newline(S, 0);
|
||||
janet_pretty_one(S, arr[i], 0);
|
||||
}
|
||||
print_newline(S, align);
|
||||
print_newline(S, 0);
|
||||
janet_buffer_push_cstring(S->buffer, "...");
|
||||
S->align += 3;
|
||||
for (i = len - 3; i < len; i++) {
|
||||
print_newline(S, align);
|
||||
janet_pretty_one(S, arr[i]);
|
||||
for (i = 0; i < 3; i++) {
|
||||
print_newline(S, 0);
|
||||
janet_pretty_one(S, arr[len - 3 + i], 0);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i) print_newline(S, align);
|
||||
janet_pretty_one(S, arr[i]);
|
||||
if (i) print_newline(S, len < JANET_PRETTY_IND_ONELINE);
|
||||
janet_pretty_one(S, arr[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
S->indent -= 2;
|
||||
S->depth++;
|
||||
janet_buffer_push_u8(S->buffer, endchar);
|
||||
S->align++;
|
||||
break;
|
||||
}
|
||||
case JANET_STRUCT:
|
||||
@@ -602,7 +586,6 @@ static void janet_pretty_one(struct pretty *S, Janet x) {
|
||||
if (istable) {
|
||||
JanetTable *t = janet_unwrap_table(x);
|
||||
JanetTable *proto = t->proto;
|
||||
S->align++;
|
||||
janet_buffer_push_cstring(S->buffer, "@");
|
||||
if (NULL != proto) {
|
||||
Janet name = janet_table_get(proto, janet_ckeywordv("_name"));
|
||||
@@ -613,7 +596,6 @@ static void janet_pretty_one(struct pretty *S, Janet x) {
|
||||
janet_buffer_push_cstring(S->buffer, janet_class_color);
|
||||
}
|
||||
janet_buffer_push_bytes(S->buffer, n, len);
|
||||
S->align += len;
|
||||
if (S->flags & JANET_PRETTY_COLOR) {
|
||||
janet_buffer_push_cstring(S->buffer, "\x1B[0m");
|
||||
}
|
||||
@@ -631,24 +613,25 @@ static void janet_pretty_one(struct pretty *S, Janet x) {
|
||||
janet_buffer_push_cstring(S->buffer, janet_class_color);
|
||||
}
|
||||
janet_buffer_push_bytes(S->buffer, n, len);
|
||||
S->align += len;
|
||||
if (S->flags & JANET_PRETTY_COLOR) {
|
||||
janet_buffer_push_cstring(S->buffer, "\x1B[0m");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
janet_buffer_push_u8(S->buffer, '{');
|
||||
const int align = ++S->align;
|
||||
janet_buffer_push_cstring(S->buffer, "{");
|
||||
|
||||
S->depth--;
|
||||
S->indent += 2;
|
||||
if (S->depth == 0) {
|
||||
janet_buffer_push_cstring(S->buffer, "...");
|
||||
S->align += 3;
|
||||
} else {
|
||||
int32_t len = 0, cap = 0;
|
||||
const JanetKV *kvs = NULL;
|
||||
janet_dictionary_view(x, &kvs, &len, &cap);
|
||||
if (!istable && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_DICT_ONELINE)
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
if (is_dict_value && len >= JANET_PRETTY_DICT_ONELINE) print_newline(S, 0);
|
||||
int32_t ks_start = S->keysort_start;
|
||||
int truncated = 0;
|
||||
|
||||
@@ -661,17 +644,15 @@ static void janet_pretty_one(struct pretty *S, Janet x) {
|
||||
int32_t j = 0;
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
while (janet_checktype(kvs[j].key, JANET_NIL)) j++;
|
||||
if (i) print_newline(S, align);
|
||||
janet_pretty_one(S, kvs[j].key);
|
||||
if (i) print_newline(S, len < JANET_PRETTY_DICT_ONELINE);
|
||||
janet_pretty_one(S, kvs[j].key, 0);
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
S->align++;
|
||||
janet_pretty_one(S, kvs[j].value);
|
||||
janet_pretty_one(S, kvs[j].value, 1);
|
||||
j++;
|
||||
}
|
||||
if (truncated) {
|
||||
print_newline(S, align);
|
||||
print_newline(S, 0);
|
||||
janet_buffer_push_cstring(S->buffer, "...");
|
||||
S->align += 3;
|
||||
}
|
||||
} else {
|
||||
/* Sorted keys dictionaries */
|
||||
@@ -704,26 +685,24 @@ static void janet_pretty_one(struct pretty *S, Janet x) {
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
if (i) print_newline(S, align);
|
||||
if (i) print_newline(S, len < JANET_PRETTY_DICT_ONELINE);
|
||||
int32_t j = S->keysort_buffer[i + ks_start];
|
||||
janet_pretty_one(S, kvs[j].key);
|
||||
janet_pretty_one(S, kvs[j].key, 0);
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
S->align++;
|
||||
janet_pretty_one(S, kvs[j].value);
|
||||
janet_pretty_one(S, kvs[j].value, 1);
|
||||
}
|
||||
|
||||
if (truncated) {
|
||||
print_newline(S, align);
|
||||
print_newline(S, 0);
|
||||
janet_buffer_push_cstring(S->buffer, "...");
|
||||
S->align += 3;
|
||||
}
|
||||
|
||||
}
|
||||
S->keysort_start = ks_start;
|
||||
}
|
||||
S->indent -= 2;
|
||||
S->depth++;
|
||||
janet_buffer_push_u8(S->buffer, '}');
|
||||
S->align++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -739,14 +718,14 @@ static JanetBuffer *janet_pretty_(JanetBuffer *buffer, int depth, int flags, Jan
|
||||
}
|
||||
S.buffer = buffer;
|
||||
S.depth = depth;
|
||||
S.align = 0;
|
||||
S.indent = 0;
|
||||
S.flags = flags;
|
||||
S.bufstartlen = startlen;
|
||||
S.keysort_capacity = 0;
|
||||
S.keysort_buffer = NULL;
|
||||
S.keysort_start = 0;
|
||||
janet_table_init(&S.seen, 10);
|
||||
janet_pretty_one(&S, x);
|
||||
janet_pretty_one(&S, x, 0);
|
||||
janet_table_deinit(&S.seen);
|
||||
return S.buffer;
|
||||
}
|
||||
@@ -764,7 +743,7 @@ static JanetBuffer *janet_jdn_(JanetBuffer *buffer, int depth, Janet x, int32_t
|
||||
}
|
||||
S.buffer = buffer;
|
||||
S.depth = depth;
|
||||
S.align = 0;
|
||||
S.indent = 0;
|
||||
S.flags = 0;
|
||||
S.bufstartlen = startlen;
|
||||
S.keysort_capacity = 0;
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
#include <janet.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
@@ -363,50 +362,33 @@ static void clear(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static int getplen(void) {
|
||||
int _plen = gbl_plen;
|
||||
/* Ensure at least 16 characters of data entry; */
|
||||
while (_plen && (_plen + 16 > gbl_cols)) {
|
||||
_plen--;
|
||||
}
|
||||
return _plen;
|
||||
}
|
||||
|
||||
static void refresh(void) {
|
||||
char seq[64];
|
||||
JanetBuffer b;
|
||||
|
||||
/* If prompt is too long, truncate */
|
||||
int _plen = getplen();
|
||||
|
||||
/* Keep cursor position on screen */
|
||||
char *_buf = gbl_buf;
|
||||
int _len = gbl_len;
|
||||
int _pos = gbl_pos;
|
||||
|
||||
while ((_plen + _pos) >= gbl_cols) {
|
||||
while ((gbl_plen + _pos) >= gbl_cols) {
|
||||
_buf++;
|
||||
_len--;
|
||||
_pos--;
|
||||
}
|
||||
|
||||
while ((_plen + _len) > gbl_cols) {
|
||||
while ((gbl_plen + _len) > gbl_cols) {
|
||||
_len--;
|
||||
}
|
||||
|
||||
|
||||
janet_buffer_init(&b, 0);
|
||||
/* Cursor to left edge, gbl_prompt and buffer */
|
||||
janet_buffer_push_u8(&b, '\r');
|
||||
janet_buffer_push_bytes(&b, (const uint8_t *) gbl_prompt, _plen);
|
||||
if (_len > 0) {
|
||||
janet_buffer_push_bytes(&b, (uint8_t *) _buf, _len);
|
||||
}
|
||||
janet_buffer_push_cstring(&b, gbl_prompt);
|
||||
janet_buffer_push_bytes(&b, (uint8_t *) _buf, _len);
|
||||
/* Erase to right */
|
||||
janet_buffer_push_cstring(&b, "\x1b[0K\r");
|
||||
/* Move cursor to original position. */
|
||||
if (_pos + _plen) {
|
||||
snprintf(seq, 64, "\x1b[%dC", (int)(_pos + _plen));
|
||||
if (_pos + gbl_plen) {
|
||||
snprintf(seq, 64, "\x1b[%dC", (int)(_pos + gbl_plen));
|
||||
janet_buffer_push_cstring(&b, seq);
|
||||
}
|
||||
if (write_console((char *) b.data, b.count) == -1) {
|
||||
@@ -432,8 +414,7 @@ static int insert(char c, int draw) {
|
||||
gbl_buf[gbl_pos++] = c;
|
||||
gbl_buf[++gbl_len] = '\0';
|
||||
if (draw) {
|
||||
int _plen = getplen();
|
||||
if (_plen + gbl_len < gbl_cols) {
|
||||
if (gbl_plen + gbl_len < gbl_cols) {
|
||||
/* Avoid a full update of the line in the
|
||||
* trivial case. */
|
||||
if (write_console(&c, 1) == -1) return -1;
|
||||
@@ -944,12 +925,11 @@ static int line() {
|
||||
gbl_len = 0;
|
||||
gbl_pos = 0;
|
||||
while (gbl_prompt[gbl_plen]) gbl_plen++;
|
||||
int _plen = getplen();
|
||||
gbl_buf[0] = '\0';
|
||||
|
||||
addhistory();
|
||||
|
||||
if (write_console((char *) gbl_prompt, _plen) == -1) return -1;
|
||||
if (write_console((char *) gbl_prompt, gbl_plen) == -1) return -1;
|
||||
for (;;) {
|
||||
char c;
|
||||
char seq[5];
|
||||
|
||||
@@ -61,68 +61,5 @@
|
||||
(check-jdn "a string")
|
||||
(check-jdn @"a buffer")
|
||||
|
||||
# Test multiline pretty specifiers
|
||||
(let [tup [:keyword "string" @"buffer"]
|
||||
tab @{true (table/setproto @{:bar tup
|
||||
:baz 42}
|
||||
@{:_name "Foo"})}]
|
||||
(set (tab tup) tab)
|
||||
(assert (= (string/format "%m" {tup @[tup tab]
|
||||
'symbol tup})
|
||||
`
|
||||
{symbol (:keyword
|
||||
"string"
|
||||
@"buffer")
|
||||
(:keyword
|
||||
"string"
|
||||
@"buffer") @[(:keyword
|
||||
"string"
|
||||
@"buffer")
|
||||
@{true @Foo{:bar (:keyword
|
||||
"string"
|
||||
@"buffer")
|
||||
:baz 42}
|
||||
(:keyword
|
||||
"string"
|
||||
@"buffer") <cycle 2>}]}`))
|
||||
(assert (= (string/format "%p" {(freeze (zipcoll (range 42)
|
||||
(range -42 0))) tab})
|
||||
`
|
||||
{{0 -42
|
||||
1 -41
|
||||
2 -40
|
||||
3 -39
|
||||
4 -38
|
||||
5 -37
|
||||
6 -36
|
||||
7 -35
|
||||
8 -34
|
||||
9 -33
|
||||
10 -32
|
||||
11 -31
|
||||
12 -30
|
||||
13 -29
|
||||
14 -28
|
||||
15 -27
|
||||
16 -26
|
||||
17 -25
|
||||
18 -24
|
||||
19 -23
|
||||
20 -22
|
||||
21 -21
|
||||
22 -20
|
||||
23 -19
|
||||
24 -18
|
||||
25 -17
|
||||
26 -16
|
||||
27 -15
|
||||
28 -14
|
||||
29 -13
|
||||
...} @{true @Foo{:bar (:keyword
|
||||
"string"
|
||||
@"buffer")
|
||||
:baz 42}
|
||||
(:keyword
|
||||
"string"
|
||||
@"buffer") <cycle 1>}}`)))
|
||||
(end-suite)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user