NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
score.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <stdbool.h>
31 #include <stdlib.h>
32 #include "mutt/lib.h"
33 #include "config/lib.h"
34 #include "email/lib.h"
35 #include "core/lib.h"
36 #include "mutt.h"
37 #include "score.h"
38 #include "pattern/lib.h"
39 #include "init.h"
40 #include "keymap.h"
41 #include "mutt_commands.h"
42 #include "mutt_globals.h"
43 #include "mutt_menu.h"
44 #include "options.h"
45 #include "protos.h"
46 #include "sort.h"
47 
48 /* These Config Variables are only used in score.c */
52 
56 struct Score
57 {
58  char *str;
59  struct PatternList *pat;
60  int val;
61  bool exact;
62  struct Score *next;
63 };
64 
65 static struct Score *ScoreList = NULL;
66 
71 void mutt_check_rescore(struct Mailbox *m)
72 {
73  if (OptNeedRescore && C_Score)
74  {
75  if (((C_Sort & SORT_MASK) == SORT_SCORE) || ((C_SortAux & SORT_MASK) == SORT_SCORE))
76  {
77  OptNeedResort = true;
78  if ((C_Sort & SORT_MASK) == SORT_THREADS)
79  OptSortSubthreads = true;
80  }
81 
82  /* must redraw the index since the user might have %N in it */
85 
86  for (int i = 0; m && i < m->msg_count; i++)
87  {
88  struct Email *e = m->emails[i];
89  if (!e)
90  break;
91 
92  mutt_score_message(m, e, true);
93  e->pair = 0;
94  }
95  }
96  OptNeedRescore = false;
97 }
98 
102 enum CommandResult mutt_parse_score(struct Buffer *buf, struct Buffer *s,
103  intptr_t data, struct Buffer *err)
104 {
105  struct Score *ptr = NULL, *last = NULL;
106  char *pattern = NULL, *pc = NULL;
107 
109  if (!MoreArgs(s))
110  {
111  mutt_buffer_printf(err, _("%s: too few arguments"), "score");
112  return MUTT_CMD_WARNING;
113  }
114  pattern = mutt_buffer_strdup(buf);
116  if (MoreArgs(s))
117  {
118  FREE(&pattern);
119  mutt_buffer_printf(err, _("%s: too many arguments"), "score");
120  return MUTT_CMD_WARNING;
121  }
122 
123  /* look for an existing entry and update the value, else add it to the end
124  * of the list */
125  for (ptr = ScoreList, last = NULL; ptr; last = ptr, ptr = ptr->next)
126  if (mutt_str_equal(pattern, ptr->str))
127  break;
128  if (!ptr)
129  {
130  struct PatternList *pat = mutt_pattern_comp(pattern, MUTT_PC_NO_FLAGS, err);
131  if (!pat)
132  {
133  FREE(&pattern);
134  return MUTT_CMD_ERROR;
135  }
136  ptr = mutt_mem_calloc(1, sizeof(struct Score));
137  if (last)
138  last->next = ptr;
139  else
140  ScoreList = ptr;
141  ptr->pat = pat;
142  ptr->str = pattern;
143  }
144  else
145  {
146  /* 'buf' arg was cleared and 'pattern' holds the only reference;
147  * as here 'ptr' != NULL -> update the value only in which case
148  * ptr->str already has the string, so pattern should be freed. */
149  FREE(&pattern);
150  }
151  pc = buf->data;
152  if (*pc == '=')
153  {
154  ptr->exact = true;
155  pc++;
156  }
157  if (mutt_str_atoi(pc, &ptr->val) < 0)
158  {
159  FREE(&pattern);
160  mutt_buffer_strcpy(err, _("Error: score: invalid number"));
161  return MUTT_CMD_ERROR;
162  }
163  OptNeedRescore = true;
164  return MUTT_CMD_SUCCESS;
165 }
166 
173 void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
174 {
175  struct Score *tmp = NULL;
176  struct PatternCache cache = { 0 };
177 
178  e->score = 0; /* in case of re-scoring */
179  for (tmp = ScoreList; tmp; tmp = tmp->next)
180  {
181  if (mutt_pattern_exec(SLIST_FIRST(tmp->pat), MUTT_MATCH_FULL_ADDRESS, NULL, e, &cache) > 0)
182  {
183  if (tmp->exact || (tmp->val == 9999) || (tmp->val == -9999))
184  {
185  e->score = tmp->val;
186  break;
187  }
188  e->score += tmp->val;
189  }
190  }
191  if (e->score < 0)
192  e->score = 0;
193 
194  if (e->score <= C_ScoreThresholdDelete)
195  mutt_set_flag_update(m, e, MUTT_DELETE, true, upd_mbox);
196  if (e->score <= C_ScoreThresholdRead)
197  mutt_set_flag_update(m, e, MUTT_READ, true, upd_mbox);
198  if (e->score >= C_ScoreThresholdFlag)
199  mutt_set_flag_update(m, e, MUTT_FLAG, true, upd_mbox);
200 }
201 
205 enum CommandResult mutt_parse_unscore(struct Buffer *buf, struct Buffer *s,
206  intptr_t data, struct Buffer *err)
207 {
208  struct Score *tmp = NULL, *last = NULL;
209 
210  while (MoreArgs(s))
211  {
213  if (mutt_str_equal("*", buf->data))
214  {
215  for (tmp = ScoreList; tmp;)
216  {
217  last = tmp;
218  tmp = tmp->next;
219  mutt_pattern_free(&last->pat);
220  FREE(&last);
221  }
222  ScoreList = NULL;
223  }
224  else
225  {
226  for (tmp = ScoreList; tmp; last = tmp, tmp = tmp->next)
227  {
228  if (mutt_str_equal(buf->data, tmp->str))
229  {
230  if (last)
231  last->next = tmp->next;
232  else
233  ScoreList = tmp->next;
234  mutt_pattern_free(&tmp->pat);
235  FREE(&tmp);
236  /* there should only be one score per pattern, so we can stop here */
237  break;
238  }
239  }
240  }
241  }
242  OptNeedRescore = true;
243  return MUTT_CMD_SUCCESS;
244 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
Manage keymappings.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
int msg_count
Total number of messages.
Definition: mailbox.h:91
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:252
The envelope/body of an email.
Definition: email.h:37
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
Config/command parsing.
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
Structs that make up an email.
struct PatternList * pat
Definition: score.c:59
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
void mutt_check_rescore(struct Mailbox *m)
Do the emails need to have their scores recalculated?
Definition: score.c:71
WHERE bool OptNeedResort
(pseudo) used to force a re-sort
Definition: options.h:43
short C_ScoreThresholdFlag
Config: Messages with a greater score will be automatically flagged.
Definition: score.c:50
WHERE bool C_Score
Config: Use message scoring.
Definition: mutt_globals.h:159
String manipulation buffer.
Definition: buffer.h:33
void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
Apply scoring to an email.
Definition: score.c:173
Flagged messages.
Definition: mutt.h:102
#define _(a)
Definition: message.h:28
Sort by the email&#39;s score.
Definition: sort2.h:54
struct PatternList * mutt_pattern_comp(const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:1056
Index panel (list of emails)
Definition: keymap.h:80
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
WHERE bool OptNeedRescore
(pseudo) set when the &#39;score&#39; command is used
Definition: options.h:42
Convenience wrapper for the config headers.
Assorted sorting methods.
char * str
Definition: score.c:58
Pager pager (email viewer)
Definition: keymap.h:81
#define MoreArgs(buf)
Definition: buffer.h:43
enum CommandResult mutt_parse_unscore(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;unscore&#39; command - Implements Command::parse()
Definition: score.c:205
int val
Definition: score.c:60
Many unsorted constants and some structs.
Convenience wrapper for the core headers.
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:60
int score
Message score.
Definition: email.h:89
enum CommandResult mutt_parse_score(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;score&#39; command - Implements Command::parse()
Definition: score.c:102
Prototypes for many functions.
WHERE short C_SortAux
Config: Secondary sort method for the index.
Definition: sort.h:61
Sort by email threads.
Definition: sort2.h:51
#define SLIST_FIRST(head)
Definition: queue.h:228
Messages to be deleted.
Definition: mutt.h:98
A mailbox.
Definition: mailbox.h:81
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:394
#define MUTT_PC_NO_FLAGS
No flags are set.
Definition: lib.h:63
Match patterns to emails.
char * data
Pointer to data.
Definition: buffer.h:35
Messages that have been read.
Definition: mutt.h:96
Definitions of NeoMutt commands.
GUI present the user with a selectable list.
Scoring rule for email.
Definition: score.c:56
Routines for adding user scores to emails.
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: exec.c:738
Success: Command worked.
Definition: mutt_commands.h:38
Warning: Help given to the user.
Definition: mutt_commands.h:37
short C_ScoreThresholdDelete
Config: Messages with a lower score will be automatically deleted.
Definition: score.c:49
#define FREE(x)
Definition: memory.h:40
struct Score * next
Definition: score.c:62
WHERE bool OptSortSubthreads
(pseudo) used when $sort_aux changes
Definition: options.h:54
short C_ScoreThresholdRead
Config: Messages with a lower score will be automatically marked read.
Definition: score.c:51
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1004
Cache commonly-used patterns.
Definition: lib.h:108
Convenience wrapper for the library headers.
bool exact
if this rule matches, don&#39;t evaluate any more
Definition: score.c:61
void mutt_set_flag_update(struct Mailbox *m, struct Email *e, int flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition: flags.c:54
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: lib.h:98
int pair
Color-pair to use when displaying in the index.
Definition: email.h:80
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:80
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:70