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
!= '\0'; end
++)
154 if ((*end
== ':') && (*(end
-1) != '\\')) break;
161 while (g_ascii_isspace (*ptr
)) ptr
++;
162 if (ptr
== end
) break;
167 while ((ptr
!= end
) && (*ptr
!= '=') && !g_ascii_isspace(*ptr
)) ptr
++;
175 while ((ptr
!= end
) && !g_ascii_isspace(*ptr
)) ptr
++;
179 if (sep
!= '\0') ptr
++;
182 set_vim_params (params
, key
, value
);
189 set_emacs_params (IndentationParams
*params
, const gchar
*key
, const gchar
*value
)
191 //DEBUG_PRINT ("Setting indent param: %s = %s", key, value);
192 if (strcmp (key
, "indent-tabs-mode") == 0)
194 if (strcmp (value
, "t") == 0)
196 params
->use_spaces
= 0;
197 params
->settings
|= SET_USE_SPACES
;
199 else if (strcmp (value
, "nil") == 0)
201 params
->use_spaces
= 1;
202 params
->settings
|= SET_USE_SPACES
;
205 else if ((strcmp (key
, "c-basic-offset") == 0) ||
206 (strcmp (key
, "indent-offset") == 0))
208 params
->statement_indentation
= atoi (value
);
209 params
->settings
|= SET_STATEMENT_INDENTATION
;
211 else if (strcasecmp (key
, "tab-width") == 0)
213 params
->tab_size
= atoi (value
);
214 params
->settings
|= SET_TAB_SIZE
;
219 parse_emacs_modeline (IndentationParams
*params
, gchar
*line
, gint linenum
)
228 /* If first line is a shebang, check second line */
229 if ((line
[0] == '#') && (line
[1] =='!'))
231 params
->settings
|= CHECK_NEXT
;
235 else if (linenum
!= 2)
237 /* Check only the 2 first lines */
241 ptr
= strstr (line
, "-*-");
242 if (ptr
== NULL
) return FALSE
;
244 end
= strstr (ptr
, "-*-");
245 if (end
== NULL
) return FALSE
;
252 while (g_ascii_isspace (*ptr
)) ptr
++;
253 if (*ptr
== '\0') break;
258 while ((*ptr
!= '\0') && (*ptr
!= ':') && (*ptr
!= ';')) ptr
++;
262 while (g_ascii_isspace (*end
)) end
--;
269 while (g_ascii_isspace (*ptr
)) ptr
++;
273 while ((*ptr
!= '\0') && (*ptr
!= ';')) ptr
++;
277 while (g_ascii_isspace (*end
)) end
--;
280 if (sep
== ';') ptr
++;
284 set_emacs_params (params
, key
, value
);
292 set_indentation (IAnjutaEditor
*editor
, IndentationParams
*params
)
294 if (params
->settings
== 0) return FALSE
;
296 if (params
->settings
& SET_USE_SPACES
)
297 ianjuta_editor_set_use_spaces (editor
, params
->use_spaces
, NULL
);
299 if (params
->settings
& SET_STATEMENT_INDENTATION
)
300 ianjuta_editor_set_indentsize (editor
, params
->statement_indentation
, NULL
);
302 if (params
->settings
& SET_TAB_SIZE
)
303 ianjuta_editor_set_tabsize (editor
, params
->tab_size
, NULL
);
310 *---------------------------------------------------------------------------*/
314 * anjuta_apply_modeline:
315 * @editor: #IAnjutaEditor object
317 * Check the editor buffer to find a mode line and update the indentation
320 * The mode line is special line used by the text editor to define settings for
321 * the current file, typically indentation. Anjuta currently recognize two kinds
324 * Emacs mode line, on the first or the second line if the first one is a
325 * shebang (#!) with the following format:
326 * -*- key1: value1; key2: value2 -*-
328 * Vim mode line, one the first 5 or the last 5 lines with the following format:
329 * vim:set key1=value1 key2=value2
331 * Returns: %TRUE if a mode line has been found and applied.
334 anjuta_apply_modeline (IAnjutaEditor
*editor
)
336 IndentationParams params
= {CHECK_NEXT
,0,0,0};
338 gchar
*content
= NULL
;
340 g_return_val_if_fail (IANJUTA_IS_EDITOR (editor
), FALSE
);
342 /* Check the first lines */
343 for (line
= 1; params
.settings
== CHECK_NEXT
; line
++)
346 content
= get_editor_line (editor
, line
);
347 if (content
== NULL
) return FALSE
;
350 if (parse_vim_modeline (¶ms
, content
, line
)) break;
351 if (parse_emacs_modeline (¶ms
, content
, line
)) break;
354 /* Check the last lines */
355 if (params
.settings
== 0) params
.settings
= CHECK_NEXT
;
356 for (line
= -1;params
.settings
== CHECK_NEXT
; line
--)
359 content
= get_editor_line (editor
, line
);
360 if (content
== NULL
) return FALSE
;
363 if (parse_vim_modeline (¶ms
, content
, line
)) break;
364 if (parse_emacs_modeline (¶ms
, content
, line
)) break;
368 /* Set indentation settings */
369 return set_indentation (editor
, ¶ms
);