File: glspi_doc.c

package info (click to toggle)
geany-plugins 0.19-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 6,864 kB
  • ctags: 3,059
  • sloc: ansic: 30,059; sh: 10,145; makefile: 531; python: 523
file content (343 lines) | stat: -rw-r--r-- 8,200 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
/*
 * glspi_doc.c - This file is part of the Lua scripting plugin for the Geany IDE
 * See the file "geanylua.c" for copyright information.
 */

#define NEED_FAIL_ARG_TYPE
#define NEED_FAIL_ARG_TYPES
#include "glspi.h"


#define NOTEBOOK GTK_NOTEBOOK(main_widgets->notebook)


#ifdef G_OS_WIN32
#define fncmp(a,b) ( a && b && (strcasecmp(a,b)==0))
#else
#define fncmp(a,b) ( a && b && (strcmp(a,b)==0))
#endif



/* Return the filename of the currently active Geany document */
static gint glspi_filename(lua_State* L)
{
	DOC_REQUIRED
	lua_pushstring(L, (const gchar *) doc->file_name);
	return 1;
}


/* Create a new Geany document tab */
static gint glspi_newfile(lua_State* L)
{
	const gchar *fn=NULL;
	if (lua_gettop(L)>0) {
		if (!lua_isstring(L, 1))	{ return FAIL_STRING_ARG(1); }
		fn=lua_tostring(L, 1);
		if ( '\0' == fn[0] ) { fn = NULL; }
	}
	document_new_file(fn, NULL, NULL);
	return 0;
}



/*
	Try to find the geany->documents_array index of the specified filename.
	Returns -1 if the filename doesn't match any open tabs.
*/
static gint filename_to_doc_idx(const gchar*fn)
{
	if (fn && *fn) {
		guint i;
		documents_foreach(i)
		{
			if fncmp(fn,documents[i]->file_name) {return i; }
		}
	}
	return -1;
}


/* Converts a geany->documents_array index to a notebook tab index */
static gint doc_idx_to_tab_idx(gint idx)
{
	return (
		(idx>=0) && ((guint)idx<geany->documents_array->len) && documents[idx]->is_valid
	) ? gtk_notebook_page_num(NOTEBOOK, GTK_WIDGET(documents[idx]->editor->sci)):-1;
}



/* Returns the filename of the specified document, or NULL on bad index */
static const gchar* doc_idx_to_filename(gint idx) {
	if ( (idx >= 0 ) && ( ((guint)idx) < geany->documents_array->len ) ) {
		GeanyDocument *doc=g_ptr_array_index(geany->documents_array, idx);
		if (doc) { return doc->file_name?doc->file_name:GEANY_STRING_UNTITLED; }
	}
	return NULL;
}



/* Actvate and focus the specified document */
static gint glspi_activate(lua_State* L)
{
	gint idx=-1;
	if (lua_gettop(L)>0) {
		if (lua_isnumber(L,1)) {
			idx=(lua_tonumber(L,1));
			if (idx<0) { /* Negative number refers to (absolute) GtkNotebook index */
				idx=(0-idx)-1;
				if (idx>=gtk_notebook_get_n_pages(NOTEBOOK)) { idx=-1;}
			} else { /* A positive number refers to the geany->documents_array index */
				idx=doc_idx_to_tab_idx(idx-1);
			}

		} else {
			if (lua_isstring(L,1)) {
				idx=doc_idx_to_tab_idx(filename_to_doc_idx(lua_tostring(L, 1)));
			} else {
				if (!lua_isnil(L,1)) { return FAIL_STR_OR_NUM_ARG(1); }
			}
		}
	}
	if (idx>=0) {
		if (idx!=gtk_notebook_get_current_page(NOTEBOOK)) {
			gtk_notebook_set_current_page(NOTEBOOK, idx);
		}
	}
	lua_pushboolean(L, (idx>0));
	return 1;
}



/* Lua "closure" function to iterate through the list of open documents */
static gint documents_closure(lua_State *L)
{
	gint idx=lua_tonumber(L, lua_upvalueindex(1));
	int max=geany->documents_array->len;
	do {
		/* Find next valid index, skipping invalid (closed)  files */
		idx++;
	} while (( idx < max ) && !documents[idx]->is_valid );
	if ( idx < max ){
		push_number(L, idx);
		lua_pushvalue(L, -1);
		lua_replace(L, lua_upvalueindex(1));
		lua_pushstring(L,doc_idx_to_filename(idx));
		return 1;
	} else {
		return 0;
	}
}


/* Access the list of open documents */
static gint glspi_documents(lua_State *L)
{
	if (lua_gettop(L)==0) {
		push_number(L,-1);
		lua_pushcclosure(L, &documents_closure, 1);
		return 1;
	} else {
		gint idx;
		const gchar *name;
		DOC_REQUIRED
		if (lua_isnumber(L,1)) {
			idx=lua_tonumber(L,1)-1;
			name=doc_idx_to_filename(idx);
			if (name) {
				lua_pushstring(L,name);
				return 1;
			} else {
				return 0;
			}
		} else {
			if (lua_isstring(L,1)) {
				name=lua_tostring(L,1);
				idx=filename_to_doc_idx(name);
				if (idx>=0) {
					push_number(L,idx+1);
					return 1;
				} else { return 0; }
			} else { return FAIL_STR_OR_NUM_ARG(1); }
		}
	}
}


/* Returns the number of open documents */
static gint glspi_count(lua_State* L)
{
	guint i, n=0;
	documents_foreach(i)
	{
		if (documents[i]->is_valid){n++;}
	}
	push_number(L,n);
	return 1;
}


/* Save a file to disk */
static gint glspi_save(lua_State* L)
{
	gboolean status=FALSE;
	if (lua_gettop(L)==0){
		DOC_REQUIRED
		status=document_save_file(document_get_current(), TRUE);
	} else {
		if (lua_isnumber(L,1)) {
			gint idx=(gint)lua_tonumber(L,1)-1;
			status=document_save_file(documents[idx], TRUE);
		} else {
			if (lua_isstring(L,1)) {
				gint idx=filename_to_doc_idx(lua_tostring(L,1));
				status=document_save_file(documents[idx], TRUE);
			} else { return FAIL_STR_OR_NUM_ARG(1);	}
		}
	}
	lua_pushboolean(L,status);
	return 1;
}


/* Open or reload a file */
static gint glspi_open(lua_State* L)
{
	gint status=-1;
	const gchar*fn=NULL;
	gint idx=-1;

	if (lua_gettop(L)==0) {
		DOC_REQUIRED
		idx=document_get_current()->index;
	} else {
		if (lua_isnumber(L,1)) {
			idx=lua_tonumber(L,1)-1;
		} else {
			if (lua_isstring(L,1)) {
				fn=lua_tostring(L,1);
			} else { return FAIL_STR_OR_NUM_ARG(1); }
		}
	}
	if (!fn) {
		status=document_reload_file(documents[idx],NULL) ? idx : -1;
	} else {
		guint len=geany->documents_array->len;
		GeanyDocument*doc=document_open_file(fn,FALSE,NULL,NULL);
		status=doc?doc->index:-1;
		if ( (status>=0) && (len==geany->documents_array->len))
		{
			/* if len doesn't change, it means we are reloading an already open file */
			/* ntrel: actually, len can stay the same when reusing invalid document slots. */
			idx=document_get_current()->index;
			status=document_reload_file(documents[idx],NULL) ? idx : -1;
		}
	}
	push_number(L,status+1);
	return 1;
}


/* Close a document */
static gint glspi_close(lua_State* L)
{
	gboolean status=FALSE;
	if (lua_gettop(L)==0){
		DOC_REQUIRED
		status=document_close(document_get_current());
	} else {
		if (lua_isnumber(L,1)) {
			guint idx=(guint)lua_tonumber(L,1)-1;
			status=document_close(documents[idx]);
		} else {
			if (lua_isstring(L,1)) {
				guint idx=(guint)filename_to_doc_idx(lua_tostring(L,1));
				status=document_close(documents[idx]);
			} else { return FAIL_STR_OR_NUM_ARG(1);	}
		}
	}
	lua_pushboolean(L,status);
	return 1;
}


#define StrField(rec,field) rec?rec->field?rec->field:"":""

#define FileTypeStr(field) StrField(doc->file_type,field)

#define BuildCmdStr(field) \
	doc->file_type?StrField(doc->file_type->programs,field):""


/* Retrieve Geany's information about an open document */
static gint glspi_fileinfo(lua_State* L)
{
	DOC_REQUIRED
	lua_newtable(L);
	if (doc->file_name) {
		gchar*tmp,*p;
		tmp=g_path_get_dirname (doc->file_name);
		p=strchr(tmp,'\0');
		if (p>tmp) {p--;}
		lua_pushstring(L, "path");
		if (p && (*p==G_DIR_SEPARATOR)){
			lua_pushstring(L, tmp);
		} else {
			lua_pushfstring(L, "%s%s", tmp, G_DIR_SEPARATOR_S);
		}
		lua_rawset(L,-3);
		g_free(tmp);

		tmp=g_path_get_basename (doc->file_name);
		p=strrchr(tmp,'.');
		if (p==tmp) {p=NULL;}
		SetTableStr("name", tmp);
		SetTableStr("ext", p?p:"");
		g_free(tmp);
	} else {
		SetTableStr("name", "")
		SetTableStr("path", "")
	}
	SetTableStr("type",   FileTypeStr(name));
	SetTableStr("desc",   FileTypeStr(title));
	SetTableStr("opener", FileTypeStr(comment_open));
	SetTableStr("closer", FileTypeStr(comment_close));
	SetTableStr("action", FileTypeStr(context_action_cmd));
/*
	SetTableStr("compiler", BuildCmdStr(compiler));
	SetTableStr("linker",   BuildCmdStr(linker));
	SetTableStr("exec",     BuildCmdStr(run_cmd));
	SetTableStr("exec2",    BuildCmdStr(run_cmd2));
*/
	SetTableNum("ftid", GPOINTER_TO_INT(doc->file_type?doc->file_type->id:GEANY_FILETYPES_NONE));
	SetTableStr("encoding", StrField(doc,encoding));
	SetTableBool("bom",doc->has_bom);
	SetTableBool("changed",doc->changed);
	SetTableBool("readonly",doc->readonly);
	return 1;
}




static const struct luaL_reg glspi_doc_funcs[] = {
	{"filename",  glspi_filename},
	{"fileinfo",  glspi_fileinfo},
	{"documents", glspi_documents},
	{"count",     glspi_count},
	{"activate",  glspi_activate},
	{"newfile",   glspi_newfile},
	{"save",      glspi_save},
	{"open",      glspi_open},
	{"close",     glspi_close},
	{NULL,NULL}
};

void glspi_init_doc_funcs(lua_State *L) {
	luaL_register(L, NULL,glspi_doc_funcs);
}