completion.c 4.34 KB
Newer Older
Moritz Lipp's avatar
Moritz Lipp committed
1
/* See LICENSE file for license and copyright information */
2
3
4
5

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
Moritz Lipp's avatar
Moritz Lipp committed
6
#include <libgen.h>
7
8
9
10
11
12
13
14
15
16

#include "completion.h"
#include "utils.h"

girara_completion_t*
cc_print(girara_session_t* session, char* input)
{
  girara_completion_t* completion  = girara_completion_init();
  girara_completion_group_t* group = girara_completion_group_create(session, NULL);

Moritz Lipp's avatar
Moritz Lipp committed
17
  if (!session || !input || !completion || !group)
18
19
20
21
22
23
24
25
26
    return NULL;

  girara_completion_add_group(completion, group);

  char* const list_printers[] = {
    "lpstat", "-v", NULL
  };

  char* output;
Moritz Lipp's avatar
Moritz Lipp committed
27
  if (!execute_command(list_printers, &output)) {
28
29
30
31
32
33
34
35
36
    girara_completion_free(completion);
    return false;
  }

  /* parse single lines */
  unsigned int prefix_length = strlen("device for ");
  char* p = strtok(output, "\n");
  char* q;

Moritz Lipp's avatar
Moritz Lipp committed
37
38
  while (p) {
    if (!(p = strstr(p, "device for ")) || !(q = strchr(p, ':'))) {
39
40
41
42
43
44
45
      p = strtok(NULL, "\n");
      continue;
    }

    unsigned int printer_length = q - p - prefix_length;
    char* printer_name = malloc(sizeof(char) * printer_length);

Moritz Lipp's avatar
Moritz Lipp committed
46
    if (!printer_name) {
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
      p = strtok(NULL, "\n");
      continue;
    }

    strncpy(printer_name, p + prefix_length, printer_length - 1);
    printer_name[printer_length - 1] = '\0';

    /* add printer */
    girara_completion_group_add_element(group, printer_name, NULL);

    free(printer_name);

    /* next line */
    p = strtok(NULL, "\n");
  }

  free(output);

  return completion;
}
67
68
69
70

girara_completion_t*
cc_open(girara_session_t* session, char* input)
{
71
72
73
74
  g_return_val_if_fail(session != NULL, NULL);
  g_return_val_if_fail(session->global.data != NULL, NULL);
  zathura_t* zathura = session->global.data;

75
76
77
  girara_completion_t* completion  = girara_completion_init();
  girara_completion_group_t* group = girara_completion_group_create(session, NULL);

Moritz Lipp's avatar
Moritz Lipp committed
78
  if (completion == NULL || group == NULL) {
79
80
81
82
    goto error_free;
  }

  gchar* path = girara_fix_path(input);
Moritz Lipp's avatar
Moritz Lipp committed
83
  if (path == NULL) {
84
85
86
87
88
    goto error_free;
  }

  /* If the path does not begin with a slash we update the path with the current
   * working directory */
Moritz Lipp's avatar
Moritz Lipp committed
89
  if (strlen(path) == 0 || path[0] != '/') {
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
    size_t path_max;
#ifdef PATH_MAX
    path_max = PATH_MAX;
#else
    path_max = pathconf(path,_PC_PATH_MAX);
    if (path_max <= 0)
      path_max = 4096;
#endif

    char cwd[path_max];
    getcwd(cwd, path_max);

    char* tmp_path = g_strdup_printf("%s/%s", cwd, path);
    if (tmp_path == NULL) {
      goto error_free;
    }

    g_free(path);
    path = tmp_path;
  }

Moritz Lipp's avatar
Moritz Lipp committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  /* Append a slash if the given argument is a directory */
  if ((g_file_test(path, G_FILE_TEST_IS_DIR) == TRUE) &&
      (path[strlen(path) - 1] != '/')) {
    char* tmp_path = g_strdup_printf("%s/", path);
    if (tmp_path == NULL) {
      goto error_free;
    }

    g_free(path);
    path = tmp_path;
  }

  gchar* current_path     = (path[strlen(path)-1] == '/') ? path : dirname(path);
  gchar* current_file     = (path[strlen(path)-1] == '/') ? ""   : basename(path);
  int current_file_length = strlen(current_file);

127
  /* read directory */
Moritz Lipp's avatar
Moritz Lipp committed
128
129
  if (g_file_test(current_path, G_FILE_TEST_IS_DIR) == TRUE) {
    GDir* dir = g_dir_open(current_path, 0, NULL);
130
131
132
133
134
135
136
    if (dir == NULL) {
      goto error_free;
    }

    /* read files */
    char* name = NULL;
    while ((name = (char*) g_dir_read_name(dir)) != NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
137
138
139
      char* e_name   = g_filename_display_name(name);
      int   e_length = strlen(e_name);

140
141
142
143
      if (e_name == NULL) {
        goto error_free;
      }

Moritz Lipp's avatar
Moritz Lipp committed
144
      char* full_path = g_strdup_printf("%s%s", current_path, e_name);
145
      if (full_path == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
146
        g_free(e_name);
147
148
149
        goto error_free;
      }

Moritz Lipp's avatar
Moritz Lipp committed
150
151
152
153
154
155
      if (g_file_test(full_path, G_FILE_TEST_IS_DIR) == true) {
        char* tmp_path = full_path;
        full_path = g_strdup_printf("%s/", full_path);
        g_free(tmp_path);
        girara_completion_group_add_element(group, full_path, NULL);
      } else if (file_valid_extension(zathura, full_path) == true) {
156
157
158
159
        girara_completion_group_add_element(group, full_path, NULL);
      }

      g_free(full_path);
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
      g_free(e_name);
    }

    g_dir_close(dir);
  }

  g_free(path);

  girara_completion_add_group(completion, group);

  return completion;

error_free:

  if (completion) {
    girara_completion_free(completion);
  }
  if (group) {
    girara_completion_group_free(group);
  }

  g_free(path);

  return NULL;
}