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 Use full styleset_foo[_init] function name as argument to
init_styleset_case() and styleset_case() macros so it's easier to init_styleset_case() and styleset_case() macros so it's easier to
understand the code. 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> 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 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 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 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: Translators:
------------ ------------

View File

@ -6,7 +6,7 @@
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" /> <meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>Geany</title> <title>Geany</title>
<meta name="authors" content="Enrico Tröger Nick Treleaven Frank Lanitz" /> <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"> <style type="text/css">
/* /*
@ -139,7 +139,7 @@ Stylesheet for Geany's documentation based on a version of John Gabriele.
<br />Nick Treleaven <br />Nick Treleaven
<br />Frank Lanitz</td></tr> <br />Frank Lanitz</td></tr>
<tr><th class="docinfo-name">Date:</th> <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> <tr><th class="docinfo-name">Version:</th>
<td>0.18</td></tr> <td>0.18</td></tr>
</tbody> </tbody>
@ -2956,6 +2956,11 @@ details).</td>
line (if there is no selection) to the line (if there is no selection) to the
embedded Terminal (VTE).</td> embedded Terminal (VTE).</td>
</tr> </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> <tr><td><strong>Settings</strong></td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td> <td>&nbsp;</td>
@ -4983,7 +4988,7 @@ USE OR PERFORMANCE OF THIS SOFTWARE.</p>
<div class="footer"> <div class="footer">
<hr class="footer" /> <hr class="footer" />
<a class="reference" href="geany.txt">View document source</a>. <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. 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> </div>

View File

@ -2678,6 +2678,9 @@ Send Selection to Terminal Sends the current sele
line (if there is no selection) to the line (if there is no selection) to the
embedded Terminal (VTE). embedded Terminal (VTE).
Reflow lines/paragraph Reformat selected lines or current paragraph,
breaking lines at the long line marker.
**Settings** **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 close_block(GeanyEditor *editor, gint pos);
static void editor_highlight_braces(GeanyEditor *editor, gint cur_pos); static void editor_highlight_braces(GeanyEditor *editor, gint cur_pos);
static void editor_auto_latex(GeanyEditor *editor, gint 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) 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_start = sci_get_position_from_line(editor->sci, line);
gint line_end = sci_get_line_end_position(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_white_space;
gboolean show_indent_guide; gboolean show_indent_guide;
gboolean show_line_endings; gboolean show_line_endings;
gint long_line_type; gint long_line_type; /* 0 - line, 1 - background, 2 - none */
gint long_line_column; gint long_line_column;
gchar *long_line_color; gchar *long_line_color;
gboolean show_markers_margin; /* view menu */ gboolean show_markers_margin; /* view menu */
@ -251,6 +251,8 @@ void editor_replace_tabs(GeanyEditor *editor);
void editor_replace_spaces(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_strip_trailing_spaces(GeanyEditor *editor);
void editor_ensure_final_newline(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); 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, 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)); 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")); 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. */ /* common function for format keybindings, only valid when scintilla has focus. */
static void cb_func_format_action(guint key_id) 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: case GEANY_KEYS_FORMAT_SENDTOVTE:
on_send_selection_to_vte1_activate(NULL, NULL); on_send_selection_to_vte1_activate(NULL, NULL);
break; 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_SENDTOCMD2,
GEANY_KEYS_FORMAT_SENDTOCMD3, GEANY_KEYS_FORMAT_SENDTOCMD3,
GEANY_KEYS_FORMAT_SENDTOVTE, GEANY_KEYS_FORMAT_SENDTOVTE,
GEANY_KEYS_FORMAT_REFLOWPARAGRAPH,
GEANY_KEYS_FORMAT_COUNT 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]; gchar tmp_str[15];
gint len = SSM(sci, SCI_GETLINECOUNT, 0, 0); gint len = SSM(sci, SCI_GETLINECOUNT, 0, 0);
gint width; gint width;
g_snprintf(tmp_str, 15, "_%d%d", len, extra_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_SETMARGINWIDTHN, 0, width);
SSM (sci, SCI_SETMARGINSENSITIVEN, 0, FALSE); /* use default behaviour */ 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) void sci_set_anchor(ScintillaObject *sci, gint pos)
{ {
if (pos < 0)
pos = sci_get_current_position(sci);
SSM(sci, SCI_SETANCHOR, pos, 0); 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); 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); 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_col_from_position (ScintillaObject* sci, gint position);
gint sci_get_line_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); gint sci_get_current_position (ScintillaObject* sci);
void sci_set_current_position (ScintillaObject* sci, gint position, gboolean scroll_to_caret); void sci_set_current_position (ScintillaObject* sci, gint position, gboolean scroll_to_caret);
void sci_set_current_line (ScintillaObject* sci, gint line); 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_target_end (ScintillaObject *sci);
gint sci_get_position_after (ScintillaObject *sci, gint start); 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 #endif