Tags:
create new tag
, view all tags

Nedit Macros: Fold on TWiki Headings

Introduction

The Nedit macros on this page fold and unfold a "raw" TWiki file at various heading levels.

For a quick example of folding (or more accurately collapsing), look at the Contents sections of this document. They are essentially alternate views of this document collapsed on TWiki headings. If the views were folded instead of collapsed, each heading would prefix a long line heading off the right of the page containing all the text between that and the next heading.

By "raw" TWiki file, I mean a file containing plain ASCII text with TWiki markup. I do (some) editing of more complicated TWiki pages by copying and pasting the text from the TWiki edit window to a Nedit window, editing in Nedit, and then copying and pasting back to the TWiki edit window. BTW, since the file format of the TWiki .txt files on a TWiki server is essentially the same (ignoring metadata), these macros should be useful if you do editing of those files (which is not recommeded).

Currently, this TWiki page is the only place these macros are "published".

If you know your way around Nedit, you can use them by copying and pasting them in the appropriate places under Nedit Preferences -> Default Settings -> Customize Menus -> Macro Menu, naming them, and assigning a keyboard accelerator.

The macros range in size from 5 to 11 lines of macro code.

In addition to creating these macros, I think I've managed to create a TWiki language preference (recognized by a .twk extension on a file) so that these macros work (and are visible) only while editing .twk files. But, I'm unsure that I really accomplished that, and, if I did, exactly how I did it, so this page won't address that at this time.

As I learn more about Nedit macros, I will probably expand the scope of these macros (fold blocks in programming languages, add other commands, collapse instead of fold text), make them more efficient, and create an installation "package". Don't hold your breath. wink

Hmm, maybe I need to include a warning about editing (especially deleting stuff) while folded, maybe especially so if recreated for AbiWord — maybe there needs to be something in the GUI to minimize the kind of editing that can be done in AbiWord while an outline is collapsed. Maybe I should dust off Microsoft Word and see what they do?

See:

Contents

Contents as a Level 3 Collapsed Outline

In addition to being a Table of Contents, this is also an outline based on TWiki headings collapsed to level 3:
Notes:
  1. on most WikiLearn pages I exclude the "Contents" heading from the Table of Contents by using the TWiki "!!" syntax
  2. a "real" collapsed outline presents an alternate view of a document, this pseudo- collapsed outline is a little misleading because you see both the collapsed outline and the remainder of the document in its non-collapsed state. In an attempt to help visualize a "real" collapsed outline, I've added horizontal rules before and after the outlines below.

In other words: If you were in Word and switched to a collapsed outline view of this page (at a given level), you would see only what is between the horizontal rules.

Note that you can easily navigate from one place to another in the document by collapsing, moving to a different heading, and re-expanding. You can also easily rearrange the sections while in the collapsed state (I'd have to refresh my memory on the exact steps to do that, but, in general, IIRC, when you select a heading while in outline mode, you also select the text under that heading).



Contents as a Level 2 Collapsed Outline

Because this page is about collapsible outlining, I show the same outline collapsed to level 2 headings. (Note the syntax: %TOC{depth="2"}%):



Contents as a Level 1 Collapsed Outline

The degenerate case of an outline collapsed to Level 1 with no Level 1 headings present in the document (as displayed in TWiki):



Explanation of Folding

Folding and collapsible outlining are ways to better visualize and navigate a document by making text containing details you aren't interested in at the moment either not visible (collapsible outlining) or less visible and obtrusive (folding).

For a quick example of folding (or more accurately collapsing), look at the Contents sections above. They are essentially alternate views of this document collapsed on TWiki headings. If the views were folded instead of collapsed, each heading would prefix a long line heading off the right of the page containing all the text between that and the next heading.

Principle of Folding in Nedit

In these macros (and all Nedit macros of which I am aware), folding is accomplished by replacing selected newline (\n) markers with form feed (\f) markers. The \f does not actually cause a form feed (at least on a Nedit display), but the key point is it that neither does it cause the start of a new line. Thus, groups of lines in which the \n's are replaced by \f's are folded (unfolded?) into one long line.

In addition, every fold macro that I've written includes the command to set line wrapping to "none", the macro that unfolds the entire document completely includes the command to set line wrapping to "continuous" aka "soft wrapping").

I include those two commands because, in normal editing, I keep wrap set to continuous, but the folding effect would not be visible if wrap were set to continuous. When the document is completely unfolded, I restore the (my) "default" continuous wrap setting.

Note: I think (but am not sure) that these macros will also work if you prefer to use hard wrapping. You will then want to switch between hard wrapping and no(ne) wrapping. As is typical of the hard wrap approach, you may have to reformat paragraphs at various times. (Nedit calls that operation "fill paragraphs".)

Basis for Folding TWiki Raw Files

These macros fold TWiki at any of the TWiki heading levels. TWiki headings are "marked up" with a string of characters as follows:

  • "---+" Level 1 Heading (Highest)
  • "---++" Level 2 Heading
  • "---+++" Level 3 Heading
  • "---++++" Level 4 Heading
  • "---+++++" Level 5 Heading
  • "---++++++" Level 6 Heading (Lowest)

Macro Names, Default Accelerators, and Functionality

TWiki>Fold>fold_level_1 (<Alt>1)
Display only Level 1 headings (all text and lower level headings folded)

TWiki>Fold>fold_level_2 (<Alt>2)
Display only Level 1 and 2 headings (all text and lower level headings folded)

TWiki>Fold>fold_level_3 (<Alt>3)
Display only Level 1 through 3 headings (all text and lower level headings folded)

TWiki>Fold>fold_level_4 (<Alt>4)
Display only Level 1 through 4 headings (all text and lower level headings folded)

TWiki>Fold>fold_level_5 (<Alt>5)
Display only Level 1 through 5 headings (all text and lower level headings folded)

TWiki>Fold>fold_level_6 (<Alt>6)
Display all headings (Levels 1 through 6 — all text folded)

TWiki>Fold>unfold_all (<Alt>0)
Restore document to (completely) unfolded condition — all headings and text (easily) visible

Algorithms and Code (version 0.2)

I had a few false starts, including an overly complicated attempt to create a macro that would fold a selection to either a specified level or to the level of the first heading found in the selection, (making it and headings at the same or higher levels visible and all lower level headings folded). I may attach that false start to this page as a starting point for a fold_selection macro.

This algorithm, by far, is brute force, and not at all efficient. It was partly because I didn't know whether commands were available in Nedit to do a more efficient approach. I now believe they are, and have a good idea of how to make the macros much more efficient, but I'm going to start by publishing the macros in their current incarnation. Perhaps they are, in some sense, "the simplest thing that could possibly work", but I know they are not the most efficient.

I'll start by describing the fold_level_1 algorithm, and then describe the others by analogy.

fold_level_1 Algorithm and Macro

This might appear to be a backwards approach, I fold the entire document and then unfold the headings at the level(s) I want to see, but it appeared to be simpler logic than trying to fold everything except those headings.

  • save the current location of the cursor (so it can be restored after folding — the replace functions (below) move the cursor)
  • set wrapping to "none"
  • fold the entire document by replacing all \n's with \f's —
  • unfold the Level 1 headings by finding all Level 1 heading markers "---+" and replace the preceding \f with a \n
  • restore the cursor to the original position in the file
  • move the cursor (and the "focus") to the beginning of the line it is contained in

The actual macro:

Note: this works but I notice now that I was inconsistent in "double escaping" (e.g., \\f) the characters that require escaping — I need to understand the requirement for double escaping better, make all the double escaping consistent, and then retest, but I have "published" this on Wikilearn before doing so.

saved_cursor=$cursor
set_wrap_text("none")

replace_all("\n", "\f", "regex")

replace_all("\\f---\\+ ", "\n---+ ", "regex")

set_cursor_pos(saved_cursor)
beginning_of_line()

fold_level_2 Algorithm and Macro

The algorithm for fold_level_2 is almost exactly the same as that for fold_level_1 with the addition of 1 extra step: after unfolding the Level 1 headings to display them, unfold the Level 2 headings to display them as well:

saved_cursor=$cursor
set_wrap_text("none")

replace_all("\n", "\f", "regex")

replace_all("\\f---\\+ ", "\n---+ ", "regex")
replace_all("\\f---\\+\\+ ", "\n---+ ", "regex")

set_cursor_pos(saved_cursor)
beginning_of_line()

fold_level_3 Algorithm and Macro

Can you guess? Just like fold_level_2, but also unfold the Level 3 headings:

saved_cursor=$cursor
set_wrap_text("none")

replace_all("\n", "\f", "regex")

replace_all("\\f---\\+ ", "\n---+ ", "regex")
replace_all("\\f---\\+\\+ ", "\n---++ ", "regex")
replace_all("\\f---\\+\\+\\+ ", "\n---+++ ", "regex")

set_cursor_pos(saved_cursor)
beginning_of_line()

fold_level_4 Algorithm and Macro

... also unfold the Level 4 headings:

saved_cursor=$cursor
set_wrap_text("none")

replace_all("\n", "\f", "regex")

replace_all("\\f---\\+ ", "\n---+ ", "regex")
replace_all("\\f---\\+\\+ ", "\n---++ ", "regex")
replace_all("\\f---\\+\\+\\+ ", "\n---+++ ", "regex")
replace_all("\\f---\\+\\+\\+\\+ ", "\n---++++ ", "regex")

set_cursor_pos(saved_cursor)
beginning_of_line()

fold_level_5 Algorithm and Macro

... also unfold the Level 5 headings:

saved_cursor=$cursor
set_wrap_text("none")

replace_all("\n", "\f", "regex")

replace_all("\\f---\\+ ", "\n---+ ", "regex")
replace_all("\\f---\\+\\+ ", "\n---++ ", "regex")
replace_all("\\f---\\+\\+\\+ ", "\n---+++ ", "regex")
replace_all("\\f---\\+\\+\\+\\+ ", "\n---++++ ", "regex")
replace_all("\\f---\\+\\+\\+\\+\\+ ", "\n---+++++ ", "regex")

set_cursor_pos(saved_cursor)
beginning_of_line()

fold_level_6 Algorithm and Macro

... also unfold the Level 6 headings:

saved_cursor=$cursor
set_wrap_text("none")

replace_all("\n", "\f", "regex")

replace_all("\\f---\\+ ", "\n---+ ", "regex")
replace_all("\\f---\\+\\+ ", "\n---++ ", "regex")
replace_all("\\f---\\+\\+\\+ ", "\n---+++ ", "regex")
replace_all("\\f---\\+\\+\\+\\+ ", "\n---++++ ", "regex")
replace_all("\\f---\\+\\+\\+\\+\\+ ", "\n---+++++ ", "regex")
replace_all("\\f---\\+\\+\\+\\+\\+\\+ ", "\n---++++++ ", "regex")

set_cursor_pos(saved_cursor)
beginning_of_line()

unfold_all Algorithm and Macro

  • save the current location of the cursor (so it can be restored after unfolding — the replace functions move the cursor)
  • unfold the entire document by replacing all \f's with \n's
  • set wrapping to "continuous" (because this is my preference for normal editing)
  • restore the cursor to the original position in the file
  • move the cursor (and the "focus") to the beginning of the line it is contained in

saved_cursor=$cursor

replace_all("\f", "\n", "regex")

set_wrap_text("continuous")
set_cursor_pos(saved_cursor)
beginning_of_line()

Efficiency of the Algorithms

As you may have noticed, the macros above traverse the document up to seven times. That cannot be the most efficient approach.

Alternatives Tried

I did do some experimenting with search and replaces of the form:

replace_all("\\f---(\\+*)", "\\n---\1", "regex")

(in other words, using regular expression multipliers and memory )

The above may not be exactly right because I reproduced it from memory — during testing I did get it in the right form so it did (almost) work.

The problem was that it acted on (unfolded) all headings of the desired level and lower, I needed it to act on (unfold) all headings of the desired level and higher.

As I wrote this, I thought that I really should be able to get the above to work, if necessary by changing the overall premise, i.e., instead of first changing all \n's to \f's and then changing \f's to \n's in front of the headings I want to see, do the opposite — leave all \n's as is, then change the \n's to \f's in front of the headings I don't want to see. The problem is, at some point I have to change the \n's to \f's in front of the non-heading text that I don't want to see, and that makes it a little more complicated. It is probably still workable, but I think there is an even more efficient approach, which I describe next.

The Next Attempt

What sounds like the most efficient approach that I've thought of so far, and for which Nedit has appropriate commands (I don't know whether the Nedit macro language is Turing complete), goes something like this:

Initialize: do things like save the cursor position, set the wrapping to none

The Next Algorithm: see below

Finalize: do things like restore the cursor position, move to the beginning of the line

The Next Algorithm

(approximately)

  • fold the entire document (replace \n's with \f's)
  • visit each heading (search for "---\+*") Something like while search( ... ) not equal to -1?? (-1 indicates a failed search). Or while cursor not equal to $size_of_document (or whatever)) (I will need a temporary variable to hold the result of search(...) and then use that temporary variable for various purposes including being the exit condition of the while loop.
  • determine the length of the heading (e.g., length($search_end - search("---\\+*", "regex")) (note that search returns the position of the found string, and $search_end contains the position of the end of the found string (for the last successful search (??))
  • determine the level of the heading (level of heading = length of heading -3 (~))
  • if the level of heading found is equal to or higher than the desired fold level, move the cursor back to (at least) one character before the found heading (set_cursor_pos(search(...) - 1), and change the \f found there to a \n (might need to do a replace(...)?) (Note that the logical heading level is inversely proportional to the heading (markup) length, e.g. Level 1 heading markup = "---+" = length 4 = highest logical level; Level 6 heading markup = "---++++++" = length 9 = lowest logical level.
  • move the cursor ahead at least (~)4 characters and repeat the search for a heading (the move ahead is to ensure we don't find the same heading again and get into an infinite loop)

Future Enhancements

  • insert a collapse (fold) marker ("+"?) in front of each heading that actually contains folded text or headings (some headings at any level of folding or collapse may be empty)

  • when a way to make text invisible exists in Nedit, incorporate it so that text appears hidden (collapsed) instead of just folded

  • until then, consider appending say 80 spaces between a visible heading and the folded text it contains so that the folded text starts so far to the right that it is not visible in the window

  • add macros for other related functions, like:

    • Expand / Collapse the current heading (the heading on the current line) or selection -- need to consider the exact approach, but presumably change the state of expansion or collapse by one (heading) level

    • Promote / Demote the current heading or selection — we need to consider the exact approach (especially for subheadings) — presumably each heading is promoted or demoted one level, and when we run out of levels of heading, demote it to plain text. IIRC, Word (last time I used it, i.e., Word 97) promotes text to a Level 1 heading, I'd want to at least experiment with promoting it to a Level 6 heading (or to the heading level below (or equal to?) the lowest heading level currently used in the selection), then promoting higher from there if desired. Or maybe one command to promote to Level 1, another to promote to the next heading level below the lowest level currently used within the selection.

    • Toggle between showing no non-heading text and showing the first line of each non-heading paragraph

  • if editing files while folded frequently results in unintentionally deleted text, consider ways to deal with the problem -- possibly enforcing a prohibition on editing while folded somehow (maybe via GUI changes?)

  • make changes to the GUI to support folding / collapsible outlining

Other Comments or Observations

Origin of Folding Terminology?

I've sometimes wondered how the folding terminology originated. Now, seeing how folding is performed in these Nedit macros, it makes sense to me.

<is it clear why I say that, or do I need to explain more?>

Hmm, maybe I can (sort of) show the next heading unfolded and then folded, by using the <pre> tags — that will work in some browsers, but not all, and I forget which)

Previous Section Folded

Hmm, it shows up properly in konqueror (i.e., one long line). In browser's where it doesn't show up as one long line, it will probably show up the way it would if the fold macros didn't switch from continuous (soft) to no wrapping. The <np>s are apparently Nedit's way of displaying a \f.

---+++ Origin of Folding Terminology?<np><np>I've sometimes wondered how the folding terminology originated.  Now, seeing how folding is performed in these Nedit macros, it makes sense to me.<np><np><is it clear why I say that, or do I need to explain more?><np><np>Hmm, maybe I can (sort of) show the first this heading folded, by using the <pre> tags — that will work in some browsers, but not all, and I forget which) 

Rant: Self Documenting Programs

Whether the program above works (the first time) or not, I again think and am now convinced that it is extremely arrogant or fraudulent for a programmer to declare that any program is self documenting or self evident.

I can explain what these macros are intended to achieve ("fold" a file, by replacing selected \n's with \p's, and which \n's must be replaced under which circumstances), but the way the macros achieve those replacements follows a significantly different path than the explanation of what I'm trying to achieve (either because of limitations of the language, or limitations of my knowledge of the language).

Thus, someone who is trying to understand the macros must understand the objective (in the "real" world, or even in the computer world) and the possibly roundabout way the macros achieve that objective. At least one of those explanations will not be contained in the code (discounting comments). Will there be some cases where the real world objective can be accomplished in a straightforward parallel programming path? Yes, I'm sure of that, but as a reader of programs, I am sure that is the case far less often than most programmers think.

Contributors

  • () RandyKramer - 22 Jun 2003
  • I should mention the help I've gotten so far from the discuss@neditPLEASENOSPAM.org mailing list, including (recently) Thorsten Haude, Joerg Fischer, Joor Loohuis, Joachim Lous, whoever wrote the earlier version(s) of the Nedit fold macros, people on the AbiWord mailing lists (Paul Rohr, Dom Lachowicz, F.J. Franklin, others), and other people who have helped me gradually develop an understanding of how to accomplish folding or collapsible outlining. I know I've left out some names I should mention — sorry!
  • If you edit this page: add your name here; move this to the next line; and if you've used a comment marker (your initials in parenthesis), include it before your WikiName.

Page Ratings

Edit | Attach | Watch | Print version | History: r11 < r10 < r9 < r8 < r7 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r11 - 2005-08-29 - RandyKramer
 
  • Learn about TWiki  
  • Download TWiki
This site is powered by the TWiki collaboration platform Powered by PerlCopyright 1999-2017 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding WikiLearn? WebBottomBar">Send feedback
See TWiki's New Look