# ============================================================================== # Paragraph-ending recognition with spaces (pers.nm) # ============================================================================== # # Date: Jun 11 1999 # # Author: Oliver Schmidt # mailto:oschmidt@gmx.de # http://welcome.to/oschmidt # # With these macros it is possible to distinguish between newlines that # indicate the end of a paragraph and between newlines that are only end of # lines within a paragraph. # # Macros for Auto-Newline wrapping and for refilling paragraphs/ selections as # well as selecting paragraphs, moving to previous/ next paragraph etc. are # supplied. # # These macros are similar to the PlainText.nm macros by Tony Balinski but they # are faster and have a slightly different behaviour. # # # The principle is as follows: # # A space (or tab) character at the end of the line indicates a line that is # not the last line of a paragraph. If there is no space (or tab) character at # the end of the line then this line is the last line of a paragraph. Lines # that consist only of spaces and tabs are treated as a separate paragraph. # # This principle makes it possible to detect the ending of a paragraph without # seperating them by empty lines. Nedit itself can do this by using Continous # wrapping with the disadvantage that every paragraph is stored in a single # line. # # With this principle it should also be possible to write macros that can # reformat the whole paragraph after each character entered. However the macros # presented here can only do Autonewline-wrapping. # # # # To use these macros you should switch on "Smart-indent" and "No wrapping". # You can do this e.g. if you create a new language Mode (Preferences->Default # Settings->Language Modes). Of course it is possible to add these macros to # existing language modes (e.g. LaTeX) as well. # # You should also set up the Smart-indent macros (Preferences->Default # Settings->Auto Indent->Program Smart Indent) as follows: # # Language Specific Initialization Macro Commands and Definitions: # ================================================================ # Here it is useful to load the pers.nm macro file. E.g. # NEDIT_require_macro_file("pers.nm") # # if you use the nedit_loaded.nm macros # or # load_macro_file($my_macros_directory"/pers.nm") # # if you don't use the nedit_loaded macros # or # return # # if you paste the macros of this file to the Common/Shared # # Initialization dialog. # # Newline Macro: # ============== # return -1 # # Type-in Macro: # ============== # PERS_autonewlineMacro($1, $2) # # Now you can add the following macros (Preferences->Default # Settings->Customize Menus->Macro Menu). You should be sure that the pers.nm # file is loaded which should be true if you define the macros only for the # above mentioned language modes or if you put them to the Common/Shared # Initialization dialog. You can also insert # NEDIT_require_macro_file("pers.nm") at the beginning of each macro if you use # the nedit_loaded.nm macros. # # Menu Entry: Refill Paragraph # ============================ # if ($selection_start == -1) # set_cursor_pos(PERS_refillParagraph($cursor)) # else # set_cursor_pos(PERS_refillParagraph( \ # PERS_makeParagraph($selection_start, $selection_end))) # # Menu Entry: Go to begin of paragraph # ==================================== # set_cursor_pos(PERS_beginOfParagraph($cursor)) # # Menu Entry: Go to end of paragraph # ================================== # set_cursor_pos(PERS_endOfParagraph($cursor)) # # Menu Entry: Go to previous paragraph # ==================================== # c = PERS_beginOfParagraph(PERS_beginOfParagraph($cursor) - 1) # while (c >= 0) # { # if (!PERS_isEmptyLine(c)) # { # set_cursor_pos(c) # return # } # c = PERS_beginOfParagraph(PERS_beginOfParagraph(c) - 1) # } # # Menu Entry: Go to next paragraph # ================================ # c = PERS_endOfParagraph($cursor) + 1 # while (c <= $text_length) # { # if (!PERS_isEmptyLine(c)) # { # set_cursor_pos(c) # return # } # c = PERS_endOfParagraph(c) + 1 # } # # Menu Entry: Select paragraph # ============================ # select(PERS_beginOfParagraph($cursor), PERS_endOfParagraph($cursor)) # # Menu Entry: Toggle 1st line handling # ==================================== # $PERS_take_second_line = !$PERS_take_second_line # if ($PERS_take_second_line) # dialog("OK. The SECOND line of a paragraph \ndetermines the indentation"\ # " for\nparagraph refilling.") # else # dialog("OK. The FIRST line of a paragraph\ndetermines the indentation"\ # " for\nparagraph refilling.") # # ============================================================================== $PERS_take_second_line = 0 # if 1 the second line of a paragraph determines the indentation margin # if 0 the first line of a paragraph determines the indentation margin # ============================================================================== # PERS_beginOfLine(pos): Returns the position of the beginning of the line of # the position pos. # ============================================================================== define PERS_beginOfLine { p = $1 - 1 while (p >= 0 && get_character(p) != "\n") p-- return p+1 } # ============================================================================== # PERS_endOfLine(pos): Returns the position of the ending of the line of the # position pos. # ============================================================================== define PERS_endOfLine { p = $1 while (p < $text_length && get_character(p) != "\n") p++ return p } # ============================================================================== # PERS_firstNonSpace(pos): Returns the position of the first non space/tab # character after the position pos. # ============================================================================== define PERS_firstNonSpace { p = $1 while (p < $text_length && \ (get_character(p) == " " || get_character(p) == "\t")) p++ return p } # ============================================================================== # PERS_prevBreakPos(pos): Returns the position of the previous break position # before the position pos. # ============================================================================== define PERS_prevBreakPos { p = $1 - 1 while (p >= 0 && \ get_character(p) != " " && \ get_character(p) != "\t" && \ get_character(p) != "\n") p-- return p+1 } # ============================================================================== # PERS_isEmptyLine(pos): Returns 1 if the line of the position pos is an # empty line. # ============================================================================== define PERS_isEmptyLine { eol = PERS_endOfLine($1) fns = PERS_firstNonSpace(PERS_beginOfLine($1)) return (fns == eol) } # ============================================================================== # PERS_beginOfParagraph(pos): Returns the position of the beginning of the # paragraph at the position pos. # ============================================================================== define PERS_beginOfParagraph { p = $1 - 1 while (p >= 0) { if (get_character(p) == "\n") { if (PERS_isEmptyLine(p)) return p + 1 if (p > 0) { if (get_character(p - 1) != " " && get_character(p - 1) != "\t") return p + 1 else p -= 2 } else p-- } else p-- } return p+1 } # ============================================================================== # PERS_endOfParagraph(pos): Returns the position of the ending of the # paragraph at the position pos. # ============================================================================== define PERS_endOfParagraph { p = $1 if (PERS_isEmptyLine(p)) return PERS_endOfLine(p) while (p<$text_length) { if (get_character(p) == "\n") { if (PERS_isEmptyLine(p)) return PERS_beginOfLine(p) if (p > 0) { if (get_character(p - 1) != " " && get_character(p - 1) != "\t") return p else p++ } else return 0 } else p++ } return p } # ============================================================================== # PERS_columns(str): Returns the number of columns the string str has. Tab # characters are correctly handled. # ============================================================================== define PERS_columns { c = 0 for (i = 0; i < length($1); i++) { if (substring($1, i, i + 1) == "\t") c = ((c / $tab_dist) + 1) * $tab_dist else c++ } return c } # ============================================================================== # PERS_autonewlineMacro(pos, char): This macro should be called as a type-in # macro. It requires that the $column variable is set up properly. This # macro inserts a newline character if the cursor is right of the # $wrap_margin. # ============================================================================== define PERS_autonewlineMacro { if ($column + 1 < $wrap_margin) return if (length($2) != 1 || $selection_start != -1) return if ($2 == "\n" || $2 == " " || $2 == "\t") return bp = PERS_prevBreakPos($1) bol = PERS_beginOfLine($1) if (bp == bol) return fns = PERS_firstNonSpace(bol) if (bp <= fns) return str = "\n" get_range(bol, fns) replace_range(bp, bp, str) set_cursor_pos($1 + length(str)) } # ============================================================================== # PERS_refill(startpos, endpos): Refills the text between the two positions. # ============================================================================== define PERS_refill { scndlne = PERS_endOfLine($1) + 1 ind1str = get_range($1, PERS_firstNonSpace($1)) if (scndlne > $2 || !$PERS_take_second_line) { # take the first line of a paragraph for indentation indstr = ind1str } else { # take the second line of a paragraph for indentation indstr = get_range(scndlne, PERS_firstNonSpace(scndlne)) } parastr = get_range($1, $2) # remove all newlines and indentation spaces for (nl = 0; nl != -1; nl = search_string(parastr, "\n", 0)) { fns = search_string(parastr, "[^ \t\n]", nl, "regex", "forward") if (fns == -1) fns = length(parastr) parastr = replace_substring(parastr, nl, fns, "") } # Make indentation indclms = PERS_columns(indstr) # Number of margin columns indchrs = length(indstr) # Number of margin characters parastr = ind1str parastr c = PERS_columns(ind1str) p = length(ind1str) # Break lines brk_rmbrd = 0 while (p < length(parastr)) { chr = substring(parastr, p, p + 1) if (chr == "\t") { p++ c = ((c / $tab_dist) + 1) * $tab_dist } else { p++ c++ } if (chr == " " || chr == "\t") { brk_rmbrd = 1 brk_p = p brk_c = c # remember possible break position } if (brk_rmbrd && c >= $wrap_margin) { parastr = replace_substring(parastr, brk_p, brk_p, "\n" indstr) c = indclms p = brk_p + indchrs + 1 brk_rmbrd = 0 } } replace_range($1, $2, parastr) } # ============================================================================== # PERS_refillParagraph(pos): Refills the paragraph at the position pos. # Returns the position of the next paragraph's beginning. # ============================================================================== define PERS_refillParagraph { bop = PERS_beginOfParagraph($1) eop = PERS_endOfParagraph($1) PERS_refill(bop, eop) next = PERS_endOfParagraph(bop) + 1 if (next > $text_length) next-- return next } # ============================================================================== # PERS_makeParagraph(startpos, endpos): Sets paragraph delimiters properly so # that the text between the two position is recognized as one paragraph. # Returns the pos of the paragraph's beginning. # ============================================================================== define PERS_makeParagraph { if ($1 > 0 && PERS_endOfParagraph($1 - 1) >= $1) { # Insert paragraph delimiter at startpos pns = search("[^ \t]", $1 - 1, "regex", "backward") prestr = get_range(pns, pns + 1) if (prestr != "\n") prestr = replace_substring(prestr, 1, 1, "\n") replacestart = pns } else { replacestart = $1 prestr = "" } str = get_range($1, $2) # Remove empty lines str1 = replace_in_string(str, "^[ \t]*\n", "", "regex") if (str1 != "") str = str1 str1 = replace_in_string(str, "\n\n[\n]*", "\n", "regex") if (str1 != "") str = str1 # Add spaces at end of lines if necessary str1 = replace_in_string(str, "([^ \t])(\n)", "\\1 \n", "regex") if (str1 != "") str = str1 # Remove last spaces of selection l = length(str) p = search_string(str, "[^ \t][ \t]*$", l, "regex", "backward") if (p != -1 && p + 1 < l) str = replace_substring(str, p + 1, $search_end, "") # Add newline if necessary l = length(str) if (substring(str, l - 1, l) != "\n" && (get_character($2) != "\n")) str = replace_substring(str, l, l, "\n") replace_range(replacestart, $2, prestr str) return replacestart + length(prestr) } # ============================================================================== # end of file