forked from quickshell/quickshell
		
	launch: look for configs in all XDG config dirs
This commit is contained in:
		
							parent
							
								
									b898592db7
								
							
						
					
					
						commit
						cb195d4b2a
					
				
					 2 changed files with 85 additions and 19 deletions
				
			
		| 
						 | 
				
			
			@ -15,10 +15,12 @@
 | 
			
		|||
#include <qjsonarray.h>
 | 
			
		||||
#include <qjsondocument.h>
 | 
			
		||||
#include <qjsonobject.h>
 | 
			
		||||
#include <qlist.h>
 | 
			
		||||
#include <qlogging.h>
 | 
			
		||||
#include <qloggingcategory.h>
 | 
			
		||||
#include <qnamespace.h>
 | 
			
		||||
#include <qstandardpaths.h>
 | 
			
		||||
#include <qtenvironmentvariables.h>
 | 
			
		||||
#include <qtversion.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +38,44 @@ using qs::ipc::IpcClient;
 | 
			
		|||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
QList<QString> configBaseDirs() {
 | 
			
		||||
	auto configHome = qEnvironmentVariable("XDG_CONFIG_HOME");
 | 
			
		||||
	if (configHome.isEmpty()) {
 | 
			
		||||
		auto home = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
 | 
			
		||||
		configHome = QDir(home).filePath(".config");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto configDirs = qEnvironmentVariable("XDG_CONFIG_DIRS").split(':', Qt::SkipEmptyParts);
 | 
			
		||||
	if (configDirs.isEmpty()) {
 | 
			
		||||
		configDirs.append("/etc/xdg");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	configDirs.prepend(configHome);
 | 
			
		||||
 | 
			
		||||
	for (auto& dir: configDirs) {
 | 
			
		||||
		dir.append("/quickshell");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return configDirs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString locateNamedConfig(const QString& name) {
 | 
			
		||||
	for (const auto& baseDir: configBaseDirs()) {
 | 
			
		||||
		auto shellPath = QDir(baseDir).filePath("shell.qml");
 | 
			
		||||
		auto hasShell = QFileInfo(shellPath).isFile();
 | 
			
		||||
 | 
			
		||||
		if (hasShell) {
 | 
			
		||||
			if (name == "default") return shellPath;
 | 
			
		||||
			else continue; // skip subfolders if shell.qml is present in folder
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		shellPath = QDir(QDir(baseDir).filePath(name)).filePath("shell.qml");
 | 
			
		||||
		if (QFileInfo(shellPath).isFile()) return shellPath;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return QString();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int locateConfigFile(CommandState& cmd, QString& path) {
 | 
			
		||||
	if (!cmd.config.path->isEmpty()) {
 | 
			
		||||
		path = *cmd.config.path;
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +88,11 @@ int locateConfigFile(CommandState& cmd, QString& path) {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		if (!manifestPath.isEmpty()) {
 | 
			
		||||
			qWarning(
 | 
			
		||||
			) << "Config manifests (manifest.conf) are deprecated and will be removed in a future "
 | 
			
		||||
			     "release.";
 | 
			
		||||
			qWarning() << "Consider using symlinks to a subfolder of quickshell's XDG config dirs.";
 | 
			
		||||
 | 
			
		||||
			auto file = QFile(manifestPath);
 | 
			
		||||
			if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
 | 
			
		||||
				auto stream = QTextStream(&file);
 | 
			
		||||
| 
						 | 
				
			
			@ -78,13 +123,23 @@ int locateConfigFile(CommandState& cmd, QString& path) {
 | 
			
		|||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			auto configDir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation));
 | 
			
		||||
			const auto& name = cmd.config.name->isEmpty() ? "default" : *cmd.config.name;
 | 
			
		||||
			path = locateNamedConfig(name);
 | 
			
		||||
 | 
			
		||||
			if (cmd.config.name->isEmpty()) {
 | 
			
		||||
				path = configDir.path();
 | 
			
		||||
			} else {
 | 
			
		||||
				path = configDir.filePath(*cmd.config.name);
 | 
			
		||||
			if (path.isEmpty()) {
 | 
			
		||||
				if (name == "default") {
 | 
			
		||||
					qCCritical(logBare
 | 
			
		||||
					) << "Could not find \"default\" config directory or shell.qml in any valid config path.";
 | 
			
		||||
				} else {
 | 
			
		||||
					qCCritical(logBare) << "Could not find" << name
 | 
			
		||||
					                    << "config directory in any valid config path.";
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			path = QFileInfo(path).canonicalFilePath();
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +153,6 @@ int locateConfigFile(CommandState& cmd, QString& path) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	path = QFileInfo(path).canonicalFilePath();
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,26 +17,38 @@ int parseCommand(int argc, char** argv, CommandState& state) {
 | 
			
		|||
	};
 | 
			
		||||
 | 
			
		||||
	auto addConfigSelection = [&](CLI::App* cmd, bool withNewestOption = false) {
 | 
			
		||||
		auto* group = cmd->add_option_group("Config Selection")
 | 
			
		||||
		                  ->description("If no options in this group are specified,\n"
 | 
			
		||||
		                                "$XDG_CONFIG_HOME/quickshell/shell.qml will be used.");
 | 
			
		||||
		auto* group =
 | 
			
		||||
		    cmd->add_option_group("Config Selection")
 | 
			
		||||
		        ->description(
 | 
			
		||||
		            "Quickshell detects configurations as named directories under each XDG config "
 | 
			
		||||
		            "directory as `<xdg dir>/quickshell/<config name>/shell.qml`.\n\n"
 | 
			
		||||
		            "If `<xdg dir>/quickshell/shell.qml` exists, it will be registered as the "
 | 
			
		||||
		            "'default' configuration, and no subdirectories will be considered. "
 | 
			
		||||
		            "If --config is not passed, 'default' will be assumed.\n\n"
 | 
			
		||||
		            "Alternatively, a config can be selected by path with --path.\n\n"
 | 
			
		||||
		            "Examples:\n"
 | 
			
		||||
		            "- `~/.config/quickshell/shell.qml` can be run with `qs`\n"
 | 
			
		||||
		            "- `/etc/xdg/quickshell/myconfig/shell.qml` can be run with `qs -c myconfig`\n"
 | 
			
		||||
		            "- `~/myshell/shell.qml` can be run with `qs -p ~/myshell`\n"
 | 
			
		||||
		            "- `~/myshell/randomfile.qml` can be run with `qs -p ~/myshell/randomfile.qml`"
 | 
			
		||||
		        );
 | 
			
		||||
 | 
			
		||||
		auto* path = group->add_option("-p,--path", state.config.path)
 | 
			
		||||
		                 ->description("Path to a QML file.")
 | 
			
		||||
		                 ->description("Path to a QML file or config folder.")
 | 
			
		||||
		                 ->envname("QS_CONFIG_PATH");
 | 
			
		||||
 | 
			
		||||
		group->add_option("-c,--config", state.config.name)
 | 
			
		||||
		    ->description("Name of a quickshell configuration to run.")
 | 
			
		||||
		    ->envname("QS_CONFIG_NAME")
 | 
			
		||||
		    ->excludes(path);
 | 
			
		||||
 | 
			
		||||
		group->add_option("-m,--manifest", state.config.manifest)
 | 
			
		||||
		    ->description("Path to a quickshell manifest.\n"
 | 
			
		||||
		    ->description("[DEPRECATED] Path to a quickshell manifest.\n"
 | 
			
		||||
		                  "If a manifest is specified, configs named by -c will point to its entries.\n"
 | 
			
		||||
		                  "Defaults to $XDG_CONFIG_HOME/quickshell/manifest.conf")
 | 
			
		||||
		    ->envname("QS_MANIFEST")
 | 
			
		||||
		    ->excludes(path);
 | 
			
		||||
 | 
			
		||||
		group->add_option("-c,--config", state.config.name)
 | 
			
		||||
		    ->description("Name of a quickshell configuration to run.\n"
 | 
			
		||||
		                  "If -m is specified, this is a configuration in the manifest,\n"
 | 
			
		||||
		                  "otherwise it is the name of a folder in $XDG_CONFIG_HOME/quickshell.")
 | 
			
		||||
		    ->envname("QS_CONFIG_NAME");
 | 
			
		||||
 | 
			
		||||
		if (withNewestOption) {
 | 
			
		||||
			group->add_flag("-n,--newest", state.config.newest)
 | 
			
		||||
			    ->description("Operate on the most recently launched instance instead of the oldest");
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +76,7 @@ int parseCommand(int argc, char** argv, CommandState& state) {
 | 
			
		|||
 | 
			
		||||
		group->add_flag("--no-color", state.log.noColor)
 | 
			
		||||
		    ->description("Disables colored logging.\n"
 | 
			
		||||
		                  "Colored logging can also be disabled by specifying a non empty value\n"
 | 
			
		||||
		                  "Colored logging can also be disabled by specifying a non empty value "
 | 
			
		||||
		                  "for the NO_COLOR environment variable.");
 | 
			
		||||
 | 
			
		||||
		group->add_flag("--log-times", state.log.timestamp)
 | 
			
		||||
| 
						 | 
				
			
			@ -87,7 +99,7 @@ int parseCommand(int argc, char** argv, CommandState& state) {
 | 
			
		|||
 | 
			
		||||
		group->add_option("-i,--id", state.instance.id)
 | 
			
		||||
		    ->description("The instance id to operate on.\n"
 | 
			
		||||
		                  "You may also use a substring the id as long as it is unique,\n"
 | 
			
		||||
		                  "You may also use a substring the id as long as it is unique, "
 | 
			
		||||
		                  "for example \"abc\" will select \"abcdefg\".");
 | 
			
		||||
 | 
			
		||||
		group->add_option("--pid", state.instance.pid)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue