summaryrefslogtreecommitdiff
path: root/ipl/procs/rewrap.icn
blob: 21d8f806e6165c370134f23567d92c02cc71660e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
############################################################################
#
#	File:     rewrap.icn
#
#	Subject:  Procedures for advanced line rewrap
#
#	Author:   Richard L. Goerwitz
#
#	Date:	  March 3, 1996
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#	Version:  1.4
#
############################################################################
#
#  The procedure rewrap(s,i), included in this file, reformats text
#  fed to it into strings < i in length.  Rewrap utilizes a static
#  buffer, so it can be called repeatedly with different s arguments,
#  and still produce homogenous output.  This buffer is flushed by
#  calling rewrap with a null first argument.  The default for
#  argument 2 (i) is 70.
#
############################################################################
#
#  Here's a simple example of how rewrap could be used.  The following
#  program reads the standard input, producing fully rewrapped output.
#
#  procedure main()
#      every write(rewrap(!&input))
#      write(rewrap())
#  end
#
#  Naturally, in practice you would want to do things like check for in-
#  dentation or blank lines in order to wrap only on a paragraph-by para-
#  graph basis, as in
#
#  procedure main()
#      while line := read(&input) do {
#          if line == "" then {
#              write("" ~== rewrap())
#              write(line)
#          } else {
#              if match("\t", line) then {
#                  write(rewrap())
#                  write(rewrap(line))
#              } else {
#                  write(rewrap(line))
#              }
#          }
#      }
#  end
#
#  Fill-prefixes can be implemented simply by prepending them to the
#  output of rewrap:
#
#      i := 70; fill_prefix := " > "
#      while line := read(input_file) do {
#          line ?:= (f_bit := tab(many('> ')) | "", tab(0))
#          write(fill_prefix || f_bit || rewrap(line, i - *fill_prefix))
#          etc.
#
#  Obviously, these examples are fairly simplistic.  Putting them to
#  actual use would certainly require a few environment-specific
#  modifications and/or extensions.  Still, I hope they offer some
#  indication of the kinds of applications rewrap might be used in.
# 
#  Note:  If you want leading and trailing tabs removed, map them to
#  spaces first.  Rewrap only fools with spaces, leaving tabs intact.
#  This can be changed easily enough, by running its input through the
#  Icon detab() function.
#
############################################################################
#
#  See also:  wrap.icn
#
############################################################################


procedure rewrap(s,i)

    local extra_bit, line
    static old_line
    initial old_line := ""

    # Default column to wrap on is 70.
    /i := 70
    # Flush buffer on null first argument.
    if /s then {
	extra_bit := old_line
	old_line := ""
	return "" ~== extra_bit
    }

    # Prepend to s anything that is in the buffer (leftovers from the last s).
    s ?:= { tab(many(' ')); old_line || trim(tab(0)) }

    # If the line isn't long enough, just add everything to old_line.
    if *s < i then old_line := s || " " & fail

    s ? {

	# While it is possible to find places to break s, do so.
	while any(' -',line := EndToFront(i),-1) do {
	    # Clean up and suspend the last piece of s tabbed over.
	    line ?:= (tab(many(' ')), trim(tab(0)))
            if *&subject - &pos + *line > i
	    then suspend line
	    else {
		old_line := ""
		return line || tab(0)
	    }
	}

	# Keep the extra section of s in a buffer.
	old_line := tab(0)

	# If the reason the remaining section of s was unrewrapable was
	# that it was too long, and couldn't be broken up, then just return
	# the thing as-is.
	if *old_line > i then {
	    old_line ? {
		if extra_bit := tab(upto(' -')+1) || (tab(many(' ')) | "")
		then old_line := tab(0)
		else extra_bit := old_line & old_line := ""
		return trim(extra_bit)
	    }
	}
	# Otherwise, clean up the buffer for prepending to the next s.
	else {
	    # If old_line is blank, then don't mess with it.  Otherwise,
	    # add whatever is needed in order to link it with the next s.
	    if old_line ~== "" then {
		# If old_line ends in a dash, then there's no need to add a
		# space to it.
		if old_line[-1] ~== "-"
		then old_line ||:= " "
	    }
	}
    }
    
end



procedure EndToFront(i)
    # Goes with rewrap(s,i)
    *&subject+1 - &pos >= i | fail
    suspend &subject[.&pos:&pos <- &pos+i to &pos by -1]
end