1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Sébastien Granjoux 2013 <seb.sfo@free.fr>
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
21 * SECTION:anjuta-modeline
22 * @short_description: Parse editor mode line
24 * @stability: Unstable
25 * @include: libanjuta/anjuta-modeline.h
29 #include "anjuta-modeline.h"
31 #include "anjuta-debug.h"
33 #include <glib-object.h>
39 *---------------------------------------------------------------------------*/
42 SET_USE_SPACES
= 1 << 0,
43 SET_STATEMENT_INDENTATION
= 1 << 1,
44 SET_TAB_SIZE
= 1 << 2,
52 gint statement_indentation
;
58 *---------------------------------------------------------------------------*/
61 *---------------------------------------------------------------------------*/
64 get_editor_line (IAnjutaEditor
*editor
, gint line
)
66 IAnjutaIterable
*start
;
68 gchar
*content
= NULL
;
74 end
= ianjuta_editor_get_end_position(editor
, NULL
);
75 last
= ianjuta_editor_get_line_from_position (editor
, end
, NULL
);
81 start
= ianjuta_editor_get_line_begin_position (editor
, line
, NULL
);
82 end
= ianjuta_editor_get_line_end_position (editor
, line
, NULL
);
83 content
= ianjuta_editor_get_text (editor
, start
, end
, NULL
);
84 g_object_unref (start
);
92 set_vim_params (IndentationParams
*params
, const gchar
*key
, const gchar
*value
)
94 //DEBUG_PRINT ("Setting indent param: %s = %s", key, value);
95 if ((strcmp (key
, "expandtab") == 0) ||
96 (strcmp (key
, "et") == 0))
98 params
->use_spaces
= 1;
99 params
->settings
|= SET_USE_SPACES
;
101 else if ((strcmp (key
, "noexpandtab") == 0) ||
102 (strcmp (key
, "noet") == 0))
104 params
->use_spaces
= 0;
105 params
->settings
|= SET_USE_SPACES
;
107 else if ((strcmp (key
, "shiftwidth") == 0) ||
108 (strcmp (key
, "sw") == 0))
110 params
->statement_indentation
= atoi (value
);
111 params
->settings
|= SET_STATEMENT_INDENTATION
;
113 else if ((strcmp (key
, "softtabstop") == 0) ||
114 (strcmp (key
, "sts") == 0) ||
115 (strcmp (key
, "tabstop") == 0) ||
116 (strcmp (key
, "ts") == 0))
118 params
->tab_size
= atoi (value
);
119 params
->settings
|= SET_TAB_SIZE
;
124 parse_vim_modeline (IndentationParams
*params
, const gchar
*line
, gint linenum
)
131 /* Check the first 5 and last 5 lines */
132 if ((linenum
< -5) || (linenum
== 0) || (linenum
> 5))
137 ptr
= strstr (line
, "vim:");
140 if ((linenum
!= -5) && (linenum
!= 5)) params
->settings
= CHECK_NEXT
;
144 while (g_ascii_isspace (*ptr
)) ptr
++;
145 if (strncmp (ptr
, "set", 3) != 0)
147 if ((linenum
!= -5) && (linenum
!= 5)) params
->settings
= CHECK_NEXT
;
152 for (end
= ptr
;; end
++)
154 if ((*end
== ':') && (*(end
-1) != '\\')) break;
162 while (g_ascii_isspace (*ptr
)) ptr
++;
163 if (*ptr
== '\0') break;
168 while ((*ptr
!= '\0') && (*ptr
!= '=') && !g_ascii_isspace(*ptr
)) ptr
++;
176 while ((*ptr
!= '\0') && !g_ascii_isspace(*ptr
)) ptr
++;
180 if (sep
!= '\0') ptr
++;
183 set_vim_params (params
, key
, value
);
190 set_emacs_params (IndentationParams
*params
, const gchar
*key
, const gchar
*value
)
192 //DEBUG_PRINT ("Setting indent param: %s = %s", key, value);
193 if (strcmp (key
, "indent-tabs-mode") == 0)
195 if (strcmp (value
, "t") == 0)
197 params
->use_spaces
= 0;
198 params
->settings
|= SET_USE_SPACES
;
200 else if (strcmp (value
, "nil") == 0)
202 params
->use_spaces
= 1;
203 params
->settings
|= SET_USE_SPACES
;
206 else if ((strcmp (key
, "c-basic-offset") == 0) ||
207 (strcmp (key
, "indent-offset") == 0))
209 params
->statement_indentation
= atoi (value
);
210 params
->settings
|= SET_STATEMENT_INDENTATION
;
212 else if (strcasecmp (key
, "tab-width") == 0)
214 params
->tab_size
= atoi (value
);
215 params
->settings
|= SET_TAB_SIZE
;
220 parse_emacs_modeline (IndentationParams
*params
, gchar
*line
, gint linenum
)
229 /* If first line is a shebang, check second line */
230 if ((line
[0] == '#') && (line
[1] =='!'))
232 params
->settings
|= CHECK_NEXT
;
236 else if (linenum
!= 2)
238 /* Check only the 2 first lines */
242 ptr
= strstr (line
, "-*-");
243 if (ptr
== NULL
) return FALSE
;
245 end
= strstr (ptr
, "-*-");
246 if (end
== NULL
) return FALSE
;
253 while (g_ascii_isspace (*ptr
)) ptr
++;
254 if (*ptr
== '\0') break;
259 while ((*ptr
!= '\0') && (*ptr
!= ':') && (*ptr
!= ';')) ptr
++;
263 while (g_ascii_isspace (*end
)) end
--;
270 while (g_ascii_isspace (*ptr
)) ptr
++;
274 while ((*ptr
!= '\0') && (*ptr
!= ';')) ptr
++;
278 while (g_ascii_isspace (*end
)) end
--;
281 if (sep
== ';') ptr
++;
285 set_emacs_params (params
, key
, value
);
293 set_indentation (IAnjutaEditor
*editor
, IndentationParams
*params
)
295 if (params
->settings
== 0) return FALSE
;
297 if (params
->settings
& SET_USE_SPACES
)
298 ianjuta_editor_set_use_spaces (editor
, params
->use_spaces
, NULL
);
300 if (params
->settings
& SET_STATEMENT_INDENTATION
)
301 ianjuta_editor_set_indentsize (editor
, params
->statement_indentation
, NULL
);
303 if (params
->settings
& SET_TAB_SIZE
)
304 ianjuta_editor_set_tabsize (editor
, params
->tab_size
, NULL
);
311 *---------------------------------------------------------------------------*/
315 * anjuta_apply_modeline:
316 * @editor: #IAnjutaEditor object
318 * Check the editor buffer to find a mode line and update the indentation
321 * The mode line is special line used by the text editor to define settings for
322 * the current file, typically indentation. Anjuta currently recognize two kinds
325 * Emacs mode line, on the first or the second line if the first one is a
326 * shebang (#!) with the following format:
327 * -*- key1: value1; key2: value2 -*-
329 * Vim mode line, one the first 5 or the last 5 lines with the following format:
330 * vim:set key1=value1 key2=value2
332 * Returns: %TRUE if a mode line has been found and applied.
335 anjuta_apply_modeline (IAnjutaEditor
*editor
)
337 IndentationParams params
= {CHECK_NEXT
,0,0,0};
339 gchar
*content
= NULL
;
341 g_return_val_if_fail (IANJUTA_IS_EDITOR (editor
), FALSE
);
343 /* Check the first lines */
344 for (line
= 1; params
.settings
== CHECK_NEXT
; line
++)
347 content
= get_editor_line (editor
, line
);
348 if (content
== NULL
) return FALSE
;
351 if (parse_vim_modeline (¶ms
, content
, line
)) break;
352 if (parse_emacs_modeline (¶ms
, content
, line
)) break;
355 /* Check the last lines */
356 if (params
.settings
== 0) params
.settings
= CHECK_NEXT
;
357 for (line
= -1;params
.settings
== CHECK_NEXT
; line
--)
360 content
= get_editor_line (editor
, line
);
361 if (content
== NULL
) return FALSE
;
364 if (parse_vim_modeline (¶ms
, content
, line
)) break;
365 if (parse_emacs_modeline (¶ms
, content
, line
)) break;
369 /* Set indentation settings */
370 return set_indentation (editor
, ¶ms
);