summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-10-22 16:18:11 -0400
committerKaz Kylheku <kaz@kylheku.com>2011-10-22 16:18:11 -0400
commit6ddb4b8f329b14e6133f29573cfeb88d1ee30846 (patch)
tree3aa77c66532cf7aaaaf8aa7e9b05d9a634dfd2a7
parent70a3b3ae47671a8a73ac517cd7c3f6a4bce782e5 (diff)
downloadtxr-6ddb4b8f329b14e6133f29573cfeb88d1ee30846.tar.gz
txr-6ddb4b8f329b14e6133f29573cfeb88d1ee30846.tar.bz2
txr-6ddb4b8f329b14e6133f29573cfeb88d1ee30846.zip
* filter.c (get_filter_trie): Function renamed to get_filter. A filter
is not necessarily a trie. (string_filter, compound_filter): New functions. (get_filter): Recognize a compound filters and return a function which implements it. * filter.h (get_filter_trie): Declaration renamed. * match.c (format_field, v_bind, v_output): Follow get_filter_trie rename. Error message text updated. * txr.1: Describe compound filters.
-rw-r--r--ChangeLog15
-rw-r--r--filter.c23
-rw-r--r--filter.h2
-rw-r--r--match.c12
-rw-r--r--txr.128
5 files changed, 68 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 67e0a93a..5ce31148 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2011-10-22 Kaz Kylheku <kaz@kylheku.com>
+ * filter.c (get_filter_trie): Function renamed to get_filter. A filter
+ is not necessarily a trie.
+ (string_filter, compound_filter): New functions.
+ (get_filter): Recognize a compound filters and return a function
+ which implements it.
+
+ * filter.h (get_filter_trie): Declaration renamed.
+
+ * match.c (format_field, v_bind, v_output): Follow get_filter_trie
+ rename. Error message text updated.
+
+ * txr.1: Describe compound filters.
+
+2011-10-22 Kaz Kylheku <kaz@kylheku.com>
+
Task #11474
* filter.c (filter_equal): New function.
diff --git a/filter.c b/filter.c
index d5bdf262..4c787955 100644
--- a/filter.c
+++ b/filter.c
@@ -122,9 +122,28 @@ val trie_lookup_feed_char(val node, val ch)
return nil;
}
-val get_filter_trie(val sym)
+static val string_filter(val str, val filter)
{
- return gethash(filters, sym);
+ return filter_string(filter, str);
+}
+
+static val compound_filter(val filter_list, val string)
+{
+ return reduce_left(func_n2(string_filter), filter_list, string, nil);
+}
+
+val get_filter(val spec)
+{
+ if (consp(spec)) {
+ val filter_list = mapcar(curry_12_2(func_n2(gethash), filters), spec);
+
+ if (memqual(nil, filter_list))
+ return nil;
+
+ return curry_12_2(func_n2(compound_filter), filter_list);
+ }
+
+ return gethash(filters, spec);
}
struct filter_pair {
diff --git a/filter.h b/filter.h
index 7f37fa7c..d0d7d34b 100644
--- a/filter.h
+++ b/filter.h
@@ -30,7 +30,7 @@ extern val filter_k, to_html_k, from_html_k;
val trie_lookup_begin(val trie);
val trie_value_at(val node);
val trie_lookup_feed_char(val node, val ch);
-val get_filter_trie(val sym);
+val get_filter(val sym);
val filter_string(val trie, val str);
val filter_equal(val filter, val left, val right);
val register_filter(val sym, val table);
diff --git a/match.c b/match.c
index ec153f82..9c8def60 100644
--- a/match.c
+++ b/match.c
@@ -1002,10 +1002,10 @@ static val format_field(val string_or_list, val modifier, val filter)
val filter_sym = getplist(plist, filter_k);
if (filter_sym) {
- filter = get_filter_trie(filter_sym);
+ filter = get_filter(filter_sym);
if (!filter) {
- uw_throwf(query_error_s, lit("format_field: filter ~s not known"),
+ uw_throwf(query_error_s, lit("format_field: ~s specifies unknown filter"),
filter_sym, nao);
}
}
@@ -2144,10 +2144,10 @@ static val v_bind(match_files_ctx c, match_files_ctx *cout)
val filter_sym = getplist(keywords, filter_k);
if (filter_sym) {
- val filter = get_filter_trie(filter_sym);
+ val filter = get_filter(filter_sym);
if (!filter) {
- uw_throwf(query_error_s, lit("bind: filter ~s not known"),
+ uw_throwf(query_error_s, lit("bind: ~s specifies unknown filter"),
filter_sym, nao);
}
@@ -2239,10 +2239,10 @@ static val v_output(match_files_ctx c, match_files_ctx *cout)
val filter_sym = cdr(assoc(alist, filter_k));
if (filter_sym) {
- filter = get_filter_trie(filter_sym);
+ filter = get_filter(filter_sym);
if (!filter)
- sem_error(spec_linenum, lit("unknown filter ~s"), filter_sym, nao);
+ sem_error(spec_linenum, lit("~s specifies unknown filter"), filter_sym, nao);
}
}
diff --git a/txr.1 b/txr.1
index 2542adcb..dbfffd86 100644
--- a/txr.1
+++ b/txr.1
@@ -2144,6 +2144,8 @@ Bind will see that A and B have bindings already, and so compare their
contents. Since the :upcase filter is specified, both their contents will be
reduced through it for the purposes of the comparison, rendering them equal.
+Of course, compound filters are supported like (:from_html :upcase).
+
.SS The Set Directive
The @(set) directive resembles bind, but is not a pattern match. It overwrites
@@ -2750,8 +2752,11 @@ The following value keywords are supported:
.IP :filter
-The argument is a symbol, which specifies a filter to be applied to the
-variable substitutions occuring within the output clause.
+The argument can be a symbol, which specifies a filter to be applied to
+the variable substitutions occuring within the output clause.
+The argument can also be a list of filter symbols, which specifies
+that multiple filters are to be applied, in left to right order.
+
See the later sections Output Filtering below, and The Deffilter Directive.
.IP :into
@@ -2788,7 +2793,9 @@ that field, if the width is specified as a positive number, and right-adjusted
if the width is specified as negative.
An output variable may specify a filter which overrides any filter established
-for the output clause. The syntax for this is @(NAME :filter <filtername>}.
+for the output clause. The syntax for this is @(NAME :filter <filterspec>}.
+The filter specification syntax is the same as in the output clause.
+See Output Filtering below.
.SS The Repeat Directive
@@ -2979,6 +2986,21 @@ To filter an individual variable, add the syntax to the variable spec:
@{x :filter :to_html}
@(end)
+Multiple filters can be applied at the same time. For instance:
+
+ @(output)
+ @{x :filter (:upcase :to_html)}
+ @(end)
+
+This will fold the contents of x to upper case, and then encode any special
+characters into HTML. Beware of combinations that do not make sense.
+For instance, suppose the original text is HTML, containing codes
+like '&quot;'. The compound filter (:upcase :from_html) will not work
+because '&quot;' will turn to '&QUOT;' which no longer be recognized
+by the :from_html filter, because the entity names in HTML codes
+are case-sensitive.
+
+
.SS The Deffilter Directive
The deffilter directive allows a query to define a custom filter, which