mirror of
https://github.com/sbrow/thor.git
synced 2026-08-26 11:23:32 -04:00
refactor: Filters are now read as an enum.
This commit is contained in:
@@ -27,12 +27,13 @@
|
|||||||
the correct template source/path. Other render errors still use the
|
the correct template source/path. Other render errors still use the
|
||||||
content template's source/path, which can point at the wrong file.
|
content template's source/path, which can point at the wrong file.
|
||||||
- [ ] try to make file paths clickable links.
|
- [ ] try to make file paths clickable links.
|
||||||
|
- [ ] centralize diagnostics to one place.
|
||||||
- [ ] Load grammars dynamically
|
- [ ] Load grammars dynamically
|
||||||
- [ ] starred must be a param.
|
- [ ] starred must be a param.
|
||||||
- [ ] Documentation
|
- [ ] Documentation
|
||||||
- [ ] talk about the context stack (and its limit).
|
- [ ] talk about the context stack (and its limit).
|
||||||
- [ ] highlight the differences in the way menus are handled.
|
- [ ] highlight the differences in the way menus are handled.
|
||||||
- [ ] consider sites with data based urls.
|
- [ ] consider sites with date based urls.
|
||||||
- [ ] Don't show annoying log output in tests.
|
- [ ] Don't show annoying log output in tests.
|
||||||
- [ ] improve home link customization.
|
- [ ] improve home link customization.
|
||||||
- [ ] currently an accessibility issue.
|
- [ ] currently an accessibility issue.
|
||||||
|
|||||||
+53
-12
@@ -1,5 +1,6 @@
|
|||||||
package mustache
|
package mustache
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
import "core:reflect"
|
import "core:reflect"
|
||||||
@@ -16,6 +17,44 @@ MAX_PIPE_ARGS :: 2
|
|||||||
|
|
||||||
DEFAULT_DATE_FORMAT :: "2 Jan 2006"
|
DEFAULT_DATE_FORMAT :: "2 Jan 2006"
|
||||||
|
|
||||||
|
Pipe_Op :: enum {
|
||||||
|
Format,
|
||||||
|
Group_By,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pipe op names are derived from the enum via reflection (lowercased).
|
||||||
|
// Adding a new op only requires adding it to the enum AND handling it in
|
||||||
|
// apply_filter's switch — the compiler enforces exhaustive matching.
|
||||||
|
|
||||||
|
pipe_op_from_string :: proc(s: string) -> (Pipe_Op, bool) {
|
||||||
|
ti := type_info_of(typeid_of(Pipe_Op))
|
||||||
|
base := runtime.type_info_base(ti)
|
||||||
|
#partial switch &e in base.variant {
|
||||||
|
case runtime.Type_Info_Enum:
|
||||||
|
for name, idx in e.names {
|
||||||
|
lower := strings.to_lower(name, context.temp_allocator) or_else name
|
||||||
|
if lower == s {
|
||||||
|
return cast(Pipe_Op)idx, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
pipe_op_candidates :: proc(allocator := context.temp_allocator) -> []string {
|
||||||
|
ti := type_info_of(typeid_of(Pipe_Op))
|
||||||
|
base := runtime.type_info_base(ti)
|
||||||
|
out := make([dynamic]string, 0, 2, allocator)
|
||||||
|
#partial switch &e in base.variant {
|
||||||
|
case runtime.Type_Info_Enum:
|
||||||
|
for name in e.names {
|
||||||
|
lower := strings.to_lower(name, allocator) or_else name
|
||||||
|
append(&out, lower)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out[:]
|
||||||
|
}
|
||||||
|
|
||||||
Pipe_Filter :: struct {
|
Pipe_Filter :: struct {
|
||||||
op: string,
|
op: string,
|
||||||
args: [dynamic; MAX_PIPE_ARGS]string,
|
args: [dynamic; MAX_PIPE_ARGS]string,
|
||||||
@@ -217,12 +256,21 @@ resolve_format_string :: proc(name: string, ctx: []any, pos: int) -> (string, Er
|
|||||||
return str, nil
|
return str, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: diagnostics don't show anything relevant
|
|
||||||
apply_filter :: proc(value: any, filter: ^Pipe_Filter, pos: int, ctx: []any) -> (any, Error) {
|
apply_filter :: proc(value: any, filter: ^Pipe_Filter, pos: int, ctx: []any) -> (any, Error) {
|
||||||
switch filter.op {
|
op, ok := pipe_op_from_string(filter.op)
|
||||||
case "group_by":
|
if !ok {
|
||||||
|
return nil, Error_Body {
|
||||||
|
msg = fmt.tprintf("unknown pipe op '%s'", filter.op),
|
||||||
|
pos = filter.op_pos,
|
||||||
|
span = len(filter.op),
|
||||||
|
kind = .Data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case .Group_By:
|
||||||
return apply_group_by(value, filter.args[:], pos)
|
return apply_group_by(value, filter.args[:], pos)
|
||||||
case "format":
|
case .Format:
|
||||||
str, ok := reflect.as_string(value)
|
str, ok := reflect.as_string(value)
|
||||||
if !ok {
|
if !ok {
|
||||||
return value, Error_Body {
|
return value, Error_Body {
|
||||||
@@ -260,15 +308,8 @@ apply_filter :: proc(value: any, filter: ^Pipe_Filter, pos: int, ctx: []any) ->
|
|||||||
} else {
|
} else {
|
||||||
return any{new_clone(str2, context.temp_allocator), typeid_of(string)}, nil
|
return any{new_clone(str2, context.temp_allocator), typeid_of(string)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
case:
|
|
||||||
return nil, Error_Body {
|
|
||||||
msg = fmt.tprintf("unknown pipe op '%s'", filter.op),
|
|
||||||
pos = filter.op_pos,
|
|
||||||
span = len(filter.op),
|
|
||||||
kind = .Data,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return {}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_format :: proc(
|
apply_format :: proc(
|
||||||
|
|||||||
Reference in New Issue
Block a user