diff --git a/vimode/README b/vimode/README index db6008e65..92573928c 100644 --- a/vimode/README +++ b/vimode/README @@ -96,7 +96,7 @@ This is an incomplete list of known limitations of the plugin: * named registers and related commands are not implemented * Ctrl+X mode is not implemented * marks are not implemented -* fold commands are not implemented +* many fold commands are not implemented * most commands starting with "'", "z", and "g" are not implemented * most ex mode commands are not implemented (excluding basic stuff like search, replace, saving, etc.) @@ -501,7 +501,16 @@ a new command, please do not forget to update the table below.:: cursor on first non-blank z. z. redraw, cursor line to center of window, cursor on first non-blank + zA zA open a closed fold or close an open fold + recursively + zC zC close folds recursively + zM zM set 'foldlevel' to zero + zO zO open folds recursively + zR zR set 'foldlevel' to the deepest fold + za za open a closed fold, close an open fold zb zb redraw, cursor line at bottom of window + zc zc close a fold + zo zo open fold zt zt redraw, cursor line at top of window zz zz redraw, cursor line at center of window diff --git a/vimode/src/Makefile.am b/vimode/src/Makefile.am index c6107cb27..375743388 100644 --- a/vimode/src/Makefile.am +++ b/vimode/src/Makefile.am @@ -37,7 +37,9 @@ vi_srcs = \ cmds/excmds.h \ cmds/excmds.c \ cmds/undo.h \ - cmds/undo.c + cmds/undo.c \ + cmds/fold.h \ + cmds/fold.c vimode_la_SOURCES = \ backends/backend-geany.c \ diff --git a/vimode/src/cmd-runner.c b/vimode/src/cmd-runner.c index a1195a028..05eaf450b 100644 --- a/vimode/src/cmd-runner.c +++ b/vimode/src/cmd-runner.c @@ -25,6 +25,7 @@ #include "cmds/changemode.h" #include "cmds/edit.h" #include "cmds/special.h" +#include "cmds/fold.h" #include @@ -262,6 +263,15 @@ CmdDef text_object_cmds[] = { {cmd_copy_line, GDK_KEY_Y, 0, 0, 0, FALSE, FALSE}, \ {cmd_paste_after, GDK_KEY_p, 0, 0, 0, FALSE, FALSE}, \ {cmd_paste_before, GDK_KEY_P, 0, 0, 0, FALSE, FALSE}, \ + /* fold */ \ + {cmd_toggle_fold, GDK_KEY_z, GDK_KEY_a, 0, 0, FALSE, FALSE}, \ + {cmd_open_fold, GDK_KEY_z, GDK_KEY_o, 0, 0, FALSE, FALSE}, \ + {cmd_close_fold, GDK_KEY_z, GDK_KEY_c, 0, 0, FALSE, FALSE}, \ + {cmd_toggle_fold_child, GDK_KEY_z, GDK_KEY_A, 0, 0, FALSE, FALSE}, \ + {cmd_open_fold_child, GDK_KEY_z, GDK_KEY_O, 0, 0, FALSE, FALSE}, \ + {cmd_close_fold_child, GDK_KEY_z, GDK_KEY_C, 0, 0, FALSE, FALSE}, \ + {cmd_open_fold_all, GDK_KEY_z, GDK_KEY_R, 0, 0, FALSE, FALSE}, \ + {cmd_close_fold_all, GDK_KEY_z, GDK_KEY_M, 0, 0, FALSE, FALSE}, \ /* changing text */ \ {cmd_enter_insert_cut_line, GDK_KEY_c, GDK_KEY_c, 0, 0, FALSE, FALSE}, \ {cmd_enter_insert_cut_line, GDK_KEY_S, 0, 0, 0, FALSE, FALSE}, \ diff --git a/vimode/src/cmds/fold.c b/vimode/src/cmds/fold.c new file mode 100644 index 000000000..9e05fba38 --- /dev/null +++ b/vimode/src/cmds/fold.c @@ -0,0 +1,127 @@ +/* + * Copyright 2024 Sylvain Cresto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "cmds/fold.h" +#include "utils.h" + +#define GOTO_NEAREST_PARENT 0 +#define GOTO_TOPMOST_PARENT 1 +#define GOTO_CONTRACTED_PARENT 2 + +static gint goto_above_fold(CmdParams *p, gint type) +{ + /* foldparent of the next line */ + gint line = SSM(p->sci, SCI_GETFOLDPARENT, p->line + 1, 0); + + if (p->line == line) + ; /* we are already on the fold point line */ + else + { + /* foldparent of the current line */ + line = SSM(p->sci, SCI_GETFOLDPARENT, p->line, 0); + } + + /* retreive first parent when type != GOTO_NEAREST_PARENT + when type == GOTO_CONTRACTED_PARENT we stop on first contracted parent if exist + */ + if (type == GOTO_CONTRACTED_PARENT && line != -1 && ! SSM(p->sci, SCI_GETFOLDEXPANDED, line, 0)) + ; /* this fold point is contracted and type == GOTO_CONTRACTED_PARENT */ + else if (type != GOTO_NEAREST_PARENT) + { + gint prev_line = line; + while (prev_line != -1) + { + prev_line = SSM(p->sci, SCI_GETFOLDPARENT, prev_line, 0); + if (prev_line != -1) + { + line = prev_line; + if (type == GOTO_CONTRACTED_PARENT && ! SSM(p->sci, SCI_GETFOLDEXPANDED, line, 0)) + break; + } + } + } + + if (line != -1) + { + /* move the cursor on the visible line before the fold */ + gint pos = SSM(p->sci, SCI_POSITIONFROMLINE, line, 0); + SET_POS_NOX(p->sci, pos, TRUE); + } + + return line; +} + + +void cmd_toggle_fold(CmdContext *c, CmdParams *p) +{ + gint line = goto_above_fold(p, GOTO_NEAREST_PARENT); + if (line != -1) + SSM(p->sci, SCI_FOLDLINE, (uptr_t) line, SC_FOLDACTION_TOGGLE); +} + + +void cmd_open_fold(CmdContext *c, CmdParams *p) +{ + gint line = goto_above_fold(p, GOTO_NEAREST_PARENT); + if (line != -1) + SSM(p->sci, SCI_FOLDLINE, (uptr_t) line, SC_FOLDACTION_EXPAND); +} + + +void cmd_close_fold(CmdContext *c, CmdParams *p) +{ + gint line = goto_above_fold(p, GOTO_NEAREST_PARENT); + if (line != -1) + SSM(p->sci, SCI_FOLDLINE, (uptr_t) line, SC_FOLDACTION_CONTRACT); +} + + +void cmd_toggle_fold_child(CmdContext *c, CmdParams *p) +{ + gint line = goto_above_fold(p, GOTO_CONTRACTED_PARENT); + if (line != -1) + SSM(p->sci, SCI_FOLDCHILDREN, (uptr_t) line, SC_FOLDACTION_TOGGLE); +} + + +void cmd_open_fold_child(CmdContext *c, CmdParams *p) +{ + gint line = goto_above_fold(p, GOTO_NEAREST_PARENT); + SSM(p->sci, SCI_FOLDCHILDREN, (uptr_t) line, SC_FOLDACTION_EXPAND); +} + + +void cmd_close_fold_child(CmdContext *c, CmdParams *p) +{ + gint line = goto_above_fold(p, GOTO_TOPMOST_PARENT); + if (line != -1) + SSM(p->sci, SCI_FOLDCHILDREN, (uptr_t) line, SC_FOLDACTION_CONTRACT); +} + + +void cmd_open_fold_all(CmdContext *c, CmdParams *p) +{ + SSM(p->sci, SCI_FOLDALL, SC_FOLDACTION_EXPAND | SC_FOLDACTION_CONTRACT_EVERY_LEVEL, 0); +} + + +void cmd_close_fold_all(CmdContext *c, CmdParams *p) +{ + goto_above_fold(p, GOTO_TOPMOST_PARENT); + SSM(p->sci, SCI_FOLDALL, SC_FOLDACTION_CONTRACT | SC_FOLDACTION_CONTRACT_EVERY_LEVEL, 0); +} diff --git a/vimode/src/cmds/fold.h b/vimode/src/cmds/fold.h new file mode 100644 index 000000000..4c42b13d1 --- /dev/null +++ b/vimode/src/cmds/fold.h @@ -0,0 +1,37 @@ +/* + * Copyright 2024 Sylvain Cresto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __VIMODE_CMDS_FOLD_H__ +#define __VIMODE_CMDS_FOLD_H__ + +#include "context.h" +#include "cmd-params.h" + +void cmd_toggle_fold(CmdContext *c, CmdParams *p); +void cmd_open_fold(CmdContext *c, CmdParams *p); +void cmd_close_fold(CmdContext *c, CmdParams *p); + +void cmd_toggle_fold_child(CmdContext *c, CmdParams *p); +void cmd_open_fold_child(CmdContext *c, CmdParams *p); +void cmd_close_fold_child(CmdContext *c, CmdParams *p); + +void cmd_toggle_fold_all(CmdContext *c, CmdParams *p); +void cmd_open_fold_all(CmdContext *c, CmdParams *p); +void cmd_close_fold_all(CmdContext *c, CmdParams *p); + +#endif