freeride-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [FR-devel] Folding and Smart Indent...


From: Euan Mee
Subject: Re: [FR-devel] Folding and Smart Indent...
Date: Sat, 4 May 2002 00:56:04 +0100

n.b. I've 'refactored' Baptiste's original post slightly. (Pas mal, 
j'espere Baptiste)

On 03 May 2002, Baptiste Lepilleur wrote (more or less):
> Folding provides an overview of the code by hiding some
> lines. It decomposes source in a hierarchy, which can be
> folded at the nodes. For example: 
> 
> class Editor                            // folding point level 1
>     def initialize( window )        // folding point level 2
>         @window = window
>     end
>                                 // end folding point level 2

Minor query:  Is this correct, or is the folding point the line with 
the 'end' statement, rather than the blank line after the 'end' 
statement?

(I'm assuming a typo but just in case,) My preference is for 
folding points to be level with the 'end's, or else configurable to 
be with the 'end's. 

> Typically, the user would have short cuts to fold/unfold
> everything at a given level. This allows quick navigation
> within the source, and provides an overview of the class
> methods. For example, if the level 2 is folded, the user
> would see: 
> class Editor 
>     def initialize( window )
>     def title=( title )
> end
>
> This gives quick navigation within the source, and an overview
> of the class methods. The folding point can be any block of
> code: class, module, def, if, else, for, while... To be able
> to use folding, you must define the structure of the code: 
> for each line, you must indicate if it is a fold point, and
> its level.  
>
> To create source for folding structures, we need to know if
> each line: 
> a) begins a new level    (class, def, if, for, while...)
> b) ends a level    (end) 
> c) ends a level and also begins a new level (else, elsif) 
> d) continues at the current level (everything else) 
>
> What's interesting is that we need something very similiar to
> do smart indentation. When the user enters a new line, we
> should be able to say that, in relation to the previous line,
> it: 
> 1) should be indented
> 2) should be outdented
> 3) should be at the same level
> 
> The correlation between folding and indentation is obvious: 
>   IF b) or c) THEN outdent the line 
>   UNLESS the level contains (i.e. brackets) no other code 
> (in other words, the indentation of the line should be set to
> the indentation of the line that began the level) 
>
>   IF a) or c) THEN indent the following lines [typically "d)"s]
>
>   IF d) THEN use the same indentation level as the previous line
>   UNLESS the previous line was type "a)" or "c)".
> 
> I have a basic implementation of this in Practical Ruby,
> though it is limited to keep thing simple to begin with:
> e.g. it does not handle lines like: 
> IF <condition1> THEN IF <condition2> THEN x = y END x = z ELSE END. 
>
> Here's how: 
> # indicates that the line should be outdented if it contains
> # either 'end' or 'else' and no other key words.
> def shouldOutdentLine( lineNumber )
>     firstKeyWord = firstWordThatIsKeyWordAndNoEndOnLine(
>     lineNumber ) %w( end else ).include?( firstKeyWord )
> end
> 
> Where firstWordThatIsKeyWordAndNoEndOnLine() is a method that
> returns the first word with the key word style, 
> unless the key word 'end' is also in the line, 
>     then it returns an empty string
>
> Basically, it tests for case b) and c)
> 
> # indicates that the line should be indented if the previous line
> # starts with
> # 'class, def, for...' and does not contain 'end'
> def shouldIndentLine( lineNumber )
>     previousNonBlankLine = findNonBlankLineBefore( lineNumber )
>     firstKeyWord = firstWordThatIsKeyWordAndNoEndOnLine( previousNonBlankLine 
> )
>     %w( module class def for while do if else ).include?( firstKeyWord )
> end
> 
> Where firstNonBlankLineBefore() is a method that
> returns the line number of the first non-blank, non-comment line.
>
> i.e. it tests if the previous 'meaningful' line is of case "a)" or "c)", in 
> which
> case, the line should be indented. 
> 
> If neither of those two methods returns true, then we are in case
> d): same level of indentation.
> 
> To extend this technique to implement a 'perfect' smart
> indent, we'd need to handle code blocks ( do |it| end), and
> ';' within a line. 
>
> It's probably easier to implement with a method that guesses
> if a block of code is of type a,b,c or d rather than if it
> needs to be in- or out- dented. 
> 
> Plus smart indents give you a source beautifier for free:
> apply the smart indent on each line! 
> 
> Smart indent is also a requirement for automatic refactoring (and
> likely insertion of code template): you need to reindent the
> refactored code !
> 
> Does anyone have suggestions, or other ideas ?

I'd like to be able to manually show & hide lines of code that 
have had their fold-points identified by the editor.

The thing I have in minnd is like the indent/outdent facilities in 
MS's Excel 5 spreadsheet.

In that, every show/hide level of in/out denting can be shown or 
hidden individually - it provides little '+' and '-' icons to the 
immediate left of the lines of the spreadsheet.

This in addition to the automated 'collapse all', 'expand all' 
facilities, and the 'expand all level n' you mention.

I'd also like the ability to 'expand the selected node fully', and 
'collapse the selected node fully', and 'expand the next n 
levels at this node'

This mirrors the way I deal with structured code - I tend to 
work on on code-structure at a time - everything else at the 
same level is collapsed down, everything at a higher level is 
visible.



Cheers,
     Euan
address@hidden

'I would live all my life in nonchalance and insouciance,
Were it not for making a living, which is rather a nouciance'
 - Ogden Nash



reply via email to

[Prev in Thread] Current Thread [Next in Thread]