Re: [PATCH] XDG base directory support (history and wxt)
Jun T <[email protected]>
| Newsgroups | gmane.comp.graphics.gnuplot.devel |
|---|---|
| Message-ID | <[email protected]> |
> 2021/09/14 4:06, Ethan A Merritt <[email protected]> wrote: > > I realize that the previous XDG patch already put a > chunk of code in plot.c to hande the gnuplotrc file, but wouldn't it > be better to have that code and the new patch code for the history file > live in xdg.c instead? > Then in plot.c or history.c the call site would > be: > > #ifdef USE_XDG_BASEDIR > expanded_history_filename = some_new_xdg_routine(GNUPLOT_HISTORY_FILE)); > #endif > if (!expanded_history_filename) { > /* current code */ > expanded_history_filename = tilde_expand(GNUPLOT_HISTORY_FILE); > } > read_history(expanded_history_filename); How about the revised patch (xdg-v2.patch)? I moved "most" of the complication into a function in xdg.c, but plot.c is not as simple as above. >> [2] Migration >> With the patch, gnuplot will continue to use traditional config or history >> files in ~/ if they exist (as it does for the main config file ~/.gnuplot). >> Users must move the traditional files to XDG dirs (or remove ~/.gnuplot-wxt >> and ~/.gnuplot_history) manually if they want to migrate. > > Isn't the obvious migration to set > XDG_DATA_DIRS = $HOME:$HOME/.local/share > XDG_CONFIG_HOME = $HOME:$HOME/.config I couldn't understand this part... > Your current home directory files will be used whether or not > you have XDG enabled, so moving files is not required. > If you choose to enable XDG and move the files, that works also. Yes, this is the case with my match. As I wrote, with my patch, if ~/.gnuplot_history or ~/.gnuplot-wxt exists gnuplot will continue to use them. User need not do anything if they are satisfied with this traditional behavior. If a user wants to use XDG directory, she/he must manually move ~/.gnuplot_history to ~/.local/state/gnuplot_history, and ~/.gnuplot-wxt to ~/.config/gnuplot/gnuplot-wxt.conf (or just remove them), but need not set XDG_CONFIG_HOME etc. (if XDG_CONFIG_HOME is set then it is used instead of ~/.config/, of course) Is this OK? _______________________________________________ gnuplot-beta mailing list [email protected] Membership management via: https://lists.sourceforge.net/lists/listinfo/gnuplot-beta
xdg-v2.patch
(application/octet-stream, 7.9 KB)
diff --git a/src/gp_hist.h b/src/gp_hist.h
index 1a938a609..dc6b3d616 100644
--- a/src/gp_hist.h
+++ b/src/gp_hist.h
@@ -75,7 +75,7 @@ extern int history_base;
void using_history(void);
void clear_history(void);
void add_history(char *line);
-void read_history(char *);
+int read_history(char *);
int write_history(char *);
int where_history(void);
int history_set_pos(int offset);
diff --git a/src/history.c b/src/history.c
index 109018116..0c9999e5c 100644
--- a/src/history.c
+++ b/src/history.c
@@ -88,10 +88,10 @@ write_history(char *filename)
/* routine to read history entries from a file
*/
-void
+int
read_history(char *filename)
{
- gp_read_history(filename);
+ return gp_read_history(filename);
}
diff --git a/src/plot.c b/src/plot.c
index 66fdb6e45..9770ff9b1 100644
--- a/src/plot.c
+++ b/src/plot.c
@@ -495,7 +495,19 @@ main(int argc_orig, char **argv)
expanded_history_filename = gp_strdup(GNUPLOT_HISTORY_FILE);
gp_expand_tilde(&expanded_history_filename);
#endif
- read_history(expanded_history_filename);
+ if (read_history(expanded_history_filename)) {
+#ifdef USE_XDG_BASEDIR
+ /* use $XDG_STATE_DIR/gnuplot_history only if
+ * $XDG_STATE_DIR exists or can be created */
+ char *xdgpath = xdg_get_path(kXDGStateHome, "gnuplot_history",
+ FALSE /* no subdir */, TRUE /* create */);
+ if (xdgpath) {
+ free(expanded_history_filename);
+ expanded_history_filename = xdgpath;
+ read_history(expanded_history_filename);
+ }
+#endif /* USE_XDG_BASEDIR */
+ }
/*
* It is safe to ignore the return values of 'atexit()' and
@@ -790,13 +802,10 @@ load_rcfile(int where)
plotrc = fopen(rcfile, "r");
} else if (where == 3) {
#ifdef USE_XDG_BASEDIR
- char * XDGConfigHome = xdg_get_var(kXDGConfigHome);
- size_t len = strlen(XDGConfigHome);
- rcfile = gp_alloc(len + 1 + sizeof("gnuplot/gnuplotrc"), "rcfile");
- strcpy(rcfile, XDGConfigHome);
- PATH_CONCAT(rcfile, "gnuplot/gnuplotrc");
- plotrc = fopen(rcfile, "r");
- free(XDGConfigHome);
+ rcfile = xdg_get_path(kXDGConfigHome, "gnuplotrc",
+ TRUE /* use subdir */, FALSE /* not create */);
+ if (rcfile)
+ plotrc = fopen(rcfile, "r");
#endif
}
diff --git a/src/wxterminal/wxt_gui.cpp b/src/wxterminal/wxt_gui.cpp
index 7e59ee655..d79fd818b 100644
--- a/src/wxterminal/wxt_gui.cpp
+++ b/src/wxterminal/wxt_gui.cpp
@@ -120,6 +120,7 @@
#include <wx/printdlg.h>
extern "C" {
+#include "xdg.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -327,13 +328,28 @@ bool wxtApp::OnInit()
/* application and vendor name are used by wxConfig to construct the name
* of the config file/registry key and must be set before the first call
* to Get() */
- SetVendorName(wxT("gnuplot"));
- SetAppName(wxT("gnuplot-wxt"));
- wxConfigBase *pConfig = wxConfigBase::Get();
+ const wxString vendorName(wxT("gnuplot"));
+ const wxString appName(wxT("gnuplot-wxt"));
+ SetVendorName(vendorName);
+ SetAppName(appName);
+
+#ifdef USE_XDG_BASEDIR
+ if (!wxFileConfig::GetLocalFile(appName).Exists()) {
+ // Traditional config file (~/.gnuplot-wxt) does not exist.
+ // We will use $XDG_CONFIG_HOME/gnuplot/gnuplot-wxt.conf only if
+ // $XDG_CONFIG_HOME/gnuplot/ exists or can be created.
+ char *configFile = xdg_get_path(kXDGConfigHome, "gnuplot-wxt.conf",
+ TRUE /* subdir */, TRUE /* create */);
+ if (configFile) {
+ wxConfig::Set(new wxFileConfig(appName, vendorName, configFile));
+ free(configFile);
+ }
+ }
+#endif
/* this will force writing back of the defaults for all values
* if they're not present in the config - this can give the user an idea
* of all possible settings */
- pConfig->SetRecordDefaults();
+ wxConfig::Get()->SetRecordDefaults();
FPRINTF((stderr, "OnInit finished\n"));
diff --git a/src/xdg.c b/src/xdg.c
index e6652d329..513236a96 100644
--- a/src/xdg.c
+++ b/src/xdg.c
@@ -1,8 +1,9 @@
#include "xdg.h"
+#ifdef USE_XDG_BASEDIR
+
#include "plot.h"
#include "util.h"
-
-#ifdef USE_XDG_BASEDIR
+#include "alloc.h"
#include <assert.h>
#include <stdio.h>
@@ -13,6 +14,7 @@
static const char *xdg_env_vars[] = {
[kXDGConfigHome] = "XDG_CONFIG_HOME",
[kXDGDataHome] = "XDG_DATA_HOME",
+ [kXDGStateHome] = "XDG_STATE_HOME",
[kXDGCacheHome] = "XDG_CACHE_HOME",
[kXDGRuntimeDir] = "XDG_RUNTIME_DIR",
[kXDGConfigDirs] = "XDG_CONFIG_DIRS",
@@ -25,36 +27,69 @@ static const char *xdg_env_vars[] = {
static const char *const xdg_defaults[] = {
[kXDGConfigHome] = "~/.config",
[kXDGDataHome] = "~/.local/share",
+ [kXDGStateHome] = "~/.local/state",
[kXDGCacheHome] = "~/.cache",
[kXDGRuntimeDir] = "",
[kXDGConfigDirs] = "/etc/xdg/",
[kXDGDataDirs] = "/usr/local/share/:/usr/share/",
};
+/* helper function: return TRUE if dirname exists or can be created */
+
+static TBOOLEAN check_dir(const char *dirname) {
+#ifdef HAVE_SYS_STAT_H
+ return existdir(dirname) || !mkdir(dirname, 00700);
+#else /* I believe this does not happen */
+ return FALSE;
+#endif
+}
+
+/* name used for subdirectory */
+static const char *appname = "gnuplot";
-/* Return XDG variable value
+/* Return pathname of XDG base directory or a file in it
*
- * First query the environement variable and if that does not exist fall back
- * to the defaults. Further reading:
+ * XDG base directory specification:
* https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
*
- * @param[in] idx XDG variable to use.
+ * @param[in] idx XDG variable to use.
+ * @param[in] fname if not NULL, name of a file in the base directory
+ * @param[in] subdir if TRUE, append "/gnuplot" to the base directory
+ * @param[in] create if TRUE, try to create the directory
*
- * @return [allocated] variable value.
+ * @return [allocated] pathname of the base directory if fname is NULL,
+ * else of the file in the directory. Returns NULL if
+ * create is TURE but the directory can't be created.
*/
-char *xdg_get_var(const XDGVarType idx) {
- /* Check the environment variable. If it is there, we are done. */
- char *XDGVar;
- if ((XDGVar = getenv(xdg_env_vars[idx])) != NULL) {
- return gp_strdup(XDGVar);
+char *xdg_get_path(XDGVarType idx, const char* fname,
+ TBOOLEAN subdir, TBOOLEAN create) {
+ char *pathname;
+ if ((pathname = getenv(xdg_env_vars[idx]))) {
+ pathname = gp_strdup(pathname); /* use the environment variable */
}
-
- /* Looks like the environment variable is not there.
- * Load the default and run word expansion on it.
- */
- XDGVar = gp_strdup(xdg_defaults[idx]);
- gp_expand_tilde(&XDGVar);
- return XDGVar;
+ else {
+ pathname = gp_strdup(xdg_defaults[idx]); /* use the default */
+ gp_expand_tilde(&pathname);
+ }
+ if (create && !check_dir(pathname)) {
+ free(pathname);
+ return NULL;
+ }
+ if (subdir) {
+ pathname = gp_realloc(pathname,
+ strlen(pathname) + strlen(appname) + 2, "XDG");
+ PATH_CONCAT(pathname, appname);
+ if (create && !check_dir(pathname)) {
+ free(pathname);
+ return NULL;
+ }
+ }
+ if (fname) {
+ pathname = gp_realloc(pathname,
+ strlen(pathname) + strlen(fname) + 2, "XDG");
+ PATH_CONCAT(pathname, fname);
+ }
+ return pathname;
}
#endif /* USE_XDG_BASEDIR */
diff --git a/src/xdg.h b/src/xdg.h
index cab5e1415..7510444ee 100644
--- a/src/xdg.h
+++ b/src/xdg.h
@@ -5,18 +5,22 @@
#define USE_XDG_BASEDIR
+#include "syscfg.h" /* for TBOOLEAN */
+
/* List of possible XDG variables */
typedef enum {
kXDGNone = -1,
kXDGConfigHome, /* XDG_CONFIG_HOME */
kXDGDataHome, /* XDG_DATA_HOME */
+ kXDGStateHome, /* XDG_STATE_HOME */
kXDGCacheHome, /* XDG_CACHE_HOME */
kXDGRuntimeDir, /* XDG_RUNTIME_DIR */
kXDGConfigDirs, /* XDG_CONFIG_DIRS */
kXDGDataDirs, /* XDG_DATA_DIRS */
} XDGVarType;
-char *xdg_get_var(const XDGVarType idx);
+char *xdg_get_path(XDGVarType idx, const char *fname,
+ TBOOLEAN subdir, TBOOLEAN create);
#endif /* USE_XDG_BASEDIR */