Можно использовать openssl
для этого (и для других хеш-алгоритмов):
$ openssl list-message-digest-commands
md4
md5
mdc2
rmd160
sha
sha1
$ openssl rmd160 /usr/bin/openssl
RIPEMD160(/usr/bin/openssl)= 788e595dcadb4b75e20c1dbf54a18a23cf233787
Если Вы используете версию "разработки" дурака (v1.5 +) - и Вы абсолютно должны - существует возможность использовать внешний фильтр, как описано в руководстве.
Сначала Вам нужен сценарий, который может произвести разные вещи согласно возрасту сообщения. Вот пример в Python:
#!/usr/bin/env python
"""mutt format date
Prints different index_format strings for mutt according to a
messages age.
The single command line argument should be a unix timestamp
giving the message's date (%{}, etc. in Mutt).
"""
import sys
from datetime import datetime
INDEX_FORMAT = "%Z {} %?X?(%X)& ? %-22.22F %.100s %> %5c%"
def age_fmt(msg_date, now):
# use iso date for messages of the previous year and before
if msg_date.date().year < now.date().year:
return '%[%Y-%m-%d]'
# use "Month Day" for messages of this year
if msg_date.date() < now.date():
return '%10[%b %e]'
# if a message appears to come from the future
if msg_date > now:
return ' b0rken'
# use only the time for messages that arrived today
return '%10[%H:%m]'
if __name__ == '__main__':
msg_date = datetime.fromtimestamp(int(sys.argv[1]))
now = datetime.now()
print INDEX_FORMAT.format(age_fmt(msg_date, now))
Сохраните это как mutt-fmt-date
где-нибудь на Вашем ПУТИ.
Две вещи важны здесь:
{}
который заменяется возвращаемым значением age_fmt()
Python.%
так, чтобы Дурак интерпретировал его.Затем можно использовать его в Вашем .muttrc
следующим образом:
set index_format="mutt-fmt-date %[%s] |"
Дурак будет затем
%[%s]
согласно правилам для строк формата.mutt-fmt-date
с результатом 1. как аргумент (из-за |
в конце).%
в конце).Протест: сценарий будет выполняться для каждого сообщения, которое должно быть о быть отображенным. Получающаяся задержка может быть довольно noticable при просмотре почтового ящика.
Вот версия в C, который работает несколько соответственно:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define DAY (time_t)86400
#define YEAR (time_t)31556926
int main(int argc, const char *argv[]) {
time_t current_time;
time_t message_time;
const char *old, *recent, *today;
const char *format;
current_time = time(NULL);
if (argc!=6) {
printf("Usage: %s old recent today format timestamp\n", argv[0]);
return 2;
}
old = argv[1];
recent = argv[2];
today = argv[3];
format = argv[4];
message_time = atoi(argv[5]);
if ((message_time/YEAR) < (current_time/YEAR)) {
printf(format, old);
} else if ((message_time/DAY) < (current_time/DAY)) {
printf(format, recent);
} else {
printf(format, today);
}
return 0;
}
Это сочетается с muttrc строкой:
set index_format='mfdate "%[%d.%m.%y]" "%8[%e. %b]" "%8[%H:%m]" "%Z %%s %-20.20L %?y?[%-5.5y]& ? %?M?+& ?%s%%" "%[%s]" |'
К сожалению, это, кажется, не возможно с текущими версиями Дурака.
$index_format
поддерживает определенный набор спецификаторов формата, тянущих из различных метаданных сообщения. Это описано в руководстве Дурака (или вот документация "стабильной" версии для того же), и как Вы видите от таблицы, существует только несколько спецификаторов формата, которые являются условным выражением. Это %M
, %y
и %Y
; %M является количеством скрытых сообщений, если поток сворачивается, и %y и %Y являются заголовками X-маркировки если существующий.
Фактическое форматирование даты и времени сообщения сделано strftime(3)
, который не поддерживает условное форматирование вообще.
Могло бы быть возможно сделать ужасное обходное решение путем непрерывной перезаписи файлов сообщений Date:
заголовки, но я не хотел бы делать это, по крайней мере. Однако это - наименее плохая возможность, что я могу думать.
Единственное действительное решение, о котором я могу думать, состояло бы в том, чтобы или реализовать такую поддержку в Дураке (который почти наверняка является, как Thunderbird делает это), или запишите замену strftime
который поддерживает условное форматирование, и введите то использование LD_PRELOAD или подобный механизм. Последний, однако, будет влиять на весь дисплей даты и времени в Дураке, который проходит strftime, не только касающийся индекса сообщения.
Внесены некоторые изменения, но не решена проблема "% в теме"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define DAY (time_t)86400
#define WEEK (time_t)604800
#define MONTH (time_t)2678400
#define YEAR (time_t)31556926
/*I use this line in .muttrc:
* set index_format = '/home/marcus/.mutt/mfdate "%9[%d.%m.%y]" "%9[%e.%b]" " [%6[%e.%b]]" "%8[%a %H:%m]" " %[%H:%m]" "%Z %%s %?X?%2X& ? %-20.20L %?M?+%-2M& ? %.86s %> [%4c]asladfg" "%[%s]" |'*/
int main(int argc, const char *argv[]) {
time_t current_time;
time_t message_time;
struct tm *ltime;
unsigned int todays_seconds=0;
unsigned int seconds_this_morning=0;
const char *last_year, *this_year, *last_months, *last_week, *today;
const char *format;
current_time = time(NULL);
ltime = localtime(¤t_time);
todays_seconds = ltime->tm_hour*3600 + ltime->tm_min*60 + ltime->tm_sec;
seconds_this_morning = current_time - todays_seconds;
if (argc!=8) {
printf("Usage: %s last_year this_year today format timestamp\n", argv[0]);
return 2;
}
last_year = argv[1];
this_year = argv[2];
last_months = argv[3];
last_week = argv[4];
today = argv[5];
format = argv[6];
message_time = atoi(argv[7]);
/*
*if ((message_time+YEAR) < current_time) {
* printf(format, last_year);
*} else if ((message_time+MONTH) < current_time) {
* printf(format, this_year);
*} else if ((message_time+WEEK) < current_time) {
* printf(format, last_months);
*} else if ((message_time+DAY) < current_time) {
* printf(format, last_week);
*} else {
* printf(format, today);
*}
*/
if ((message_time/YEAR) < (current_time/YEAR)) {
printf(format, last_year);
} else if ((message_time/MONTH) < (current_time/MONTH)) {
printf(format, this_year);
} else if ((message_time + WEEK) < current_time) {
/*} else if ((message_time/DAY) < (current_time/DAY)) {*/
printf(format, last_months);
/*
*} else if ((message_time+DAY) < current_time) {
* printf(format, last_week);
*/
} else if ((message_time ) < seconds_this_morning) {
printf(format, last_week);
} else {
printf(format, today);
}
return 0;
}
По какой-то причине более новые версии mutt (1.7 показали эту проблему) префикс строки даты с символами '14' и '32', которые не позволяют atoi преобразовывать строка в int. Изменение строки на
message_time = atoi(2+argv[7]);
Возможно, глупое решение, но у меня оно работает.
Немного отредактирована версия @Marcus c (до сих пор нет решения для %
в теме вопроса):
// -*- coding:utf-8-unix; mode:c; -*-
/*
Sets mutt index date based on mail age.
build:
gcc mutt-index-date-formatter.c -o mutt-index-format
use this line in .muttrc:
set index_format = 'mutt-index-format "%9[%d.%m.%y]" "%9[%e.%b]" "%8[%a %H:%m]" "%[%H:%m]" "%3C [%Z] %?X?%2X& -? %%s %-20.20L %?M?+%-2M& ? %s %> [%4c]asladfg" "%[%s]" |'*/
// ////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define DAY (time_t)86400
#define WEEK (time_t)604800
#define YEAR (time_t)31556926
int main(int argc, const char *argv[]) {
time_t current_time;
time_t message_time;
struct tm *ltime;
unsigned int todays_seconds=0;
unsigned int seconds_this_morning=0;
const char *last_year, *this_year, *last_months, *last_week, *today;
const char *format;
char *concat_str;
current_time = time(NULL);
ltime = localtime(¤t_time);
todays_seconds = ltime->tm_hour*3600 + ltime->tm_min*60 + ltime->tm_sec;
seconds_this_morning = current_time - todays_seconds; // unix time @ 00:00
if (argc != 7) {
printf("Usage: %s last_year this_year last_week today format timestamp\n", argv[0]);
return 2;
}
last_year = argv[1];
this_year = argv[2];
last_week = argv[3];
today = argv[4];
format = argv[5];
message_time = atoi(2 + argv[6]);
if (message_time >= seconds_this_morning) {
asprintf(&concat_str, " %s", today);
printf(format, concat_str);
} else if (message_time >= seconds_this_morning - DAY) {
asprintf(&concat_str, "ydy %s", today);
printf(format, concat_str);
} else if (message_time > seconds_this_morning - WEEK) {
printf(format, last_week);
} else if (message_time/YEAR < current_time/YEAR) {
printf(format, last_year);
} else {
printf(format, this_year);
}
return 0;
}
Это форматирует даты следующим образом (все время в формате 24h):
02:04
для сегодняшней почтыydy 02:04
для вчерашней почтыЧт 02:04
за последние 7 дней почты27.Mar
для почты текущего года13.12.16
для почты прошлых летПолный формат индекса в этом примере — #no [флаги] #no_of_attachments даты отправителя субъект msg_size
Эта переменная index_format
set index_format='mfdate "%[%s]" "%4C %Z %[!%b %d %Y] %-17.17F (%3l) %s" |'
вместе с этим модифицированным mfdate.c
, представленным в этом ответе от пользователя hop:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define DAY (time_t)86400
#define YEAR (time_t)31556926
int main(int argc, const char *argv[]) {
time_t current_time;
time_t message_time;
const char *old = "old";
char *recent = "recent";
char *today = "today";
const char *format;
current_time = time(NULL);
if (argc != 3) {
printf("Usage: %s format\n", argv[0]);
return EXIT_FAILURE;
}
format = argv[2];
message_time = atoi(argv[1]);
if ((message_time/YEAR) < (current_time/YEAR)) {
printf("%s,%s", old, format);
} else if ((message_time/DAY) < (current_time/DAY)) {
printf("%s,%s", recent, format);
} else {
printf("%s,%s", today, format);
}
return EXIT_SUCCESS;
}
у меня корректно работает в mutt 1.6.1
и как видите проблем со знаком %
в теме нет , если это
вот в чем заключалась настоящая проблема:
Это первоначальная «просто рабочая» версия, потому что, внимательно изучив ваш первоначальный вопрос, я не уверен, что это то, что вы хотите. Однако, если это то то, что вам нужно, дайте мне знать, и мы подумаем, как сделать его лучше.
Он также может работать с вашим предпочтительным index_format
:
set index_format='mfdate "%[%s]" "%%Z %%{%%Y %%b %%e %%H:%%M} %%?X?(%%X)& ? %%-22.22F %%.100s %%> %%5c" |'
mfdate.c:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define DAY (time_t)86400
#define YEAR (time_t)31556926
int main(int argc, const char *argv[]) {
time_t current_time;
time_t message_time;
const char *old = "old";
char *recent = "recent";
char *today = "today";
const char *format;
current_time = time(NULL);
if (argc != 3) {
printf("Usage: %s format\n", argv[0]);
return EXIT_FAILURE;
}
format = argv[2];
message_time = atoi(argv[1]);
if ((message_time/YEAR) < (current_time/YEAR)) {
printf("%s,%s%%", old, format);
} else if ((message_time/DAY) < (current_time/DAY)) {
printf("%s,%s%%", recent, format);
} else {
printf("%s,%s%%", today, format);
}
return 0;
}
Позвольте мне объяснить, как это работает:
mfdate
принимает 2 аргумента:
"%[%s]"
и:
"%%Z %%{%%Y %%b %%e %%H:%%M} %%?X?(%%X)& ? %%-22.22F %%.100s %%> %%5c"
Первый аргумент только время сообщения
, как описано в
Документация index_format
в .muttrc
:
# %[fmt] the date and time of the message is converted to the local
# time zone, and ``fmt'' is expanded by the library function
# ``strftime''; a leading bang disables locales
В этом случае fmt
заменяется на %s
, поскольку %s
означает
количество секунд с начала Эпохи
, как описано в man strftime
. То
Первый аргумент используется для вычисления того, сколько лет сообщению и что
ярлык: старый
, недавний
или сегодня
должен быть.
Второй аргумент — оставшаяся часть index_format
Переменная. Он используется в mfdate
только для печати, но дополнительный %
используется
добавлено в конец printf
, потому что, как сказано в руководстве по Mutt:
Возвращаемая строка будет использоваться для отображения. Если возвращенная строка оканчивается на %, он будет пропущен через средство форматирования во второй раз.
Каждый %
удваивается здесь, потому что мы хотим передать литерал %
в
второе форматирование сделал mutt
.