Add 'Reflow lines/paragraph' keybinding, defaults to Ctrl-J.

Heavily based on a patch by Eugene Arshinov (thanks).
Add sci_lines_split(), sci_lines_join(), sci_text_width(),
editor_strip_line_trailing_spaces().



git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@4025 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
Nick Treleaven 2009-07-24 15:44:14 +00:00
parent 88ae507faf
commit aa89783b74
10 changed files with 193 additions and 10 deletions

View File

@ -4,6 +4,13 @@
Use full styleset_foo[_init] function name as argument to
init_styleset_case() and styleset_case() macros so it's easier to
understand the code.
* src/keybindings.c, src/keybindings.h, src/sciwrappers.c,
src/sciwrappers.h, src/editor.c, src/editor.h, THANKS,
doc/geany.txt, doc/geany.html:
Add 'Reflow lines/paragraph' keybinding, defaults to Ctrl-J.
Heavily based on a patch by Eugene Arshinov (thanks).
Add sci_lines_split(), sci_lines_join(), sci_text_width(),
editor_strip_line_trailing_spaces().
2009-07-24 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>

2
THANKS
View File

@ -65,7 +65,7 @@ Chris Macksey <cmacksey(at)users(dot)sourceforge(dot)net> - ActionScript filetyp
Simon Treny <simon(dot)treny(at)free(dot)fr> - Documents sidebar stock icons patch
Elias Pschernig <elias(at)users(dot)sourceforge(dot)net> - Recent Projects menu patch
Jesse Mayes <plasmasheep(at)gmail(dot)com> - Tango'ish Save All icon
Eugene Arshinov <earshinov(at)gmail(dot)com> - Reload color schemes via menu patch
Eugene Arshinov <earshinov(at)gmail(dot)com> - Reload color schemes, split lines KB patches
Translators:
------------

View File

@ -6,7 +6,7 @@
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>Geany</title>
<meta name="authors" content="Enrico Tröger Nick Treleaven Frank Lanitz" />
<meta name="date" content="2009-07-09" />
<meta name="date" content="2009-07-14" />
<style type="text/css">
/*
@ -139,7 +139,7 @@ Stylesheet for Geany's documentation based on a version of John Gabriele.
<br />Nick Treleaven
<br />Frank Lanitz</td></tr>
<tr><th class="docinfo-name">Date:</th>
<td>2009-07-09</td></tr>
<td>2009-07-14</td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>0.18</td></tr>
</tbody>
@ -2956,6 +2956,11 @@ details).</td>
line (if there is no selection) to the
embedded Terminal (VTE).</td>
</tr>
<tr><td>Reflow lines/paragraph</td>
<td>&nbsp;</td>
<td>Reformat selected lines or current paragraph,
breaking lines at the long line marker.</td>
</tr>
<tr><td><strong>Settings</strong></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
@ -4983,7 +4988,7 @@ USE OR PERFORMANCE OF THIS SOFTWARE.</p>
<div class="footer">
<hr class="footer" />
<a class="reference" href="geany.txt">View document source</a>.
Generated on: 2009-07-14 11:22 UTC.
Generated on: 2009-07-24 15:29 UTC.
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
</div>

View File

@ -2678,6 +2678,9 @@ Send Selection to Terminal Sends the current sele
line (if there is no selection) to the
embedded Terminal (VTE).
Reflow lines/paragraph Reformat selected lines or current paragraph,
breaking lines at the long line marker.
**Settings**

View File

@ -101,7 +101,6 @@ static void auto_table(GeanyEditor *editor, gint pos);
static void close_block(GeanyEditor *editor, gint pos);
static void editor_highlight_braces(GeanyEditor *editor, gint cur_pos);
static void editor_auto_latex(GeanyEditor *editor, gint pos);
static void editor_strip_line_trailing_spaces(GeanyEditor *editor, gint line);
void editor_snippets_free(void)
@ -4307,7 +4306,7 @@ void editor_replace_spaces(GeanyEditor *editor)
}
static void editor_strip_line_trailing_spaces(GeanyEditor *editor, gint line)
void editor_strip_line_trailing_spaces(GeanyEditor *editor, gint line)
{
gint line_start = sci_get_position_from_line(editor->sci, line);
gint line_end = sci_get_line_end_position(editor->sci, line);

View File

@ -100,7 +100,7 @@ typedef struct GeanyEditorPrefs
gboolean show_white_space;
gboolean show_indent_guide;
gboolean show_line_endings;
gint long_line_type;
gint long_line_type; /* 0 - line, 1 - background, 2 - none */
gint long_line_column;
gchar *long_line_color;
gboolean show_markers_margin; /* view menu */
@ -251,6 +251,8 @@ void editor_replace_tabs(GeanyEditor *editor);
void editor_replace_spaces(GeanyEditor *editor);
void editor_strip_line_trailing_spaces(GeanyEditor *editor, gint line);
void editor_strip_trailing_spaces(GeanyEditor *editor);
void editor_ensure_final_newline(GeanyEditor *editor);

View File

@ -320,6 +320,8 @@ static void init_default_kb(void)
GDK_3, GDK_CONTROL_MASK, "edit_sendtocmd3", _("Send to Custom Command 3"), NULL);
keybindings_set_item(group, GEANY_KEYS_FORMAT_SENDTOVTE, cb_func_format_action,
0, 0, "edit_sendtovte", _("Send Selection to Terminal"), LW(send_selection_to_vte1));
keybindings_set_item(group, GEANY_KEYS_FORMAT_REFLOWPARAGRAPH, cb_func_format_action,
GDK_j, GDK_CONTROL_MASK, "format_reflowparagraph", _("Reflow lines/paragraph"), NULL);
group = ADD_KB_GROUP(INSERT, _("Insert"));
@ -1910,6 +1912,145 @@ static void cb_func_editor_action(guint key_id)
}
static void join_lines(GeanyEditor *editor)
{
gint start, end, i;
start = sci_get_line_from_position(editor->sci,
sci_get_selection_start(editor->sci));
end = sci_get_line_from_position(editor->sci,
sci_get_selection_end(editor->sci));
/* if there is only one line in selection, join it with the following one */
if (end == start)
end = start + 1;
/*
* remove trailing spaces for every line except the last one
* so that these spaces won't appear within text after joining
*/
for (i = start; i < end; i++)
editor_strip_line_trailing_spaces(editor, i);
/* remove starting spaces from second and following lines due to the same reason */
for (i = start+1; i <= end; i++)
sci_set_line_indentation(editor->sci, i, 0);
/*
* SCI_LINESJOIN automatically adds spaces between joined lines, including
* empty ones. We should drop empty lines if we want only one space to be
* inserted (see also example below). I don't think we should care of that.
*/
sci_target_start(editor->sci,
sci_get_position_from_line(editor->sci, start));
sci_target_end(editor->sci,
sci_get_position_from_line(editor->sci, end));
sci_lines_join(editor->sci);
/*
* Example: joining
*
* [TAB]if (something_wrong)
* [TAB]{
* [TAB][TAB]
* [TAB][TAB]exit(1);[SPACE][SPACE]
* [TAB]}[SPACE]
*
* gives
*
* [TAB]if (something_wrong) { exit(1); }[SPACE]
*/
}
static void split_lines(GeanyEditor *editor)
{
gint start, indent, linescount, i;
/* do nothing if long line marker is disabled */
if (editor_prefs.long_line_type == 2)
return;
start = sci_get_line_from_position(editor->sci,
sci_get_selection_start(editor->sci));
/*
* If several lines are selected, first join them.
* This allows to reformat text paragraphs easily.
*/
if (sci_get_lines_selected(editor->sci) > 1)
join_lines(editor);
/*
* If this line is short enough, just return
*/
if (editor_prefs.long_line_column >
sci_get_line_end_position(editor->sci, start) -
sci_get_position_from_line(editor->sci, start))
{
return;
}
/*
* We have to manipulate line indentation so that indentation
* of the resulting lines would be consistent. For example,
* the result of splitting "[TAB]very long content":
*
* +-------------+-------------+
* | proper | wrong |
* +-------------+-------------+
* | [TAB]very | [TAB]very |
* | [TAB]long | long |
* | [TAB]content| content |
* +-------------+-------------+
*/
indent = sci_get_line_indentation(editor->sci, start);
sci_set_line_indentation(editor->sci, start, 0);
/*
* Use sci_get_line_count() to determine how many new lines
* appeared during splitting. SCI_LINESSPLIT should better return
* this value itself...
*/
sci_target_from_selection(editor->sci);
linescount = sci_get_line_count(editor->sci);
sci_lines_split(editor->sci,
(editor_prefs.long_line_column - indent) *
sci_text_width(editor->sci, STYLE_DEFAULT, " "));
linescount = sci_get_line_count(editor->sci) - linescount;
/* Fix indentation. */
for (i = start; i <= start + linescount; i++)
sci_set_line_indentation(editor->sci, i, indent);
}
static void reflow_paragraph(GeanyEditor *editor)
{
ScintillaObject *sci = editor->sci;
gboolean sel;
sci_start_undo_action(sci);
sel = sci_has_selection(sci);
if (!sel)
{
gint line, pos;
keybindings_send_command(GEANY_KEY_GROUP_SELECT, GEANY_KEYS_SELECT_PARAGRAPH);
/* deselect last line break */
pos = sci_get_selection_end(sci);
line = sci_get_line_from_position(sci, pos);
pos = sci_get_line_end_position(sci, line - 1);
sci_set_selection_end(sci, pos);
}
split_lines(editor);
if (!sel)
sci_set_anchor(sci, -1);
sci_end_undo_action(sci);
}
/* common function for format keybindings, only valid when scintilla has focus. */
static void cb_func_format_action(guint key_id)
{
@ -1964,6 +2105,9 @@ static void cb_func_format_action(guint key_id)
case GEANY_KEYS_FORMAT_SENDTOVTE:
on_send_selection_to_vte1_activate(NULL, NULL);
break;
case GEANY_KEYS_FORMAT_REFLOWPARAGRAPH:
reflow_paragraph(doc->editor);
break;
}
}

View File

@ -174,6 +174,7 @@ enum
GEANY_KEYS_FORMAT_SENDTOCMD2,
GEANY_KEYS_FORMAT_SENDTOCMD3,
GEANY_KEYS_FORMAT_SENDTOVTE,
GEANY_KEYS_FORMAT_REFLOWPARAGRAPH,
GEANY_KEYS_FORMAT_COUNT
};

View File

@ -46,8 +46,9 @@ void sci_set_line_numbers(ScintillaObject * sci, gboolean set, gint extra_width)
gchar tmp_str[15];
gint len = SSM(sci, SCI_GETLINECOUNT, 0, 0);
gint width;
g_snprintf(tmp_str, 15, "_%d%d", len, extra_width);
width = SSM(sci, SCI_TEXTWIDTH, STYLE_LINENUMBER, (sptr_t) tmp_str);
width = sci_text_width(sci, STYLE_LINENUMBER, tmp_str);
SSM (sci, SCI_SETMARGINWIDTHN, 0, width);
SSM (sci, SCI_SETMARGINSENSITIVEN, 0, FALSE); /* use default behaviour */
}
@ -709,8 +710,12 @@ void sci_set_search_anchor(ScintillaObject *sci)
}
/* removes a selection if pos < 0 */
void sci_set_anchor(ScintillaObject *sci, gint pos)
{
if (pos < 0)
pos = sci_get_current_position(sci);
SSM(sci, SCI_SETANCHOR, pos, 0);
}
@ -863,7 +868,7 @@ void sci_target_from_selection(ScintillaObject *sci)
}
void sci_target_start(ScintillaObject *sci, gint start)
void sci_target_start(ScintillaObject *sci, gint start)
{
SSM(sci, SCI_SETTARGETSTART, start, 0);
}
@ -1084,4 +1089,17 @@ gint sci_get_position_after(ScintillaObject *sci, gint start)
return SSM(sci, SCI_POSITIONAFTER, start, 0);
}
void sci_lines_split(ScintillaObject *sci, gint pixelWidth)
{
SSM(sci, SCI_LINESSPLIT, pixelWidth, 0);
}
void sci_lines_join(ScintillaObject *sci)
{
SSM(sci, SCI_LINESJOIN, 0, 0);
}
gint sci_text_width(ScintillaObject *sci, gint styleNumber, const gchar *text)
{
return SSM(sci, SCI_TEXTWIDTH, styleNumber, (sptr_t) text);
}

View File

@ -59,7 +59,7 @@ gint sci_marker_previous (ScintillaObject* sci, gint line, gint marker_mask
gint sci_get_col_from_position (ScintillaObject* sci, gint position);
gint sci_get_line_from_position (ScintillaObject* sci, gint position);
gint sci_get_position_from_line (ScintillaObject* sci, gint line );
gint sci_get_position_from_line (ScintillaObject* sci, gint line);
gint sci_get_current_position (ScintillaObject* sci);
void sci_set_current_position (ScintillaObject* sci, gint position, gboolean scroll_to_caret);
void sci_set_current_line (ScintillaObject* sci, gint line);
@ -176,4 +176,8 @@ void sci_cancel (ScintillaObject *sci);
gint sci_get_target_end (ScintillaObject *sci);
gint sci_get_position_after (ScintillaObject *sci, gint start);
void sci_lines_split (ScintillaObject *sci, gint pixelWidth);
void sci_lines_join (ScintillaObject *sci);
gint sci_text_width (ScintillaObject *sci, int styleNumber, const char * text);
#endif