# libhelp
@if USE_DEVEL_HELP
LIBHELP= libhelp.a
-LIBHELPOBJS= help/help.o help/vector.o
+LIBHELPOBJS= help/help.o help/scan.o help/vector.o
CLEANFILES+= $(LIBHELP) $(LIBHELPOBJS)
MUTTLIBS+= $(LIBHELP)
ALLOBJS+= $(LIBHELPOBJS)
#include "config.h"
#include <stddef.h>
#include <errno.h>
-#include <ftw.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <unistd.h>
#include "mutt/mutt.h"
#include "address/lib.h"
-#include "config/lib.h"
-#include "core/lib.h"
#include "email/lib.h"
#include "help.h"
+#include "core/lib.h"
#include "globals.h"
#include "mutt_header.h"
#include "mutt_thread.h"
#include "muttlib.h"
#include "mx.h"
+#include "scan.h"
#include "vector.h"
struct stat;
mutt_list_insert_tail(&source->env->references, mutt_str_strdup(tgt_msgid));
}
-/**
- * help_add_to_list - Callback for nftw whenever a file is read
- * @param fpath Filename
- * @param sb Timestamp for the file
- * @param tflag File type
- * @param ftwbuf Private nftw data
- *
- * @sa https://linux.die.net/man/3/nftw
- *
- * @note Only act on file
- */
-static int help_add_to_list(const char *fpath, const struct stat *sb, int tflag,
- struct FTW *ftwbuf)
-{
- mutt_debug(1, "entering add_to_list: '%s'\n", fpath);
- if (tflag == FTW_F)
- help_doc_gather(&DocList, fpath);
-
- return 0; /* To tell nftw() to continue */
-}
-
/**
* help_read_dir - Read a directory and process its entries recursively using nftw to
* find and link all help documents
{
mutt_debug(1, "entering help_read_dir: '%s'\n", path);
- // Max of 20 open file handles, 0 flags
- if (nftw(path, help_add_to_list, 20, 0) == -1)
+ struct Vector *file_paths = scan_dir(path);
+
+ for (size_t i = 0; i < file_paths->size; i++)
{
- perror("nftw");
- return 1;
+ char *path2 = vector_get(file_paths, i, NULL);
+ help_doc_gather(&DocList, path2);
}
/* Sort 'index.md' in list to the top */
vector_sort(DocList, help_doc_type_cmp);
}
/* mark all but the first email as read */
- m->emails[0]->read = false;
- for (size_t i = 1; i < m->msg_count; i++)
+ for (size_t i = 0; i < m->msg_count; i++)
{
- m->emails[i]->read = true;
+ m->emails[i]->read = false;
}
m->msg_unread = m->msg_count;
*/
int help_ac_add(struct Account *a, struct Mailbox *m)
{
- if (!a || !m)
- return -1;
-
- if (m->magic != MUTT_HELP)
+ if (!a || !m || (m->magic != MUTT_HELP))
return -1;
-
- m->account = a;
-
- struct MailboxNode *np = mutt_mem_calloc(1, sizeof(*np));
- np->mailbox = m;
- STAILQ_INSERT_TAIL(&a->mailboxes, np, entries);
return 0;
}
#ifndef MUTT_HELP_HELP_H
#define MUTT_HELP_HELP_H
-#include <stddef.h>
#include <stdint.h>
#include "mx.h"
-#include "vector.h"
extern struct MxOps MxHelpOps;
#define HELP_DOC_SECTION (1 << 4) ///< Document is treated as help section
/**
- * struct helpfile_header - Describes the header of a help file
+ * struct HelpFileHeader - Describes the header of a help file
*/
struct HelpFileHeader
{
- char *key;
- char *val;
+ char *key; ///< Name of header
+ char *val; ///< Value of header
};
/**
};
void help_doclist_free(void);
-int help_doclist_init(void);
+int help_doclist_init(void);
#endif /* MUTT_HELP_HELP_H */
--- /dev/null
+/**
+ * @file
+ * Scan a directory with nftw
+ *
+ * @authors
+ * Copyright (C) 2019 Tran Manh Tu <xxlaguna93@gmail.com>
+ *
+ * @copyright
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ftw.h>
+#include <string.h>
+#include <stdio.h>
+#include "mutt/mutt.h"
+#include "scan.h"
+#include "vector.h"
+
+struct stat;
+
+static struct Vector *DocPaths; ///< All valid help documents within $help_doc_dir folder
+
+/**
+ * add_file - Callback for nftw whenever a file is read
+ * @param fpath Filename
+ * @param sb Timestamp for the file
+ * @param tflag File type
+ * @param ftwbuf Private nftw data
+ *
+ * @sa https://linux.die.net/man/3/nftw
+ *
+ * @note Only act on file
+ */
+static int add_file(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf)
+{
+ if (tflag == FTW_F)
+ {
+ char *ext = strrchr(fpath, '.');
+ char *path = mutt_str_strdup(fpath);
+ if (ext && !mutt_str_strcmp(ext, ".md"))
+ {
+ vector_new_append(&DocPaths, sizeof(char *), path);
+ }
+ }
+ return 0; /* To tell nftw() to continue */
+}
+
+/**
+ * scan_dir - Scan a directory recursively using nftw to
+ * find all paths to .md files
+ * @param path absolute path of a directory
+ */
+struct Vector *scan_dir(const char *path)
+{
+ vector_free(&DocPaths, NULL);
+ DocPaths = vector_new(sizeof(char *));
+ // Max of 20 open file handles, 0 flags
+ if (nftw(path, add_file, 20, 0) == -1)
+ {
+ perror("nftw");
+ }
+
+ return DocPaths;
+}
--- /dev/null
+/**
+ * @file
+ * Scan a directory with nftw
+ *
+ * @authors
+ * Copyright (C) 2019 Tran Manh Tu <xxlaguna93@gmail.com>
+ *
+ * @copyright
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUTT_HELP_SCAN_H
+#define MUTT_HELP_SCAN_H
+
+struct Vector *scan_dir(const char *path);
+
+#endif /* MUTT_HELP_SCAN_H */
#include <stdio.h>
#include <stdlib.h>
-#include "vector.h"
#include "mutt/mutt.h"
+#include "vector.h"
+
+#define VECTOR_INIT_CAPACITY 16
/**
- * vector_free - Free a list of Help documents
- * @param list List to free
- * @param item_free Function to free the list contents
+ * vector_free - Free a Vector
+ * @param v Vector to free
+ * @param item_free Function to free the Vector's contents
*/
-void vector_free(struct Vector **list, void (*item_free)(void **))
+void vector_free(struct Vector **v, vector_item_free_t item_free)
{
- if (!list || !*list)
+ if (!v || !*v)
return;
- for (size_t i = 0; i < (*list)->size; i++)
+ for (size_t i = 0; i < (*v)->size; i++)
{
- item_free(&((*list)->data[i]));
+ item_free(&((*v)->data[i]));
}
- FREE(&(*list)->data);
- FREE(list);
+ FREE(&(*v)->data);
+ FREE(v);
}
/**
- * vector_shrink - Resize a List of Help documents to save space
- * @param list List to resize
+ * vector_shrink - Resize a Vector to save space
+ * @param v Vector to resize
*/
-void vector_shrink(struct Vector *list)
+void vector_shrink(struct Vector *v)
{
- if (!list)
+ if (!v)
return;
- mutt_mem_realloc(list->data, list->size * list->item_size);
- list->capa = list->size;
+ mutt_mem_realloc(v->data, v->size * v->item_size);
+ v->capa = v->size;
}
/**
- * vector_new - Create a new list of Help documents
- * @param item_size Size of items in list
- * @retval ptr New Help list
+ * vector_new - Create a new Vector
+ * @param item_size Size of items in Vector
+ * @retval ptr New Vector
*/
struct Vector *vector_new(size_t item_size)
{
- struct Vector *list = NULL;
+ struct Vector *v = NULL;
if (item_size == 0)
return NULL;
- list = mutt_mem_malloc(sizeof(struct Vector));
- list->item_size = item_size;
- list->size = 0;
- list->capa = VECTOR_INIT_CAPACITY;
- list->data = mutt_mem_calloc(list->capa, sizeof(void *) * list->item_size);
+ v = mutt_mem_malloc(sizeof(struct Vector));
+ v->item_size = item_size;
+ v->size = 0;
+ v->capa = VECTOR_INIT_CAPACITY;
+ v->data = mutt_mem_calloc(v->capa, sizeof(void *) * v->item_size);
- return list;
+ return v;
}
/**
- * vector_append - Add an item to the Help document list
- * @param list List to add to
+ * vector_append - Add an item to the Vector
+ * @param v Vector to add to
* @param item Item to add
*/
-void vector_append(struct Vector *list, void *item)
+void vector_append(struct Vector *v, void *item)
{
- if (!list || !item)
+ if (!v || !item)
return;
- if (list->size >= list->capa)
+ if (v->size >= v->capa)
{
- list->capa = (list->capa == 0) ? VECTOR_INIT_CAPACITY : (list->capa * 2);
- mutt_mem_realloc(list->data, list->capa * list->item_size);
+ v->capa = (v->capa == 0) ? VECTOR_INIT_CAPACITY : (v->capa * 2);
+ mutt_mem_realloc(v->data, v->capa * v->item_size);
}
- list->data[list->size] = mutt_mem_calloc(1, list->item_size);
- list->data[list->size] = item;
- list->size++;
+ v->data[v->size] = mutt_mem_calloc(1, v->item_size);
+ v->data[v->size] = item;
+ v->size++;
}
/**
- * vector_new_append - Append a new item to a Help document list
- * @param list List to append to
+ * vector_new_append - Append a new item to a Vector
+ * @param v Vector to append to
* @param item_size Size of item to add
- * @param item Item to add to list
+ * @param item Item to add to Vector
*/
-void vector_new_append(struct Vector **list, size_t item_size, void *item)
+void vector_new_append(struct Vector **v, size_t item_size, void *item)
{
if ((item_size == 0) || !item)
return;
- if (!list || !*list)
- *list = vector_new(item_size);
+ if (!v || !*v)
+ *v = vector_new(item_size);
- vector_append(*list, item);
+ vector_append(*v, item);
}
-
/**
- * vector_get - Get an item from a Help document list
- * @param list List to use
- * @param index Index in list
+ * vector_get - Get an item from a Vector
+ * @param v Vector to use
+ * @param index Index in Vector
* @param copy Function to copy item (may be NULL)
* @retval ptr Item selected
* @retval NULL Invalid index
*/
-void *vector_get(struct Vector *list, size_t index, void *(*copy)(const void *) )
+void *vector_get(struct Vector *v, size_t index, vector_item_copy_t copy)
{
- if (!list || (index >= list->size))
+ if (!v || (index >= v->size))
return NULL;
- return ((copy) ? copy(list->data[index]) : list->data[index]);
+ return ((copy) ? copy(v->data[index]) : v->data[index]);
}
/**
- * vector_clone - Copy a list of Help documents
- * @param list List to copy
- * @param shrink true if the list should be minimised
- * @param copy Function to copy a list item
- * @retval ptr Duplicated list of Help documents
+ * vector_clone - Copy a Vector
+ * @param v Vector to copy
+ * @param shrink true if the Vector should be minimised
+ * @param copy Function to copy a Vector item
+ * @retval ptr Duplicated Vector
*/
-struct Vector *vector_clone(struct Vector *list, bool shrink, void *(*copy)(const void *) )
+struct Vector *vector_clone(struct Vector *v, bool shrink, vector_item_copy_t copy)
{
- if (!list)
+ if (!v)
return NULL;
- struct Vector *clone = vector_new(list->item_size);
- for (size_t i = 0; i < list->size; i++)
- vector_append(clone, vector_get(list, i, copy));
+ struct Vector *clone = vector_new(v->item_size);
+ for (size_t i = 0; i < v->size; i++)
+ vector_append(clone, vector_get(v, i, copy));
if (shrink)
vector_shrink(clone);
}
/**
- * vector_sort - Sort a list of Help documents
- * @param list List to sort
+ * vector_sort - Sort a Vector
+ * @param v Vector to sort
* @param compare Function to compare two items
*/
-void vector_sort(struct Vector *list, int (*compare)(const void *, const void *))
+void vector_sort(struct Vector *v, int (*compare)(const void *, const void *))
{
- if (!list)
+ if (!v)
return;
- qsort(list->data, list->size, sizeof(void *), compare);
+ qsort(v->data, v->size, sizeof(void *), compare);
}
*/
#include <stdbool.h>
+#include <stddef.h>
#ifndef MUTT_HELP_VECTOR_H
#define MUTT_HELP_VECTOR_H
-#define VECTOR_INIT_CAPACITY 16
-
/**
* struct Vector - Generic array to hold several elements
*/
struct Vector
{
size_t item_size; ///< Size of a single element
- size_t size; ///< List length
- size_t capa; ///< List capacity
- void **data; ///< Internal list data pointers
+ size_t size; ///< Vector length
+ size_t capa; ///< Vector capacity
+ void **data; ///< Internal Vector data pointers
};
-void vector_append (struct Vector *list, void *item);
-struct Vector *vector_clone (struct Vector *list, bool shrink, void *(*copy)(const void *));
-void vector_free (struct Vector **list, void (*item_free)(void **));
-void * vector_get (struct Vector *list, size_t index, void *(*copy)(const void *));
+/**
+ * typedef vector_item_free_t - Custom function to free a Vector item
+ * @param ptr Vector item to be freed
+ */
+typedef void (*vector_item_free_t)(void **ptr);
+
+/**
+ * typedef vector_item_copy_t - Custom function to duplicate a Vector item
+ * @param item Vector item to be copied
+ * @retval ptr New copy of Vector item
+ */
+typedef void *(*vector_item_copy_t)(const void *item);
+
+void vector_append (struct Vector *v, void *item);
+struct Vector *vector_clone (struct Vector *v, bool shrink, vector_item_copy_t copy);
+void vector_free (struct Vector **v, vector_item_free_t item_free);
+void * vector_get (struct Vector *v, size_t index, vector_item_copy_t copy);
struct Vector *vector_new (size_t item_size);
-void vector_new_append(struct Vector **list, size_t item_size, void *item);
-void vector_shrink (struct Vector *list);
-void vector_sort (struct Vector *list, int (*compare)(const void *, const void *));
+void vector_new_append(struct Vector **v, size_t item_size, void *item);
+void vector_shrink (struct Vector *v);
+void vector_sort (struct Vector *v, int (*compare)(const void *, const void *));
#endif /* MUTT_HELP_VECTOR_H */