mutt: formato data condizionato in "index_format"


15

Ho impostato il seguente valore per index_formatin mutt:

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

che visualizza la data nel formato come

2013 Dec 5

Mi chiedevo se fosse possibile avere diversi formati di data a seconda di quanti anni ha l'e-mail. Con ciò intendo:

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

Penso di aver visto questa funzionalità in Thunderbird. Sarebbe bello averlo in Mutt

Risposte:


16

Se stai usando la versione "sviluppo" di mutt (v1.5 +) - e assolutamente dovresti - c'è la possibilità di usare un filtro esterno come descritto nel manuale .

Innanzitutto è necessario uno script in grado di produrre cose diverse in base all'età di un messaggio. Ecco un esempio in 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))

Salvalo come mutt-fmt-dateda qualche parte sul tuo PERCORSO.

Due cose sono importanti qui:

  • La stringa di formato deve contenere un'occorrenza di {}cui viene sostituito con il valore restituito age_fmt()da Python.
  • La stringa di formato deve terminare con un in %modo che Mutt la interpreti.

Quindi puoi usarlo .muttrccome segue:

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

Mutt lo farà allora

  1. interpretare %[%s]secondo le regole per le stringhe di formato.
  2. chiama mutt-fmt-datecon il risultato di 1. come argomento (a causa della |fine).
  3. interpretare di nuovo ciò che viene restituito dallo script come stringa di formato (a causa della %fine).

Avvertenza : lo script verrà eseguito per ogni messaggio che deve essere visualizzato. Il ritardo risultante può essere abbastanza evidente quando si scorre una cassetta postale.

Ecco una versione in C che si comporta in modo abbastanza adeguato:

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

Questo va di pari passo con la linea muttrc:

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

Non ho ancora avuto il tempo di eseguire il debug di questo, ma sembra che ci sia un problema con questa soluzione e soggetti che contengono un segno%. Le patch sarebbero apprezzate!

1
Ho creato una taglia. Hai qualche idea su come risolvere il bug?
Martin Vegter,

7

Sfortunatamente, ciò non sembra essere possibile con le versioni attuali di Mutt.

$index_formatsupporta un set specifico di identificatori di formato, attingendo a vari metadati del messaggio. È descritto nel manuale di Mutt (o qui c'è la documentazione della versione "stabile" per lo stesso ), e come puoi vedere dalla tabella, ci sono solo alcuni specificatori di formato che sono condizionali. Quelli sono %M, %ye %Y; % M è il numero di messaggi nascosti se il thread è compresso e% ye% Y sono intestazioni X-Label se presenti.

Viene eseguita la formattazione effettiva della data e dell'ora del messaggio strftime(3), che non supporta affatto la formattazione condizionale.

Si potrebbe essere possibile fare una brutta soluzione riscrivendo continuamente i file di messaggio Date:intestazioni, ma non vorrei farlo, almeno. Tuttavia, è la minima possibilità che mi viene in mente.

L'unica vera soluzione a cui riesco a pensare sarebbe quella di implementare tale supporto in Mutt (che quasi certamente è il modo in cui lo fa Thunderbird), o scrivere una sostituzione strftimeche supporti la formattazione condizionale e iniettarla usando LD_PRELOAD o un meccanismo simile. Quest'ultimo, tuttavia, influirà su tutta la visualizzazione della data e dell'ora in Mutt che attraversa il periodo di lavoro, non solo relativa all'indice dei messaggi.


2
Se stai usando la versione 1.5+ (che dovresti assolutamente), c'è un modo. Suggerire di riscrivere le intestazioni delle date è divertente, però ...

@hop FWIW, la tua risposta ha ottenuto il mio voto.
un CVn

4

Per qualche motivo le versioni più recenti di mutt (1.7 hanno mostrato quel problema) hanno come prefisso la stringa della data con i caratteri '14' e '32', che impediscono a aii di convertire la stringa in un int. Modifica della linea in

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

Forse una soluzione stupida, ma funziona per me.


4

Modificato un po 'la versione c di @Marcus (comunque nessuna soluzione al %problema nell'argomento):

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

Questo formato data come segue (tutti gli orari sono in formato 24h):

  • 02:04 per la posta di oggi
  • ydy 02:04 per la posta di ieri
  • Thu 02:04 per gli ultimi 7 giorni di posta
  • 27.Mar per la posta di quest'anno
  • 13.12.16 per la posta degli anni precedenti

Il formato dell'indice completo in questo esempio è #no [flags] #no_of_attachments date sender subject msg_size


3

Ha apportato alcune modifiche, ma non ha risolto il problema "% 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;
}

Sarebbe utile se riassumessi le modifiche apportate e i motivi alla base di esse.
Zagrimsan,

0

Questa index_formatvariabile

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

insieme a questo modificato mfdate.cpresentato in questa risposta dall'utente 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;
}

funziona correttamente per me in mutt 1.6.1e come vedi non ci sono problemi con il %segno nell'oggetto, se questo è il vero problema:inserisci qui la descrizione dell'immagine

Questa è la versione iniziale "funzionante" perché dopo aver dato un'occhiata più da vicino alla tua domanda originale non sono sicuro che questo sia ciò che desideri. Tuttavia, se questo è quello che vuoi, fammi sapere e penseremo come migliorarlo.

MODIFICA :

Può anche funzionare con il tuo preferito 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;
}

inserisci qui la descrizione dell'immagine

MODIFICA :

Lasciami spiegare come funziona:

Ci mfdatevogliono 2 argomenti:

"%[%s]"

e:

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

Il primo argomento è solo time of the message, come descritto nella index_formatdocumentazione in .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

In questo caso fmtviene sostituito con %s, perché come %smezzi The number of seconds since the Epochcome spiegato in man strftime. Il primo argomento è utilizzato per calcolare quanti anni il messaggio è e ciò che l'etichetta: old, recento todaydovrebbe avere.

Il secondo argomento è la parte rimanente della index_format variabile. È usato mfdatesolo per la stampa ma %alla fine di questo viene aggiunto un extra printfperché, come dice il manuale di mutt :

La stringa restituita verrà utilizzata per la visualizzazione. Se la stringa restituita termina in%, verrà passata attraverso il formatter una seconda volta.

Tutto %è raddoppiato qui perché vogliamo passare letteralmente %alla seconda formattazione effettuata da mutt.


Perché il downvote? Qualcosa non va in questa risposta?
Arkadiusz Drabczyk,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.