First step towards implementing code folding
This is a first step towards implementing code folding #618. There are two parts involved:
- Parsing the file.
- Hiding the collapsed lines.
This patch implements part 2, although there are several TODO items.
Regarding part 1: there is a proof-of-concept that is based on indentation for off-side languages and braces for other languages, enough to test part 2.
This pull request is mostly seeking for comments and help implementing part 1 and the TODO items.
This new version updades the fold collapse status based on file edits and it is more or less usable.
This new version is working! Please, test and report feedback.
So first thing I want to say is that I am in love with this, it is a feature I have been hoping for for ages. I built the version and started trying it with some python.
For people reading, I added the following bindings to ~/.config/micro/bindings.json
"Alt-u": "FoldCollapse",
"Alt-i": "FoldExpand",
"Alt-U": "FoldCollapseRecursive",
"Alt-I": "FoldExpandRecursive",
these are only temporary and I do not intend on keeping them, but they are necessary to use the new functions.
Here are my observations and feedback:
Something I have found that can cause issues is that once text is collapsed, you can still type into it without being able to see what you write, and moving your cursor over the collapsed region requires moving over every line collapsed. This means that if I collapse a function from lines 6 to 8, and it appears to me that after line 6 is line 9, I have to move my cursor down 3 times to actually get there, and it disappears during this time. I can also type during this time, so if i were to enter characters while my cursor was not visible, and then expand the region, I would see that my input was actually written to inside of the collapsed block.
I think both of these would be best solved by modifying the code that is responsible for moving the cursor up and down to make it aware of lines that are collapsed.
I have not looked at the specifics of the syntax detection, but I have been able to use it with unindented C code blocks as well as python functions. Unterminated python blocks extend to the last blank line, so they can also swallow up the ending of a program. It might be useful to have the function ignore blank spaces at the end of code blocks (this is primarily when talking about python, where the end of code blocks is not explicit.
Another quality of life feature might be indicating in some way what the last line included in the current code block is, perhaps with a tilde in the same place a +/- is inserted.
I want to reiterate that I am very happy that this is a feature being added. Something I use micro for is markdown (.md) notes, and I would love the ability to collapse sections, though certain problems with the ambiguity of the ending of a section would need to be resolved. I also use micro for latex (.tex mainly), and collapsing sections for that would be useful. Both of these markup languages have unique (and often inconsistent, depending on the implementation) syntax, so I am also wondering if there might be a modular way to implement this per file type, in such a way that the end user could modify the conditions for what is considered a code block in a given file type.
For aforementioned situations such as in latex files where what the user wants to collapse might be ambiguous, there is a vim plugin whose idea might be referenced: https://github.com/matze/vim-tex-fold. I am specifically referring to the manual markers, %{{{ and %}}}.
Hi @atropos1789, cursor movement works for me. I've just tested it again whith v2.0.13-1-gd8e9d61a and it still works. Collapsed sections are skipped all at once and I am not able to write into a collapsed section. Please, try again with no plugins and with settings like mine. If it still doesn't work for you, report back what are you doing step by step.
settings.json
{
"autoclose": false,
"clipboard": "terminal",
"colorscheme": "simple",
"ignorecase": false,
"tabsize": 2,
"tabstospaces": true
}
bindings.json
{
"Alt-," : "None",
"Alt-." : "None",
"Alt-Backspace" : "None",
"Alt-CtrlH" : "None",
"Alt-F" : "None",
"Alt-[" : "None",
"Alt-]" : "None",
"Alt-a" : "None",
"Alt-b" : "None",
"Alt-c" : "None",
"Alt-e" : "None",
"Alt-f" : "None",
"Alt-g" : "None",
"Alt-m" : "None",
"Alt-n" : "None",
"Alt-p" : "None",
"Alt-x" : "None",
"Alt-{" : "None",
"Alt-}" : "None",
"Ctrl-b" : "None",
"Ctrl-g" : "None",
"Ctrl-h" : "None",
"Ctrl-j" : "None",
"Ctrl-k" : "None",
"Ctrl-n" : "None",
"Ctrl-p" : "None",
"Ctrl-u" : "None",
"Ctrl-w" : "None",
"CtrlShiftDown" : "None",
"CtrlShiftUp" : "None",
"F10" : "None",
"F7" : "None",
"Ctrl-MouseLeft" : "MouseMultiCursor" ,
"MouseLeft" : "MousePress" ,
"MouseMiddle" : "PastePrimary" ,
"MouseWheelUp" : "ScrollUp" ,
"MouseWheelDown" : "ScrollDown" ,
"CtrlUp" : "ScrollUp" ,
"CtrlDown" : "ScrollDown" ,
"Ctrl-e" : "JumpToMatchingBrace" ,
"Ctrl-l" : "command-edit:goto " , "Ctrl-a" : "SelectAll" ,
"Left" : "CursorLeft" , "ShiftLeft" : "SelectLeft" ,
"Right" : "CursorRight" , "ShiftRight" : "SelectRight" ,
"CtrlLeft" : "WordLeft" , "CtrlShiftLeft" : "SelectWordLeft" ,
"CtrlRight" : "WordRight" , "CtrlShiftRight" : "SelectWordRight" ,
"Home" : "StartOfTextToggle" , "ShiftHome" : "SelectToStartOfTextToggle" ,
"End" : "EndOfLine" , "ShiftEnd" : "SelectToEndOfLine" ,
"Up" : "CursorUp" , "ShiftUp" : "SelectUp" ,
"Down" : "CursorDown" , "ShiftDown" : "SelectDown" ,
"PageUp" : "CursorPageUp" , "ShiftPageUp" : "SelectPageUp" ,
"PageDown" : "CursorPageDown" , "ShiftPageDown" : "SelectPageDown" ,
"CtrlHome" : "CursorStart" , "ShiftCtrlHome" : "SelectToStart" ,
"CtrlEnd" : "CursorEnd" , "ShiftCtrlEnd" : "SelectToEnd" ,
"AltShiftDown" : "SpawnMultiCursorDown",
"AltShiftUp" : "SpawnMultiCursorUp" ,
"AltLeft" : "FoldCollapse" ,
"AltShiftLeft" : "FoldCollapseRecursive",
"AltRight" : "FoldExpand" ,
"AltShiftRight" : "FoldExpandRecursive" ,
"Ctrl-r" : "command-edit:replace ",
"Ctrl-f" : "FindLiteral" ,
"Ctrl-F3" : "Find" ,
"F3" : "FindNext" ,
"ShiftF3" : "FindPrevious" ,
"Esc" : "Escape,RemoveAllMultiCursors",
"Insert" : "ToggleOverwriteMode" ,
"Enter" : "InsertNewline" ,
"Backspace" : "Backspace" ,
"Delete" : "Delete" ,
"Tab" : "IndentSelection|InsertTab" ,
"Backtab" : "OutdentSelection|OutdentLine" ,
"AltUp" : "MoveLinesUp" ,
"AltDown" : "MoveLinesDown" ,
"Ctrl-d" : "DuplicateLine" ,
"Ctrl-c" : "CopyLine|Copy" ,
"Ctrl-x" : "Cut|CutLine" ,
"Ctrl-v" : "Paste" ,
"Ctrl-t" : "CommandMode" ,
"Ctrl-s" : "Save" ,
"Ctrl-q" : "Quit" ,
"Ctrl-y" : "Redo" ,
"Ctrl-z" : "Undo" ,
"Ctrl-o" : "AddTab&OpenFile" ,
"CtrlPageUp" : "PreviousTab" ,
"CtrlPageDown" : "NextTab"
}
Comments and strings can now be folded too.
Closed accidentally, reopenning...
New version fixes several corner cases.
Added C preprocessor folds.
Merge with upstream.
Multiple one-line comments are now considered a single collapsible region.