[Marc Mutz]:
It's a side-effect of executing setdate. I call this a
side-effect, since it's not an explicit "set".
alright.
(easily fixed, just specify lexical sorting of the "set" at all
times.)
I always wondered why imapflags didn't include a flag test. It
should, esp. if one considers the include extension where a
included script doesn't know what it's parent has already done and
might want to know.
agreed. the current method is to use a :matches, which will work, but
is a bit roundabout.
wouldn't it be better to make generic functions for this?
addflag "flag" "\\Flagged";
changes ${flag}. you'd now use
keep :flags "${flag}";
rather than
keep :globalflags;
and
keep :flags "${flag} \\Flagged";
instead of
keep :globalflags_plus "\\Flagged";
some scripts may become more verbose, but the complexity of the
IMAPFLAGS is decreased, IMO. (ADDFLAG and REMOVEFLAG could move to a
separate extension.)
One could always add the feature to accept multiple flags per string
argument, so you can use
set "myflags" "${#imapflags}" # save away
# ...
setflags "${myflags}" # restore
I fact, you already used that feature in the code above.
yep.
Also, keep in mind that imapflags implementations already exist
and you can imagine what a confusion would arise if addflags' et
al. syntax would be changed.
I don't think this is something we should worry too much about.
deploying features before they are standardised is a gamble.
mark
- equivalent to addflag "\\Flagged"
unmark
- equivalent to removeflag "\\Flagged"
what is the rationale for MARK and UNMARK? according to the draft
these actions are _not_ equivalent to ADDFLAG "\\Flagged".
But IIRC, it's suggested they are. However, this is nitpicking
again, since it's clear that the exact (un)mark semantics are
implementation-defined. I've just chosen the obvious one.
I was just wondering why their effect is allowed to be implementation
defined. I can see that MARK/UNMARK are useful shorthands.
Ok, here's what I think are properties of system variables, why
they are needed and why they should be prefixed:
I agree they need to be recognisable by syntax alone. one type of
prefix could be "date." or "imap.", ie. the distinguishing feature is
the presence of one or more periods.
3. They may represent concepts that are not naturally represented
as strings.
Examples: ${#imapflags} is a set of imap flags, not a string.
${#currentdate} is a number or struct tm or whatever, not a
string.
There are many issues if you allow ${#imapflags} to be "set" by
the user (duplicate or invalid flags, ordering
issues). However, it's a variable (remember that imapflags was
what prompted a variables extension in the first place, even if
you were not personally driven by that) and there was objection
to define extensions that have any kind of "internal variable"
(as imapflags once called it) without first having variables
for Sieve in general.
I don't understand this reasoning. you want "internal variables" with
properties very different from those of the general variables. where
is the connection between the features?
It is, however, potentially very useful to allow interpolation
into strings, and a system variable declaration must specify
the string representation to use. I've already given an example
for ${#imapflags}, ${#currentdate} could be interpolated in
rfc2822 format.
So system variables could be handled internally in their
natural representation, with a string representation being
required only on expansion into strings, which should be pretty
rare.
ok. I honestly don't know what's the best way to handle the IMAP
flags.
1)
part of me wants to add a list variable type. the main sticky point
is the interpolation. my suggestion was:
set "foo" [ "one", "two", "three" ];
set "bar" [ "${foo}", "four" ];
set "zot" [ "woo${foo}hoo" ];
now ${bar} is [ "one", "two", "three", "four" ] and ${zot} is [ "woo",
"one", "two", "three", "four", "hoo" ]. this makes "${foo}${bar}"
equivalent with [ "${foo}", "${bar}" ].
to go with this, we'd need a prune command to remove an element from a
list. actually we need two, one by position, and one by value. for
imapflags, an append command would be useful as well (it's not worth
worrying about duplicates.)
one problem with this is run-time syntax errors, like
set "folder" [ "foo", "bar" ];
fileinto "${folder}";
this could be solved by making making a new list variable syntax,
e.g., @{folder} becomes a list, while ${folder} is becomes a single
string with a single space as delimiter or something.
2)
part of me thinks strings will work OK. it just needs careful
programming to keep everything padded with spaces.
set "flags" "${flags} \\Flagged "; # note trailing space
if string :matches "${flags}" "* \\Flagged *" {
set "flags" "${1} ${2}";
}
3)
part of me thinks an intrinsic variable is the solution which appears
cleanest to the user.
why do you need variables at all for IMAP flags? to keep state, it
seems.
if something {
addflag "\\Flagged";
if somethingelse {
addflag "Big";
keep :globalflags;
}
}
# now we want to restore the flags to the values before the if.
# or do we?
sorry, I can't come up with a credible example.
4. Their values may not be computed with Sieve.
You said setdate would be a macro for a list of set's. But it
isn't. You can't represent setdate "+0200" like that.
I meant as seen from an optimising Sieve parser, not from a user
perspective. it wasn't a good comparison, anyway.
E.g. a hypothetical ${#envelope_sender} system variable would
not be a good idea, since you can always obtain that by using
the matches-set idiom:
if :envelope :all :matches "from" "*" {
set "myenvelopesender" "${1}";
}
it seems to me Sieve scripts will soon consist of mostly matches-set
idioms ... ;-)
5. Their values may not be available from the message.
Example: ${#currentdate}
I now agree that ${year} as specified is not a proper system
variable.
Here's a proposal for a date test (which is important to have in
it own right) that makes setdate superfluous by using the
matches-set idiom to explicitly set the setdate variables:
if date :current :timezone "+0200" :hour :matches "*" {
set "${hour}" "${1}";
}
you won't get daylight savings time handled correctly this way.
compare with
setdate "Europe/Oslo";
if not string "${timezone}" "Europe/Oslo" {
setdate "+0100";
}
ie., use Europe/Oslo if the server recognises the time zone, otherwise
fall back to +0100.
where the date test syntax would be:
date [COMPARATOR] WHICH [TIMEZONE] [DATE-PART] [MATCH-TYPE]
<key-list: string-list>
WHICH := ":current" / ":received" / ":sent"
/ ( ":header" <headerfield: string-list> )
DATE-PART := ":weekday" / ":day" / ":month" / ":year"
/ ":hour" / ":minute" / ":second" / ":numericzone"
/ ":all" / ... ; ":all" is default
TIMEZONE := ":timezone" <timezone: string>
; server's local timezone is default for :current,
timezone specified in the header is default for :received, :sent
and :header.
I think this is nice. but for a user simply wanting to save his mail
in different folders depending on month would write
setdate;
fileinto "INBOX.${year}-${month}";
which now becomes
if date :current :year :matches "*" {
set "year" "${1}";
}
if date :current :month :matches "*" {
fileinfo "INBOX.${year}-${1}";
}
Together with the relational extension and a rfc822-date
comparator,
please make it an ISO 8601 date comparator ...
And for those that want "old" setdate:
set "setdate_timezone" "CEST"
include :global "setdate";
where "setdate" includes the matches-set idioms:
:-)
the existence of a global "setdate" script is not guaranteed. isn't
it better to make the support for this certain? I think your date
test and SETDATE can co-exist.
In this scenario, ${#currentdate} would be a system variable with
all properties as defined above: It affects the date :current
test, is read-only, it's natural representation is not a string,
it's value can't be computed with Sieve and it can't be extracted
from the message.
but is this a good thing, or do we want to make generic mechanisms
instead?
--
Kjetil T. | read and make up your own mind
| http://www.cactus48.com/truth.html