girara
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
config.c
Go to the documentation of this file.
1 /* See LICENSE file for license and copyright information */
2 
3 #include <stdlib.h>
4 #include <string.h>
5 #include <glib/gi18n-lib.h>
6 
7 #include "config.h"
8 #include "commands.h"
9 #include "datastructures.h"
10 #include "internal.h"
11 #include "session.h"
12 #include "settings.h"
13 #include "shortcuts.h"
14 #include "utils.h"
15 
16 #define COMMENT_PREFIX "\"#"
17 
18 static void
19 cb_window_icon(girara_session_t* session, const char* UNUSED(name),
20  girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
21 {
22  g_return_if_fail(session != NULL && value != NULL);
23 
24  if (session->gtk.window != NULL) {
25  GError* error = NULL;
26  gtk_window_set_icon_from_file(GTK_WINDOW(session->gtk.window), (const char*) value, &error);
27  if (error != NULL) {
28  girara_error("failed to load window icon: %s", error->message);
29  g_error_free(error);
30  }
31  }
32 }
33 
34 static void
35 cb_font(girara_session_t* session, const char* UNUSED(name),
36  girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
37 {
38  g_return_if_fail(session != NULL && value != NULL);
39 
40  pango_font_description_free(session->style.font);
41 
42  /* parse font */
43  PangoFontDescription* font = pango_font_description_from_string(value);
44  session->style.font = font;
45 
46  /* inputbar */
47  if (session->gtk.inputbar_entry != NULL) {
48  gtk_widget_override_font(GTK_WIDGET(session->gtk.inputbar_entry), font);
49  }
50 
51  if (session->gtk.inputbar_dialog != NULL) {
52  gtk_widget_override_font(GTK_WIDGET(session->gtk.inputbar_dialog), font);
53  }
54 
55  /* notification area */
56  if (session->gtk.notification_text != NULL) {
57  gtk_widget_override_font(GTK_WIDGET(session->gtk.notification_text), font);
58  }
59 
60  GIRARA_LIST_FOREACH(session->elements.statusbar_items, girara_statusbar_item_t *, iter, item)
61  if (item != NULL){
62  gtk_widget_override_font(GTK_WIDGET(item->text), font);
63  }
64  GIRARA_LIST_FOREACH_END(session->elements.statusbar_items, girara_statusbar_item_t *, iter, item);
65 }
66 
67 static void
68 cb_guioptions(girara_session_t* session, const char* UNUSED(name),
69  girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
70 {
71  g_return_if_fail(session != NULL && value != NULL);
72 
73  /* set default values */
74  bool show_commandline = false;
75  bool show_statusbar = false;
76 
77  /* evaluate input */
78  char* input = (char*) value;
79  int input_length = strlen(input);
80 
81  for (int i = 0; i < input_length; i++) {
82  switch (input[i]) {
83  /* command line */
84  case 'c':
85  show_commandline = true;
86  break;
87  /* statusbar */
88  case 's':
89  show_statusbar = true;
90  break;
91  }
92  }
93 
94  /* apply settings */
95  if (show_commandline == true) {
96  session->global.autohide_inputbar = false;
97  gtk_widget_show(session->gtk.inputbar);
98  } else {
99  session->global.autohide_inputbar = true;
100  gtk_widget_hide(session->gtk.inputbar);
101  }
102 
103  if (show_statusbar == true) {
104  session->global.hide_statusbar = false;
105  gtk_widget_show(session->gtk.statusbar);
106  } else {
107  session->global.hide_statusbar = true;
108  gtk_widget_hide(session->gtk.statusbar);
109  }
110 }
111 
112 static void
113 cb_scrollbars(girara_session_t* session, const char* UNUSED(name),
114  girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
115 {
116  g_return_if_fail(session != NULL && value != NULL);
117 
118  if (*(bool*) value == true) {
119  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(session->gtk.view),
120  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
121  } else {
122  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(session->gtk.view),
123  GTK_POLICY_NEVER, GTK_POLICY_NEVER);
124  }
125 }
126 
127 void
128 girara_config_load_default(girara_session_t* session)
129 {
130  if (session == NULL) {
131  return;
132  }
133 
134  /* values */
135  int window_width = 800;
136  int window_height = 600;
137  int n_completion_items = 15;
138  bool show_scrollbars = false;
139  girara_mode_t normal_mode = session->modes.normal;
140 
141  /* other values */
142  session->global.autohide_inputbar = true;
143 
144  /* settings */
145  girara_setting_add(session, "font", "monospace normal 9", STRING, FALSE, _("Font"), cb_font, NULL);
146  girara_setting_add(session, "default-fg", "#DDDDDD", STRING, TRUE, _("Default foreground color"), NULL, NULL);
147  girara_setting_add(session, "default-bg", "#000000", STRING, TRUE, _("Default background color"), NULL, NULL);
148  girara_setting_add(session, "inputbar-fg", "#9FBC00", STRING, TRUE, _("Inputbar foreground color"), NULL, NULL);
149  girara_setting_add(session, "inputbar-bg", "#131313", STRING, TRUE, _("Inputbar background color"), NULL, NULL);
150  girara_setting_add(session, "statusbar-fg", "#FFFFFF", STRING, TRUE, _("Statusbar foreground color"), NULL, NULL);
151  girara_setting_add(session, "statusbar-bg", "#000000", STRING, TRUE, _("Statsubar background color"), NULL, NULL);
152  girara_setting_add(session, "completion-fg", "#DDDDDD", STRING, TRUE, _("Completion foreground color"), NULL, NULL);
153  girara_setting_add(session, "completion-bg", "#232323", STRING, TRUE, _("Completion background color"), NULL, NULL);
154  girara_setting_add(session, "completion-group-fg", "#DEDEDE", STRING, TRUE, _("Completion group foreground color"), NULL, NULL);
155  girara_setting_add(session, "completion-group-bg", "#000000", STRING, TRUE, _("Completion group background color"), NULL, NULL);
156  girara_setting_add(session, "completion-highlight-fg", "#232323", STRING, TRUE, _("Completion highlight foreground color"), NULL, NULL);
157  girara_setting_add(session, "completion-highlight-bg", "#9FBC00", STRING, TRUE, _("Completion highlight background color"), NULL, NULL);
158  girara_setting_add(session, "notification-error-fg", "#FFFFFF", STRING, TRUE, _("Error notification foreground color"), NULL, NULL);
159  girara_setting_add(session, "notification-error-bg", "#FF1212", STRING, TRUE, _("Error notification background color"), NULL, NULL);
160  girara_setting_add(session, "notification-warning-fg", "#000000", STRING, TRUE, _("Warning notification foreground color"), NULL, NULL);
161  girara_setting_add(session, "notification-warning-bg", "#F3F000", STRING, TRUE, _("Warning notifaction background color"), NULL, NULL);
162  girara_setting_add(session, "notification-fg", "#000000", STRING, TRUE, _("Notification foreground color"), NULL, NULL);
163  girara_setting_add(session, "notification-bg", "#FFFFFF", STRING, TRUE, _("Notification background color"), NULL, NULL);
164  girara_setting_add(session, "tabbar-fg", "#939393", STRING, TRUE, _("Tab bar foreground color"), NULL, NULL);
165  girara_setting_add(session, "tabbar-bg", "#000000", STRING, TRUE, _("Tab bar background color"), NULL, NULL);
166  girara_setting_add(session, "tabbar-focus-fg", "#9FBC00", STRING, TRUE, _("Tab bar foreground color (active)"), NULL, NULL);
167  girara_setting_add(session, "tabbar-focus-bg", "#000000", STRING, TRUE, _("Tab bar background color (active)"), NULL, NULL);
168  girara_setting_add(session, "word-separator", " /.-=&#?", STRING, TRUE, NULL, NULL, NULL);
169  girara_setting_add(session, "window-width", &window_width, INT, TRUE, _("Initial window width"), NULL, NULL);
170  girara_setting_add(session, "window-height", &window_height, INT, TRUE, _("Initial window height"), NULL, NULL);
171  girara_setting_add(session, "n-completion-items", &n_completion_items, INT, TRUE, _("Number of completion items"), NULL, NULL);
172  girara_setting_add(session, "show-scrollbars", &show_scrollbars, BOOLEAN, FALSE, _("Show scrollbars"), cb_scrollbars, NULL);
173  girara_setting_add(session, "window-icon", "", STRING, FALSE, _("Window icon"), cb_window_icon, NULL);
174  girara_setting_add(session, "exec-command", "", STRING, FALSE, _("Command to execute in :exec"), NULL, NULL);
175  girara_setting_add(session, "guioptions", "s", STRING, FALSE, _("Show or hide certain GUI elements"), cb_guioptions, NULL);
176 
177  /* shortcuts */
178  girara_shortcut_add(session, 0, GDK_KEY_Escape, NULL, girara_sc_abort, normal_mode, 0, NULL);
179  girara_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_c, NULL, girara_sc_abort, normal_mode, 0, NULL);
180  girara_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_q, NULL, girara_sc_quit, normal_mode, 0, NULL);
181  girara_shortcut_add(session, 0, GDK_KEY_colon, NULL, girara_sc_focus_inputbar, normal_mode, 0, ":");
182  girara_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_w, NULL, girara_sc_tab_close, normal_mode, 0, NULL);
183  girara_shortcut_add(session, 0, 0, "gt", girara_sc_tab_navigate, normal_mode, GIRARA_NEXT, NULL);
184  girara_shortcut_add(session, 0, 0, "gT", girara_sc_tab_navigate, normal_mode, GIRARA_PREVIOUS, NULL);
185 
186  /* inputbar shortcuts */
187  girara_inputbar_shortcut_add(session, 0, GDK_KEY_Escape, girara_isc_abort, 0, NULL);
188  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_c, girara_isc_abort, 0, NULL);
189  girara_inputbar_shortcut_add(session, 0, GDK_KEY_Tab, girara_isc_completion, GIRARA_NEXT, NULL);
190  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_Tab, girara_isc_completion, GIRARA_NEXT_GROUP, NULL);
191  girara_inputbar_shortcut_add(session, 0, GDK_KEY_ISO_Left_Tab, girara_isc_completion, GIRARA_PREVIOUS, NULL);
192  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_ISO_Left_Tab, girara_isc_completion, GIRARA_PREVIOUS_GROUP, NULL);
194  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_h, girara_isc_string_manipulation, GIRARA_DELETE_LAST_CHAR, NULL);
196  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_k, girara_isc_string_manipulation, GIRARA_DELETE_TO_LINE_END, NULL);
197  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_d, girara_isc_string_manipulation, GIRARA_DELETE_CURR_CHAR, NULL);
198  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_w, girara_isc_string_manipulation, GIRARA_DELETE_LAST_WORD, NULL);
199  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_f, girara_isc_string_manipulation, GIRARA_NEXT_CHAR, NULL);
200  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_b, girara_isc_string_manipulation, GIRARA_PREVIOUS_CHAR, NULL);
203  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_a, girara_isc_string_manipulation, GIRARA_GOTO_START, NULL);
204  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_e, girara_isc_string_manipulation, GIRARA_GOTO_END, NULL);
206  girara_inputbar_shortcut_add(session, 0, GDK_KEY_Down, girara_isc_command_history, GIRARA_NEXT, NULL);
207  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_p, girara_isc_command_history, GIRARA_PREVIOUS, NULL);
208  girara_inputbar_shortcut_add(session, GDK_CONTROL_MASK, GDK_KEY_n, girara_isc_command_history, GIRARA_NEXT, NULL);
209 
210  /* commands */
211  girara_inputbar_command_add(session, "exec", NULL, girara_cmd_exec, NULL, _("Execute a command"));
212  girara_inputbar_command_add(session, "map", "m", girara_cmd_map, NULL, _("Map a key sequence"));
213  girara_inputbar_command_add(session, "quit", "q", girara_cmd_quit, NULL, _("Quit the program"));
214  girara_inputbar_command_add(session, "set", "s", girara_cmd_set, girara_cc_set, _("Set an option"));
215  girara_inputbar_command_add(session, "unmap", NULL, girara_cmd_unmap, NULL, _("Unmap a key sequence"));
216 
217  /* config handle */
218  girara_config_handle_add(session, "map", girara_cmd_map);
219  girara_config_handle_add(session, "set", girara_cmd_set);
220  girara_config_handle_add(session, "unmap", girara_cmd_unmap);
221 
222  /* shortcut mappings */
223  girara_shortcut_mapping_add(session, "focus_inputbar", girara_sc_focus_inputbar);
226  girara_shortcut_mapping_add(session, "feedkeys", girara_sc_feedkeys);
227 }
228 
229 bool
230 girara_config_handle_add(girara_session_t* session, const char* identifier, girara_command_function_t handle)
231 {
232  g_return_val_if_fail(session != NULL, false);
233  g_return_val_if_fail(identifier != NULL, false);
234 
235  /* search for existing config handle */
236  GIRARA_LIST_FOREACH(session->config.handles, girara_config_handle_t*, iter, data)
237  if (strcmp(data->identifier, identifier) == 0) {
238  data->handle = handle;
240  return true;
241  }
242  GIRARA_LIST_FOREACH_END(session->config.handles, girara_config_handle_t*, iter, data);
243 
244  /* add new config handle */
245  girara_config_handle_t* config_handle = g_slice_new(girara_config_handle_t);
246 
247  config_handle->identifier = g_strdup(identifier);
248  config_handle->handle = handle;
249  girara_list_append(session->config.handles, config_handle);
250 
251  return true;
252 }
253 
254 void
255 girara_config_handle_free(girara_config_handle_t* handle)
256 {
257  if (handle == NULL) {
258  return;
259  }
260 
261  g_free(handle->identifier);
262  g_slice_free(girara_config_handle_t, handle);
263 }
264 
265 static bool
266 config_parse(girara_session_t* session, const char* path)
267 {
268  /* open file */
269  FILE* file = girara_file_open(path, "r");
270 
271  if (file == NULL) {
272  return false;
273  }
274 
275  /* read lines */
276  char* line = NULL;
277  unsigned int line_number = 1;
278  while ((line = girara_file_read_line(file)) != NULL) {
279  /* skip empty lines and comments */
280  if (strlen(line) == 0 || strchr(COMMENT_PREFIX, line[0]) != NULL) {
281  free(line);
282  continue;
283  }
284 
285  gchar** argv = NULL;
286  gint argc = 0;
287 
288  girara_list_t* argument_list = girara_list_new();
289  if (argument_list == NULL) {
290  free(line);
291  fclose(file);
292  return false;
293  }
294 
295  girara_list_set_free_function(argument_list, g_free);
296  if (g_shell_parse_argv(line, &argc, &argv, NULL) != FALSE) {
297  for(int i = 1; i < argc; i++) {
298  char* argument = g_strdup(argv[i]);
299  girara_list_append(argument_list, (void*) argument);
300  }
301  } else {
302  girara_list_free(argument_list);
303  fclose(file);
304  free(line);
305  return false;
306  }
307 
308  /* include gets a special treatment */
309  if (strcmp(argv[0], "include") == 0) {
310  if (argc != 2) {
311  girara_warning("Could not process line %d in '%s': usage: include path.", line_number, path);
312  } else {
313  char* newpath = NULL;
314  if (g_path_is_absolute(argv[1]) == TRUE) {
315  newpath = g_strdup(argv[1]);
316  } else {
317  char* basename = g_path_get_dirname(path);
318  char* tmp = g_build_filename(basename, argv[1], NULL);
319  newpath = girara_fix_path(tmp);
320  g_free(tmp);
321  g_free(basename);
322  }
323 
324  if (strcmp(newpath, path) == 0) {
325  girara_warning("Could not process line %d in '%s': trying to include itself.", line_number, path);
326  } else {
327  girara_debug("Loading config file '%s'.", newpath);
328  if (config_parse(session, newpath) == FALSE) {
329  girara_warning("Could not process line %d in '%s': failed to load '%s'.", line_number, path, newpath);
330  }
331  }
332  g_free(newpath);
333  }
334  } else {
335  /* search for config handle */
336  girara_config_handle_t* handle = NULL;
337  GIRARA_LIST_FOREACH(session->config.handles, girara_config_handle_t*, iter, tmp)
338  handle = tmp;
339  if (strcmp(handle->identifier, argv[0]) == 0) {
340  handle->handle(session, argument_list);
341  break;
342  } else {
343  handle = NULL;
344  }
345  GIRARA_LIST_FOREACH_END(session->config.handles, girara_config_handle_t*, iter, tmp);
346 
347  if (handle == NULL) {
348  girara_warning("Could not process line %d in '%s': Unknown handle '%s'", line_number, path, argv[0]);
349  }
350  }
351 
352  line_number++;
353  girara_list_free(argument_list);
354  g_strfreev(argv);
355  free(line);
356  }
357 
358  fclose(file);
359  return true;
360 }
361 
362 void
363 girara_config_parse(girara_session_t* session, const char* path)
364 {
365  config_parse(session, path);
366 }
367