Skip to content

Commit

Permalink
link-parser: Add minimal XDG base directory support
Browse files Browse the repository at this point in the history
  • Loading branch information
ampli committed May 24, 2024
1 parent bec0e8f commit 0bcaf23
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 7 deletions.
39 changes: 36 additions & 3 deletions link-parser/lg_readline.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#include "command-line.h"
#include "parser-utilities.h"
#include "lg_xdg.h"

extern Switch default_switches[];
static const Switch **sorted_names; /* sorted command names */
Expand All @@ -48,6 +49,38 @@ static wchar_t * prompt(EditLine *el)
return wc_prompt;
}

// lg_readline()is called via a chain of functions:
// fget_input_string -> get_line -> get_terminal_line -> lg_readline.
// To avoid changing all of them, this variable is static for now.
// FIXME: Move the call of find_history_filepath() to lg_readline(), and
// implement one of these:
// 1. Add the dictionary, argv[0] and prog to the call of each function.
// 2. Option 1 is cumbersome since the first 3 functions have numerous
// arguments. So replace them with a new struct "io_params".
static const char *history_file;

static const char history_file_basename[] = "lg_history";

void find_history_filepath(const char *dictname, const char *argv0,
const char *prog)
{
const char *xdg_prog = xdg_get_program_name(argv0);
if (NULL == xdg_prog) xdg_prog = prog;

// Find the location of the history file.
const char *hfile =
xdg_make_path(XDG_BD_STATE, "%s/%s", xdg_prog, history_file_basename);
if (NULL == hfile)
{
prt_error("Warning: xdg_get_home(XDG_BD_STATE) failed - "
"history file will be in the current directory\n");
history_file = strdup("dev/null");
return;
}

history_file = hfile;
}

/**
* Try to complete the wide string in \p input, whose length is \p len.
*
Expand Down Expand Up @@ -372,7 +405,6 @@ char *lg_readline(const char *mb_prompt)

if (!is_init)
{
#define HFILE ".lg_history"
is_init = true;

size_t sz = mbstowcs(NULL, mb_prompt, 0) + 4;
Expand All @@ -384,7 +416,7 @@ char *lg_readline(const char *mb_prompt)
history_w(hist, &ev, H_SETSIZE, 100);
history_w(hist, &ev, H_SETUNIQUE, 1);
el_wset(el, EL_HIST, history_w, hist);
history_w(hist, &ev, H_LOAD, HFILE);
history_w(hist, &ev, H_LOAD, history_file);

el_set(el, EL_SIGNAL, 1); /* Restore tty setting on returning to shell */

Expand All @@ -410,6 +442,7 @@ char *lg_readline(const char *mb_prompt)
{
el_end(el);
history_wend(hist);
free((void *)history_file);
free(wc_prompt);
wc_prompt = NULL;
hist = NULL;
Expand All @@ -421,7 +454,7 @@ char *lg_readline(const char *mb_prompt)
if (1 < numc)
{
history_w(hist, &ev, H_ENTER, wc_line);
history_w(hist, &ev, H_SAVE, HFILE);
history_w(hist, &ev, H_SAVE, history_file);
}
/* fwprintf(stderr, L"==> got %d %ls", numc, wc_line); */

Expand Down
27 changes: 27 additions & 0 deletions link-parser/lg_xdg.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ static bool make_dirpath(const char *path)
// Skip Windows UNC path \\X
if (is_sep(dir[0]) && is_sep(dir[1]))
{
const char *p;

// Start from the root or network share
for (p = dir + 2; *p != '\0'; p++)
if (is_sep(*p)) break;
Expand All @@ -103,6 +105,7 @@ static bool make_dirpath(const char *path)
char sep = *p;
if (is_sep(*p))
{
if (is_sep(p[-1])) continue; // Ignore directory separator sequences
*p = '\0'; // Now dir is the path up to this point
//prt_error("DEBUG: mkdir: '%s'\n", dir);
mkdir(dir, S_IRWXU); // Try to create the directory
Expand All @@ -120,6 +123,12 @@ static bool make_dirpath(const char *path)
return true;
}

/**
* @brief Get the home directory for the given XDG base directory type.
*
* @param bd_type The XDG base directory type.
* @return const char* The home directory path (freed by caller).
*/
const char *xdg_get_home(xdg_basedir_type bd_type)
{
const char *def_suffix = xdg_def[bd_type].rel_path;
Expand Down Expand Up @@ -165,6 +174,12 @@ const char *xdg_get_home(xdg_basedir_type bd_type)
return def_dir;
}

/**
* @brief Get the program name from the provided path.
*
* @param argv0 The path to the executable.
* @return const char* The program name.
*/
const char *xdg_get_program_name(const char *argv0)
{
if ((NULL == argv0) || ('\0' == argv0[0])) return NULL;
Expand All @@ -178,10 +193,22 @@ const char *xdg_get_program_name(const char *argv0)
return basename;
}


/**
* @brief Construct a full path within the specified XDG base directory.
*
* @param bd_type The XDG base directory type.
* @param fmt The format string for the path.
* @param ... Additional arguments for the format string.
* @return const char* The constructed full path (freed by caller).
*/

const char *xdg_make_path(xdg_basedir_type bd_typec, const char *fmt, ...)
{
const char *xdg_home = xdg_get_home(bd_typec);

if (NULL == xdg_home) return NULL;

char *xdg_fmt;
asprintf(&xdg_fmt, "%s/%s", xdg_home, fmt);

Expand Down
5 changes: 5 additions & 0 deletions link-parser/link-parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

#include "parser-utilities.h"
#include "command-line.h"
#include "lg_readline.h" // find_history_file

#define DISPLAY_MAX 1024

Expand All @@ -62,6 +63,7 @@ static char * debug = (char *)"";
static char * test = (char *)"";
static bool isatty_io; /* Both input and output are tty. */

static const char prog[] = "link-parser"; // If cannot obtain the program name
static const char prompt[] = "linkparser> ";
static const char *use_prompt(int verbosity_level)
{
Expand Down Expand Up @@ -698,6 +700,9 @@ int main(int argc, char * argv[])
linkgrammar_get_version());
}

if (isatty_io)
find_history_filepath(dictionary_get_lang(dict), argv[0], prog);

/* Main input loop */
while (true)
{
Expand Down
4 changes: 2 additions & 2 deletions link-parser/parser-utilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ int __mingw_vprintf (const char * __restrict__ fmt, va_list vl)
#endif /* __MINGW32__ */

#if !HAVE_ASPRINTF
int vasprintf(char ** __restrict__ buf, const char * __restrict__ fmt, va_list vl)
int vasprintf(char ** restrict buf, const char * restrict fmt, va_list vl)
{
int n = vsnprintf(NULL, 0, fmt, vl);
if (0 > n) return n;
Expand All @@ -609,7 +609,7 @@ int vasprintf(char ** __restrict__ buf, const char * __restrict__ fmt, va_list v
return n;
}

int asprintf(char ** __restrict__ buf, const char * __restrict__ fmt, ...)
int asprintf(char ** restrict buf, const char * restrict fmt, ...)
{
va_list args;
va_start(args, fmt);
Expand Down
7 changes: 5 additions & 2 deletions link-parser/parser-utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ void initialize_screen_width(Command_Options *);
#define MAX_INPUT_LINE 2048

#ifdef _WIN32
#ifndef mkdir
#define mkdir(d, a) mkdir(d)
#endif
#ifndef __MINGW32__
/* There is no ssize_t definition in native Windows. */
#include <BaseTsd.h>
Expand All @@ -47,9 +50,9 @@ int lg_isatty(int);
bool get_line(const char *, char **, unsigned int, FILE *, FILE *, bool);

#if !HAVE_ASPRINTF
int vasprintf(char ** __restrict__, const char * __restrict__, va_list)
int vasprintf(char ** restrict, const char * restrict, va_list)
GNUC_PRINTF(2,0);
int asprintf(char ** __restrict__, const char * __restrict__, ...)
int asprintf(char ** restrict, const char * restrict, ...)
GNUC_PRINTF(2,3);
#endif /* !HAVE_ASPRINTF */

Expand Down

0 comments on commit 0bcaf23

Please sign in to comment.