mutt: format tanggal bersyarat di "index_format"

15

Saya memiliki nilai yang ditetapkan untuk index_formatdi mutt:

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

yang menampilkan tanggal dalam format sebagai

2013 Dec 5

Saya bertanya-tanya apakah mungkin memiliki format tanggal yang berbeda tergantung pada usia email. Maksud saya:

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

Saya pikir saya telah melihat fungsi ini di Thunderbird. Akan menyenangkan untuk memilikinya di mutt

Martin Vegter
sumber

Jawaban:

16

Jika Anda menggunakan versi "development" dari mutt (v1.5 +) - dan Anda benar-benar harus - ada kemungkinan untuk menggunakan filter eksternal seperti yang dijelaskan dalam manual .

Pertama, Anda memerlukan skrip yang dapat menampilkan berbagai hal sesuai dengan usia pesan. Berikut ini adalah contoh dalam 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))

Simpan ini sebagai mutt-fmt-datesuatu tempat di PATH Anda.

Dua hal penting di sini:

  • String format harus mengandung satu kejadian {}yang diganti dengan nilai pengembalian age_fmt()oleh Python.
  • String format harus diakhiri dengan %sehingga Mutt akan menafsirkannya.

Maka Anda dapat menggunakannya di Anda .muttrcsebagai berikut:

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

Mutt akan melakukannya

  1. menafsirkan %[%s]sesuai dengan aturan untuk format string.
  2. panggilan mutt-fmt-datedengan hasil 1. sebagai argumen (karena |di bagian akhir).
  3. menafsirkan apa yang didapatnya dari skrip sebagai format string lagi (karena %di bagian akhir).

Peringatan : skrip akan dieksekusi untuk setiap pesan yang akan ditampilkan. Penundaan yang dihasilkan bisa sangat terlihat ketika menggulir kotak surat.

Berikut adalah versi dalam C yang berkinerja cukup memadai:

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

Ini sejalan dengan baris muttrc:

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

sumber
Saya belum punya waktu untuk men-debug ini, tetapi tampaknya ada masalah dengan solusi ini dan subjek yang berisi tanda%. Tambalan akan dihargai!
1
Saya telah membuat hadiah. Apakah Anda punya ide bagaimana cara memperbaiki bug?
Martin Vegter
7

Sayangnya, itu tampaknya tidak mungkin dilakukan dengan versi Mutt saat ini.

$index_formatmendukung satu set spesifik penentu format, menggambar dari berbagai metadata pesan. Ini dijelaskan dalam manual Mutt (atau di sini adalah dokumentasi versi "stable" untuk hal yang sama ), dan seperti yang Anda lihat dari tabel, hanya ada beberapa penentu format yang bersyarat. Yaitu %M, %ydan %Y; % M adalah jumlah pesan tersembunyi jika utasnya diciutkan, dan% y dan% Y adalah header X-Label jika ada.

Pemformatan aktual dari tanggal dan waktu pesan dilakukan oleh strftime(3), yang sama sekali tidak mendukung pemformatan bersyarat.

Ini mungkin menjadi mungkin untuk melakukan jelek solusi dengan terus menulis ulang file pesan Date:header, tapi saya tidak ingin melakukan itu setidaknya. Namun, itu adalah kemungkinan terburuk yang bisa saya pikirkan.

Satu-satunya solusi nyata yang dapat saya pikirkan adalah mengimplementasikan dukungan semacam itu di Mutt (yang hampir pasti adalah bagaimana Thunderbird melakukannya), atau menulis pengganti strftimeyang mendukung pemformatan bersyarat dan menyuntikkan yang menggunakan LD_PRELOAD atau mekanisme serupa. Yang terakhir, bagaimanapun, akan memengaruhi semua tampilan tanggal dan waktu dalam Mutt yang melewati strftime, tidak hanya terkait dengan indeks pesan.

sebuah CVn
sumber
2
Jika Anda menggunakan versi 1.5+ (yang memang harus Anda lakukan), ada caranya. Menyarankan penulisan ulang header tanggal itu lucu, meskipun ...
@hop FWIW, jawaban Anda mendapatkan jawaban saya.
CVn
4

Untuk beberapa alasan, versi mutt yang lebih baru (1,7 menunjukkan masalah itu) awali string tanggal dengan karakter '14' dan '32', yang mencegah atoi dari mengonversi string ke int. Mengubah jalur ke

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

Mungkin solusi yang bodoh, tetapi itu berhasil untuk saya.

Marcus H
sumber
4

Versi c @Marcus yang sudah diedit sedikit (masih belum ada solusi untuk %masalah pokoknya ):

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

Format ini tanggal sebagai berikut (sepanjang waktu dalam format 24 jam):

  • 02:04 untuk surat hari ini
  • ydy 02:04 untuk surat kemarin
  • Thu 02:04 untuk email 7 hari terakhir
  • 27.Mar untuk surat tahun ini
  • 13.12.16 untuk surat tahun sebelumnya

Format indeks lengkap dalam contoh ini adalah #no [flags] #no_of_attachments date sender subject msg_size

laur
sumber
3

Membuat beberapa modifikasi, tetapi tidak menyelesaikan masalah "% dalam subjek"

#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;
}
Marcus H
sumber
Akan lebih baik jika Anda merangkum perubahan yang Anda buat dan alasan di baliknya.
zagrimsan
0

index_formatVariabel ini

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

bersama-sama dengan ini diubah mfdate.cdisajikan dalam jawaban ini oleh pengguna 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;
}

berfungsi dengan benar untuk saya mutt 1.6.1dan seperti yang Anda lihat tidak ada masalah dengan %masuknya subjek, jika ini yang menjadi masalah sebenarnya:masukkan deskripsi gambar di sini

Ini adalah versi "hanya berfungsi" awal karena setelah melihat lebih dekat pertanyaan awal Anda , saya tidak yakin apakah ini yang Anda inginkan. Namun, jika ini adalah apa yang Anda inginkan beritahu saya dan kami akan berpikir bagaimana membuatnya lebih baik.

EDIT :

Ini juga dapat bekerja dengan pilihan Anda 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;
}

masukkan deskripsi gambar di sini

EDIT :

Biarkan saya jelaskan cara kerjanya:

The mfdatemengambil 2 argumen:

"%[%s]"

dan:

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

Argumen pertama hanya time of the message, seperti yang dijelaskan dalam index_formatdokumentasi di .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

Dalam hal ini fmtdiganti dengan %s, karena sebagai %ssarana The number of seconds since the Epochseperti yang dijelaskan dalam man strftime. Argumen pertama digunakan untuk menghitung berapa lama pesan dan apa label: old, recentatau todayseharusnya.

Argumen kedua adalah bagian yang tersisa dari index_format variabel. Ini digunakan mfdatehanya untuk mencetak tetapi tambahan %ditambahkan pada akhir printfkarena seperti yang tertulis dalam manual mutt :

String yang dikembalikan akan digunakan untuk tampilan. Jika string yang dikembalikan berakhir dalam%, itu akan melewati formatter untuk kedua kalinya.

Setiap %digandakan di sini karena kami ingin meneruskan literal %ke pemformatan kedua yang dilakukan oleh mutt.

Arkadiusz Drabczyk
sumber
Mengapa downvote? Ada yang salah dengan jawaban ini?
Arkadiusz Drabczyk