Skip to content

Commit 6bd7d41

Browse files
authored
Enabled custom options for local terminals list (#1026)
The `custom_args` key is read only from the local list (the global list doesn't — and shouldn't — have it), while `open_arg` and `noclose_arg` are first read from the local list, and if empty, from the global list. Also, a memory leak and a bug are fixed in `terminal.cpp`. Closes #954 NOTE: This PR will be followed by a pcmanfm-qt PR that uses it.
1 parent f94adc3 commit 6bd7d41

File tree

2 files changed

+74
-37
lines changed

2 files changed

+74
-37
lines changed

src/core/terminal.cpp

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,48 +19,58 @@ static void child_setup(gpointer user_data) {
1919
}
2020

2121
bool launchTerminal(const char* programName, const FilePath& workingDir, Fm::GErrorPtr& error) {
22-
/* read user and system terminals files */
22+
CStrPtr desktop_id;
23+
CStrPtr launch;
24+
CStrPtr custom_args;
25+
26+
/* read local and global terminals lists */
2327
GKeyFile* kf = g_key_file_new();
24-
bool found = g_key_file_load_from_data_dirs(kf, "libfm-qt/terminals.list", nullptr, G_KEY_FILE_NONE, nullptr);
25-
if(found) {
26-
found = g_key_file_has_group(kf, programName);
28+
if(g_key_file_load_from_data_dirs(kf, "libfm-qt/terminals.list", nullptr, G_KEY_FILE_NONE, nullptr)
29+
&& g_key_file_has_group(kf, programName)) {
30+
desktop_id = CStrPtr{g_key_file_get_string(kf, programName, "desktop_id", nullptr)};
31+
launch = CStrPtr{g_key_file_get_string(kf, programName, "launch", nullptr)};
32+
/* read only from the local list */
33+
custom_args = CStrPtr{g_key_file_get_string(kf, programName, "custom_args", nullptr)};
2734
}
28-
if(!found) {
35+
if (!desktop_id || !launch // file or key did not exist
36+
// value did not exist
37+
|| g_strcmp0(desktop_id.get(), "") == 0 || g_strcmp0(launch.get(), "") == 0) {
2938
g_key_file_free(kf);
3039
kf = g_key_file_new();
31-
if(!g_key_file_load_from_file(kf, LIBFM_QT_DATA_DIR "/terminals.list", G_KEY_FILE_NONE, &error)) {
32-
g_key_file_free(kf);
33-
return false;
40+
if(g_key_file_load_from_file(kf, LIBFM_QT_DATA_DIR "/terminals.list", G_KEY_FILE_NONE, &error)
41+
&& g_key_file_has_group(kf, programName)) {
42+
if (!desktop_id || g_strcmp0(desktop_id.get(), "") == 0) {
43+
desktop_id = CStrPtr{g_key_file_get_string(kf, programName, "desktop_id", nullptr)};
44+
}
45+
if (!launch || g_strcmp0(launch.get(), "") == 0) {
46+
launch = CStrPtr{g_key_file_get_string(kf, programName, "launch", nullptr)};
47+
}
3448
}
3549
}
36-
37-
auto launch = g_key_file_get_string(kf, programName, "launch", nullptr);
38-
auto desktop_id = g_key_file_get_string(kf, programName, "desktop_id", nullptr);
50+
g_key_file_free(kf);
3951

4052
GDesktopAppInfo* appinfo = nullptr;
41-
if(desktop_id) {
42-
appinfo = g_desktop_app_info_new(desktop_id);
53+
if(desktop_id && g_strcmp0(desktop_id.get(), "") != 0) {
54+
appinfo = g_desktop_app_info_new(desktop_id.get());
4355
}
4456

4557
const gchar* cmd;
4658
gchar* _cmd = nullptr;
4759
if(appinfo) {
4860
cmd = g_app_info_get_commandline(G_APP_INFO(appinfo));
4961
}
50-
else if(launch) {
51-
cmd = _cmd = g_strdup_printf("%s %s", programName, launch);
62+
else if(launch && g_strcmp0(launch.get(), "") != 0) {
63+
cmd = _cmd = g_strdup_printf("%s %s", programName, launch.get());
5264
}
5365
else {
5466
cmd = programName;
5567
}
5668

57-
#if 0 // FIXME: what's this?
58-
if(custom_args) {
59-
cmd = g_strdup_printf("%s %s", cmd, custom_args);
69+
if(custom_args && g_strcmp0(custom_args.get(), "") != 0) {
70+
cmd = g_strdup_printf("%s %s", cmd, custom_args.get());
6071
g_free(_cmd);
6172
_cmd = (char*)cmd;
6273
}
63-
#endif
6474

6575
char** argv;
6676
int argc;
@@ -115,10 +125,25 @@ bool launchTerminal(const char* programName, const FilePath& workingDir, Fm::GEr
115125
nullptr, &error);
116126
g_strfreev(argv);
117127
g_strfreev(envp);
118-
g_key_file_free(kf);
119128
return ret;
120129
}
121130

131+
std::vector<CStrPtr> internalTerminals() {
132+
std::vector<CStrPtr> terminals;
133+
GKeyFile* kf = g_key_file_new();
134+
if(g_key_file_load_from_file(kf, LIBFM_QT_DATA_DIR "/terminals.list", G_KEY_FILE_NONE, nullptr)) {
135+
gsize n;
136+
auto programs = g_key_file_get_groups(kf, &n);
137+
terminals.reserve(terminals.capacity() + n);
138+
for(auto name = programs; *name; ++name) {
139+
terminals.emplace_back(*name);
140+
}
141+
g_free(programs);
142+
}
143+
g_key_file_free(kf);
144+
return terminals;
145+
}
146+
122147
std::vector<CStrPtr> allKnownTerminals() {
123148
std::vector<CStrPtr> terminals;
124149
std::vector<std::string> dataTerminals;
@@ -157,28 +182,38 @@ extern "C" char* expand_terminal(char* cmd, gboolean keep_open, GError** error)
157182
CStrPtr noclose_arg;
158183
CStrPtr custom_args;
159184

160-
/* read user and system terminals files */
161-
bool found = false;
185+
/* read local and global terminals lists */
162186
GKeyFile* kf = g_key_file_new();
163-
if(g_key_file_load_from_data_dirs(kf, "libfm-qt/terminals.list", nullptr, G_KEY_FILE_NONE, nullptr)) {
164-
found = g_key_file_has_group(kf, defaultTerminalName.c_str());
165-
}
166-
if(!found) {
167-
g_key_file_free(kf);
168-
kf = g_key_file_new();
169-
if(g_key_file_load_from_file(kf, LIBFM_QT_DATA_DIR "/terminals.list", G_KEY_FILE_NONE, error)) {
170-
found = g_key_file_has_group(kf, defaultTerminalName.c_str());
171-
}
172-
}
173-
if(found) {
187+
if(g_key_file_load_from_data_dirs(kf, "libfm-qt/terminals.list", nullptr, G_KEY_FILE_NONE, nullptr)
188+
&& g_key_file_has_group(kf, defaultTerminalName.c_str())) {
174189
program = defaultTerminalName.c_str();
175190
open_arg = CStrPtr{g_key_file_get_string(kf, program, "open_arg", nullptr)};
176191
noclose_arg = CStrPtr{g_key_file_get_string(kf, program, "noclose_arg", nullptr)};
177192
custom_args = CStrPtr{g_key_file_get_string(kf, program, "custom_args", nullptr)};
193+
/* NOTE: "custom_args" is read only from the local list, but if "open_arg" or
194+
"noclose_arg" is missing in the local list, it will be read from the global list. */
195+
}
196+
if(!open_arg || !noclose_arg // file or key did not exist
197+
// value did not exist
198+
|| g_strcmp0(open_arg.get(), "") == 0 || g_strcmp0(noclose_arg.get(), "") == 0) {
199+
g_key_file_free(kf);
200+
kf = g_key_file_new();
201+
if(g_key_file_load_from_file(kf, LIBFM_QT_DATA_DIR "/terminals.list", G_KEY_FILE_NONE, error)
202+
&& g_key_file_has_group(kf, defaultTerminalName.c_str())) {
203+
if(!program) {
204+
program = defaultTerminalName.c_str();
205+
}
206+
if(!open_arg || g_strcmp0(open_arg.get(), "") == 0) {
207+
open_arg = CStrPtr{g_key_file_get_string(kf, program, "open_arg", nullptr)};
208+
}
209+
if(!noclose_arg || g_strcmp0(noclose_arg.get(), "") == 0) {
210+
noclose_arg = CStrPtr{g_key_file_get_string(kf, program, "noclose_arg", nullptr)};
211+
}
212+
}
178213
}
179214
g_key_file_free(kf);
180215

181-
const char* opts;
216+
const char* opts = nullptr;
182217
/* if %s is not found, fallback to -e */
183218
/* bug #3457335: Crash on application start with Terminal=true. */
184219
/* fallback to xterm if a terminal emulator is not found. */
@@ -190,9 +225,9 @@ extern "C" char* expand_terminal(char* cmd, gboolean keep_open, GError** error)
190225
open_arg = CStrPtr{g_strdup("-e")};
191226
}
192227

193-
if(keep_open && noclose_arg)
228+
if(keep_open && noclose_arg && g_strcmp0(noclose_arg.get(), "") != 0)
194229
opts = noclose_arg.get();
195-
else
230+
else if (open_arg && g_strcmp0(open_arg.get(), "") != 0)
196231
opts = open_arg.get();
197232

198233
if(!opts) {
@@ -201,7 +236,7 @@ extern "C" char* expand_terminal(char* cmd, gboolean keep_open, GError** error)
201236
}
202237

203238
char* ret = nullptr;
204-
if(custom_args)
239+
if(custom_args && g_strcmp0(custom_args.get(), "") != 0)
205240
ret = g_strdup_printf("%s %s %s %s", program, custom_args.get(),
206241
opts, cmd);
207242
else

src/core/terminal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ namespace Fm {
1111

1212
LIBFM_QT_API bool launchTerminal(const char* programName, const FilePath& workingDir, GErrorPtr& error);
1313

14+
LIBFM_QT_API std::vector<CStrPtr> internalTerminals();
15+
1416
LIBFM_QT_API std::vector<CStrPtr> allKnownTerminals();
1517

1618
LIBFM_QT_API const std::string defaultTerminal();

0 commit comments

Comments
 (0)