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

ฉันคิดว่าฉันได้เห็นการทำงานนี้ในธันเดอร์เบิร์ด จะดีที่มีใน mutt

คำตอบ:


16

หากคุณกำลังใช้งาน "การพัฒนา" รุ่นโง่ (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
  • สตริงรูปแบบจะต้องลงท้ายด้วย%เพื่อที่ Mutt จะตีความมัน

จากนั้นคุณสามารถใช้มันในของคุณ.muttrcดังนี้:

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

โง่แล้วจะ

  1. ตีความ%[%s]ตามกฎสำหรับสตริงรูปแบบ
  2. การเรียกmutt-fmt-dateด้วยผลลัพธ์ของ 1. เป็นอาร์กิวเมนต์ (เนื่องจาก|การสิ้นสุด)
  3. ตีความสิ่งที่ได้รับกลับมาจากสคริปต์เป็นสตริงรูปแบบอีกครั้ง (เพราะ%ในตอนท้าย)

Caveat : สคริปต์จะถูกดำเนินการสำหรับทุกข้อความที่จะแสดง ความล่าช้าที่เกิดขึ้นสามารถสังเกตเห็นได้ค่อนข้างชัดเจนเมื่อเลื่อนดูในกล่องจดหมาย

นี่คือเวอร์ชันใน 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 และ% Y เป็นส่วนหัวของ X-Label ถ้ามี

การจัดรูปแบบที่แท้จริงของวันที่และเวลาของข้อความจะดำเนินการโดยstrftime(3)ซึ่งไม่สนับสนุนการจัดรูปแบบตามเงื่อนไขเลย

มันอาจจะเป็นไปได้ที่จะทำน่าเกลียดวิธีแก้ปัญหาโดยการเขียนใหม่อย่างต่อเนื่องไฟล์ข้อความDate:หัว แต่ฉันไม่ต้องการที่จะทำอย่างนั้นอย่างน้อย อย่างไรก็ตามเป็นไปได้น้อยที่สุดที่ฉันสามารถนึกได้

ทางออกที่แท้จริงเพียงอย่างเดียวที่ฉันสามารถนึกได้ก็คือการใช้การสนับสนุนเช่นนี้ใน Mutt (ซึ่งเกือบจะแน่นอนก็คือ Thunderbird ทำได้) หรือเขียนการแทนที่strftimeซึ่งรองรับการจัดรูปแบบตามเงื่อนไขและฉีดที่ใช้ LD_PRELOAD หรือกลไกที่คล้ายกัน หลัง แต่จะส่งผลกระทบต่อทุกการแสดงวันที่และเวลาในการโง่ที่จะไปผ่าน strftime ไม่เพียง แต่เกี่ยวข้องกับดัชนีข้อความ


2
หากคุณใช้เวอร์ชัน 1.5+ (ซึ่งคุณควรจริง ๆ ) ก็มีวิธี แนะนำให้เขียนส่วนหัวของวันที่ใหม่เป็นเฮฮา แต่…

@hop FWIW คำตอบของคุณทำให้ฉันสนใจ
CVn

4

ด้วยเหตุผลบางอย่างรุ่นที่ใหม่กว่าของ mutt (1.7 แสดงว่าปัญหานั้น) นำหน้าสตริงวันที่ด้วยอักขระ '14' และ '32' ซึ่งป้องกันไม่ให้ atoi แปลงสตริงเป็น 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

ทำการแก้ไขบางอย่าง แต่ไม่ได้แก้ปัญหา "% ในหัวเรื่อง"

#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" |'

พร้อมกับการแก้ไขนี้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"

อาร์กิวเมนต์แรกเป็นเพียง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สำหรับการพิมพ์เท่านั้น แต่มีการเพิ่มพิเศษ%เมื่อสิ้นสุดprintfเพราะตามที่ระบุไว้ในคู่มือ mutt :

สตริงที่ส่งคืนจะถูกใช้สำหรับการแสดงผล หากสตริงที่ส่งคืนลงท้ายด้วย% มันจะถูกส่งผ่านฟอร์แมตเตอร์เป็นครั้งที่สอง

ทุกคน%เป็นสองเท่านี่เพราะเราต้องการที่จะผ่านตัวอักษรที่สองการจัดรูปแบบทำโดย%mutt


ทำไมต้องลงคะแนน? มีอะไรผิดปกติกับคำตอบนี้ไหม
Arkadiusz Drabczyk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.