mutt: định dạng ngày có điều kiện trong Index index_format '


14

Tôi có giá trị được đặt sau index_formattrong mutt:

"%Z %{%Y %b %e  %H:%M} %?X?(%X)&   ? %-22.22F  %.100s %> %5c "

Hiển thị ngày ở định dạng như

2013 Dec 5

Tôi đã tự hỏi liệu có thể có các định dạng ngày khác nhau tùy thuộc vào độ tuổi của email. Ý tôi là

for less than 7 days:  today, yesterday, tuesday, monday
this year:             Dec 5
older than this year:  2013 Dec 5

Tôi nghĩ rằng tôi đã thấy chức năng này trong Thunderbird. Sẽ rất tốt nếu có nó trong mutt

Câu trả lời:


16

Nếu bạn đang sử dụng phiên bản "phát triển" của mutt (v1.5 +) - và bạn hoàn toàn nên - có khả năng sử dụng bộ lọc ngoài như được mô tả trong hướng dẫn .

Trước tiên, bạn cần một tập lệnh có thể xuất ra những thứ khác nhau tùy theo tuổi của tin nhắn. Đây là một ví dụ trong 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))

Lưu cái này làm mutt-fmt-date một nơi nào đó trên ĐƯỜNG của bạn.

Hai điều quan trọng ở đây:

  • Chuỗi định dạng phải chứa một lần {}được thay thế bằng giá trị trả về của age_fmt()Python.
  • Chuỗi định dạng phải kết thúc bằng một %để Mutt sẽ giải thích nó.

Sau đó, bạn có thể sử dụng nó trong của bạn .muttrcnhư sau:

set index_format="mutt-fmt-date %[%s] |"

Mutt sẽ

  1. giải thích %[%s]theo các quy tắc cho chuỗi định dạng.
  2. gọi mutt-fmt-datevới kết quả là 1. làm đối số (vì |ở cuối).
  3. diễn giải những gì nó nhận được từ tập lệnh dưới dạng chuỗi định dạng một lần nữa (vì %ở cuối).

Hãy cẩn thận : tập lệnh sẽ được thực thi cho mọi thông báo sắp được hiển thị. Độ trễ kết quả có thể khá đáng chú ý khi cuộn qua hộp thư.

Đây là một phiên bản trong C thực hiện phần nào đầy đủ:

#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;
}

Điều này đi cùng với dòng muttrc:

set index_format='mfdate "%[%d.%m.%y]" "%8[%e. %b]" "%8[%H:%m]" "%Z %%s %-20.20L %?y?[%-5.5y]&       ? %?M?+& ?%s%%" "%[%s]" |'

Tôi chưa có thời gian để gỡ lỗi này, nhưng dường như có vấn đề với giải pháp này và các chủ đề có chứa dấu%. Các bản vá sẽ được đánh giá cao!

1
Tôi đã tạo ra một tiền thưởng. Bạn có bất cứ ý tưởng làm thế nào để sửa lỗi?
Martin Vegter

7

Thật không may, điều đó dường như không thể xảy ra với các phiên bản hiện tại của Mutt.

$index_formathỗ trợ một bộ xác định định dạng cụ thể, rút ​​ra từ các siêu dữ liệu thông báo khác nhau. Nó được mô tả trong hướng dẫn sử dụng Mutt (hoặc đây là tài liệu của phiên bản "ổn định" ) và như bạn có thể thấy trong bảng, chỉ có một vài chỉ định định dạng có điều kiện. Đó là %M, %y%Y; % M là số lượng tin nhắn ẩn nếu luồng bị thu gọn và% y và% Y là các tiêu đề X-Label nếu có.

Định dạng thực tế của ngày và thời gian tin nhắn được thực hiện bởi strftime(3) , không hỗ trợ định dạng có điều kiện nào cả.

thể có một cách giải quyết xấu xí bằng cách liên tục viết lại các tệp tin 'Date: tiêu đề , nhưng tôi sẽ không muốn làm điều đó ít nhất. Tuy nhiên, đó là khả năng xấu nhất mà tôi có thể nghĩ đến.

Giải pháp thực sự duy nhất tôi có thể nghĩ đến là triển khai hỗ trợ như vậy trong Mutt (gần như chắc chắn là cách Thunderbird thực hiện) hoặc viết một thay thế strftimehỗ trợ định dạng có điều kiện và tiêm bằng cách sử dụng LD_PRELOAD hoặc một cơ chế tương tự. Tuy nhiên, cái sau sẽ ảnh hưởng đến tất cả hiển thị ngày và thời gian trong Mutt đi qua các tầng, không chỉ liên quan đến chỉ mục tin nhắn.


2
Nếu bạn đang sử dụng phiên bản 1.5+ (mà bạn hoàn toàn nên), có một cách. Đề xuất viết lại các tiêu đề ngày rất vui nhộn, mặc dù vậy

@hop FWIW, câu trả lời của bạn có upvote của tôi.
một CVn

4

Vì một số lý do, các phiên bản mới hơn của mutt (1.7 cho thấy vấn đề đó) tiền tố chuỗi ngày với các ký tự '14' và '32', khiến cho atoi không chuyển đổi chuỗi thành int. Thay đổi dòng thành

message_time = atoi(2+argv[7]);

Có thể là một giải pháp ngu ngốc, nhưng nó hiệu quả với tôi.


4

Đã chỉnh sửa phiên bản c của @Marcus một chút (vẫn chưa có giải pháp cho %vấn đề trong chủ đề):

// -*- 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(&current_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;
}

Định dạng này ngày như sau (tất cả thời gian ở định dạng 24h):

  • 02:04 cho thư ngày hôm nay
  • ydy 02:04 cho thư ngày hôm qua
  • Thu 02:04 trong 7 ngày qua thư
  • 27.Mar cho thư năm nay
  • 13.12.16 cho thư của năm trước

Định dạng chỉ mục đầy đủ trong ví dụ này là #no [flags] #no_of_attachments date sender subject msg_size


3

Đã thực hiện một số sửa đổi, nhưng không giải quyết được vấn đề "% trong chủ đề"

#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(&current_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;
}

Sẽ tốt hơn nếu bạn tóm tắt những thay đổi bạn đã thực hiện và lý do đằng sau chúng.
zagrimsan

0

index_formatBiến này

set index_format='mfdate "%[%s]" "%4C %Z %[!%b %d %Y] %-17.17F (%3l) %s" |'

cùng với sửa đổi này được mfdate.ctrình bày trong câu trả lời này bởi người dùng 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;
}

hoạt động chính xác cho tôi mutt 1.6.1và như bạn thấy không có vấn đề gì với việc %đăng nhập vào chủ đề, nếu đây là vấn đề thực sự xảy ra:nhập mô tả hình ảnh ở đây

Đây là phiên bản "chỉ hoạt động" ban đầu bởi vì sau khi xem xét kỹ hơn câu hỏi ban đầu của bạn, tôi không chắc đây có phải là điều bạn muốn không. Tuy nhiên, nếu đây những gì bạn muốn cho tôi biết và chúng tôi sẽ nghĩ làm thế nào để làm cho nó tốt hơn.

CHỈNH SỬA :

Nó cũng có thể làm việc với sở thích của bạn 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;
}

nhập mô tả hình ảnh ở đây

CHỈNH SỬA :

Hãy để tôi giải thích cách nó hoạt động:

mfdate2 đối số:

"%[%s]"

và:

"%%Z %%{%%Y %%b %%e  %%H:%%M} %%?X?(%%X)&   ? %%-22.22F  %%.100s %%> %%5c"

Đối số đầu tiên là duy nhất time of the message, như được mô tả trong index_formattài liệu trong .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

Trong trường hợp fmtnày được thay thế bằng %s, vì như %slà phương tiện The number of seconds since the Epochnhư được giải thích trong man strftime. Đối số đầu tiên được sử dụng để tính toán bao nhiêu tuổi được thông báo và những gì label: old, recenthoặctoday nó nên có.

Đối số thứ hai là phần còn lại của index_format biến. Nó chỉ được sử dụng mfdateđể in nhưng một phần bổ sung %được thêm vào cuối printfbởi vì như trong hướng dẫn sử dụng mutt :

Chuỗi trả về sẽ được sử dụng để hiển thị. Nếu chuỗi trả về kết thúc bằng%, nó sẽ được chuyển qua bộ định dạng lần thứ hai.

Mỗi cái %được nhân đôi ở đây vì chúng tôi muốn chuyển một nghĩa đen %sang định dạng thứ hai được thực hiện bởi mutt.


Tại sao các downvote? Có gì sai với câu trả lời này?
Arkadiusz Drabchot
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.