mutt :“index_format”의 조건부 날짜 형식


15

index_formatmutt에 다음 값이 설정 되어 있습니다.

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

형식으로 날짜를 표시합니다

2013 Dec 5

이메일의 나이에 따라 다른 날짜 형식을 사용할 수 있는지 궁금합니다. 그 말은 :

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

썬더 버드에서이 기능을 본 것 같습니다. 그것을 똥개로 두는 것이 좋을 것입니다

답변:


16

"개발"버전의 mutt (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-datePATH 어딘가에 저장하십시오 .

여기서 두 가지가 중요합니다.

  • 형식 문자열은 하나의 발생을 포함 {}해야하며 그 발생은 age_fmt()Python 의 반환 값으로 대체됩니다 .
  • 형식 문자열은 %Mutt가 해석 할 수 있도록 끝나야 합니다.

그런 .muttrc다음 다음과 같이 사용할 수 있습니다 .

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

그러면 Mutt는

  1. 새기다 %[%s]형식 문자열의 규칙에 따라 하십시오.
  2. 전화 mutt-fmt-date때문에의 (인수 1의 결과| 끝).
  3. 스크립트에서 다시 얻은 내용을 형식 문자열로 다시 해석하십시오 (마침표 때문에 %).

경고 : 표시 될 모든 메시지에 대해 스크립트가 실행됩니다. 사서함을 스크롤 할 때 결과 지연이 눈에 can 수 있습니다.

다음은 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]" |'

아직 디버깅 할 시간이 없었지만이 솔루션 및 % 기호가 포함 된 주제에 문제가있는 것 같습니다. 패치 감사합니다!

1
현상금을 만들었습니다. 버그 수정 방법에 대한 아이디어가 있습니까?
Martin Vegter

7

불행히도 현재 버전의 Mutt에서는 가능하지 않습니다.

$index_format다양한 메시지 메타 데이터에서 특정 형식 지정자 세트를 지원합니다. 이 매뉴얼은 Mutt 매뉴얼에 설명되어 있으며 (또는 여기에 "안정된"버전의 문서가 있습니다 ), 표에서 볼 수 있듯이 조건부로 몇 가지 형식 지정자가 있습니다. 사람들은 %M, %y그리고 %Y; % M 숨겨진 메시지의 개수 경우 Y는 X 레이블 헤더있는 스레드가 축소되고, Y 및 %의 % 만약 존재.

메시지 날짜 및 시간의 실제 형식은에 의해 수행되며 strftime(3)조건부 형식을 전혀 지원하지 않습니다.

할 수있을 추한 지속적으로 메시지 파일 '다시 작성하여 해결 방법을 Date:헤더를,하지만 난 적어도 그렇게하고 싶지 않아요. 그러나 내가 생각할 수있는 것은 최악의 가능성입니다.

내가 생각할 수있는 유일한 해결책은 Mutt에서 그러한 지원을 구현하거나 (Thunderbird가 거의 확실하게 수행하는 방식 임) strftime조건부 서식을 지원하고 LD_PRELOAD 또는 유사한 메커니즘을 사용하여이를 대체하는 대체 를 작성하는 것 입니다. 그러나 후자 는 메시지 인덱스뿐만 아니라 strftime을 거치는 Mutt의 모든 날짜 및 시간 표시에 영향을 미칩니다 .


2
1.5 이상 버전을 사용하는 경우 (절대로해야 함) 방법이 있습니다. 그래도 날짜 헤더를 다시

@hop FWIW, 귀하의 답변에 찬성했습니다.
CVn

4

어떤 이유로 최신 버전의 mutt (1.7은 문제가 있음을 나타냄)에 날짜 문자열 앞에 문자 '14'와 '32'를 붙여 문자열을 int로 변환하지 못하게합니다. 줄을 다음으로 변경

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

어리석은 해결책 일 수도 있지만 그것은 나를 위해 작동합니다.


4

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

이 형식의 날짜는 다음과 같습니다 (모든 시간은 24 시간 형식입니다).

  • 02:04 오늘의 메일
  • ydy 02:04 어제의 메일
  • Thu 02:04 지난 7 일간의 메일
  • 27.Mar 올해의 메일
  • 13.12.16 전년도 우편물

이 예에서 전체 색인 형식은 #no [flags] #no_of_attachments date sender subject msg_size


3

일부 수정했지만 "% in subject"문제를 해결하지 못했습니다

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

변경 사항과 그 이유를 요약하면 좋을 것입니다.
zagrimsan

0

index_format변수

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

이 답변 에 사용자 hop 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 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이 개 인수를 :

"%[%s]"

과:

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

첫 번째 인수는 time of the message다음 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수단 The number of seconds since the Epoch으로 대체 됩니다 man strftime. 첫 번째 인수는 얼마나 오래된 메시지가 어떤 라벨을 계산하는 데 사용됩니다 old, recent또는 today이 있어야합니다.

두 번째 인수는 index_format 변수 의 나머지 부분입니다 . mfdate인쇄에만 사용 되지만 mutt manual 에서 언급했듯이 %끝에 추가됩니다 .printf

반환 된 문자열은 표시에 사용됩니다. 반환 된 문자열이 %로 끝나면 두 번째로 포맷터를 통과합니다.

에 의해 수행되는 두 번째 형식에 %리터럴 %을 전달하려고하기 때문에 모든 것이 여기에서 두 배가 됩니다 mutt.


왜 공감해야합니까? 이 답변에 문제가 있습니까?
Arkadiusz Drabczyk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.