Auto-indent after an HTML/XML line with a missing closing tag (patch

by Eugene Arshinov, thanks).
Behaviour only applies if XML tag autoclosing is off.



git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@5322 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
Nick Treleaven 2010-10-25 16:58:13 +00:00
parent c25d9856fe
commit 3c6212544c
4 changed files with 83 additions and 26 deletions

View File

@ -8,6 +8,10 @@
src/document.c, src/document.h, THANKS, geany.glade:
Add 'Ensure consistent line endings' file saving pref (patch by
Manuel Bua, thanks).
* src/utils.c, src/utils.h, src/editor.c:
Auto-indent after an HTML/XML line with a missing closing tag (patch
by Eugene Arshinov, thanks).
Behaviour only applies if XML tag autoclosing is off.
2010-10-22 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>

View File

@ -1304,6 +1304,37 @@ static gint get_python_indent(ScintillaObject *sci, gint line)
}
static gint get_xml_indent(ScintillaObject *sci, gint line)
{
gboolean need_close = FALSE;
gint end = sci_get_line_end_position(sci, line) - 1;
if (sci_get_char_at(sci, end) == '>' &&
sci_get_char_at(sci, end - 1) != '/')
{
gint style = sci_get_style_at(sci, end);
if (style == SCE_H_TAG || style == SCE_H_TAGUNKNOWN)
{
gint start = sci_get_position_from_line(sci, line);
gchar *line_contents = sci_get_contents_range(sci, start, end + 1);
gchar *opened_tag_name = utils_find_open_xml_tag(line_contents, end + 1 - start);
if (NZV(opened_tag_name))
{
need_close = TRUE;
if (sci_get_lexer(sci) == SCLEX_HTML && utils_is_short_html_tag(opened_tag_name))
need_close = FALSE;
}
g_free(line_contents);
g_free(opened_tag_name);
}
}
return need_close ? 1 : 0;
}
static gint get_indent_size_after_line(GeanyEditor *editor, gint line)
{
ScintillaObject *sci = editor->sci;
@ -1316,11 +1347,25 @@ static gint get_indent_size_after_line(GeanyEditor *editor, gint line)
if (iprefs->auto_indent_mode > GEANY_AUTOINDENT_BASIC)
{
gint additional_indent = 0;
if (lexer_has_braces(sci))
size += iprefs->width * get_brace_indent(sci, line);
additional_indent = iprefs->width * get_brace_indent(sci, line);
else
if (FILETYPE_ID(editor->document->file_type) == GEANY_FILETYPES_PYTHON)
size += iprefs->width * get_python_indent(sci, line);
additional_indent = iprefs->width * get_python_indent(sci, line);
/* HTML lexer "has braces" because of PHP and JavaScript. If get_brace_indent() did not
* recommend us to insert additional indent, we are probably not in PHP/JavaScript chunk and
* should make the XML-related check */
if (additional_indent == 0 && !editor_prefs.auto_close_xml_tags &&
(FILETYPE_ID(editor->document->file_type) == GEANY_FILETYPES_HTML ||
FILETYPE_ID(editor->document->file_type) == GEANY_FILETYPES_XML))
{
size += iprefs->width * get_xml_indent(sci, line);
}
size += additional_indent;
}
return size;
}
@ -2615,7 +2660,7 @@ static gboolean handle_xml(GeanyEditor *editor, gint pos, gchar ch)
{
ScintillaObject *sci = editor->sci;
gint lexer = sci_get_lexer(sci);
gint min, style;
gint min, size, style;
gchar *str_found, sel[512];
gboolean result = FALSE;
@ -2647,19 +2692,12 @@ static gboolean handle_xml(GeanyEditor *editor, gint pos, gchar ch)
/* User typed something like "<br/>" */
return FALSE;
str_found = utils_find_open_xml_tag(sel, pos - min, (ch == '/'));
size = pos - min;
if (ch == '/')
size -= 2; /* skip </ */
str_found = utils_find_open_xml_tag(sel, size);
/* when found string is something like br, img or another short tag, quit */
if (utils_str_equal(str_found, "br")
|| utils_str_equal(str_found, "hr")
|| utils_str_equal(str_found, "img")
|| utils_str_equal(str_found, "base")
|| utils_str_equal(str_found, "basefont") /* < or not < */
|| utils_str_equal(str_found, "frame")
|| utils_str_equal(str_found, "input")
|| utils_str_equal(str_found, "link")
|| utils_str_equal(str_found, "area")
|| utils_str_equal(str_found, "meta"))
if (lexer == SCLEX_HTML && utils_is_short_html_tag(str_found))
{
/* ignore tag */
}

View File

@ -281,7 +281,7 @@ gint utils_write_file(const gchar *filename, const gchar *text)
* Search backward through size bytes looking for a '<', then return the tag, if any.
* @return The tag name
*/
gchar *utils_find_open_xml_tag(const gchar sel[], gint size, gboolean check_tag)
gchar *utils_find_open_xml_tag(const gchar sel[], gint size)
{
const gchar *begin, *cur;
@ -290,10 +290,7 @@ gchar *utils_find_open_xml_tag(const gchar sel[], gint size, gboolean check_tag)
return NULL;
}
begin = &sel[0];
if (check_tag)
cur = &sel[size - 3];
else
cur = &sel[size - 1];
cur = &sel[size-1];
/* Skip to the character before the closing brace */
while (cur > begin)
@ -312,16 +309,18 @@ gchar *utils_find_open_xml_tag(const gchar sel[], gint size, gboolean check_tag)
{
if (*cur == '<')
break;
else if (! check_tag && *cur == '>')
break;
--cur;
}
if (*cur == '<')
{
GString *result = g_string_sized_new(64);
GString *result;
cur++;
if (*cur == '/')
return NULL; /* we found a closing tag */
result = g_string_sized_new(64);
while (strchr(":_-.", *cur) || isalnum(*cur))
{
g_string_append_c(result, *cur);
@ -334,6 +333,22 @@ gchar *utils_find_open_xml_tag(const gchar sel[], gint size, gboolean check_tag)
}
/* Returns true if specified tag doesn't usually contain any content and can be left unclosed */
gboolean utils_is_short_html_tag(const gchar *tag_name)
{
return utils_str_equal(tag_name, "br")
|| utils_str_equal(tag_name, "hr")
|| utils_str_equal(tag_name, "img")
|| utils_str_equal(tag_name, "base")
|| utils_str_equal(tag_name, "basefont") /* < or not < */
|| utils_str_equal(tag_name, "frame")
|| utils_str_equal(tag_name, "input")
|| utils_str_equal(tag_name, "link")
|| utils_str_equal(tag_name, "area")
|| utils_str_equal(tag_name, "meta");
}
const gchar *utils_get_eol_name(gint eol_mode)
{
switch (eol_mode)
@ -2063,5 +2078,3 @@ gchar **utils_strv_join(gchar **first, gchar **second)
g_free(second);
return strv;
}

View File

@ -140,7 +140,9 @@ gboolean utils_is_opening_brace(gchar c, gboolean include_angles);
gint utils_write_file(const gchar *filename, const gchar *text);
gchar *utils_find_open_xml_tag(const gchar sel[], gint size, gboolean check_tag);
gchar *utils_find_open_xml_tag(const gchar sel[], gint size);
gboolean utils_is_short_html_tag(const gchar *tag_name);
void utils_ensure_same_eol_characters(GString *template, gint target_eol_mode);