File: gnatcoll-paragraph_filling-words.adb

package info (click to toggle)
libgnatcoll 18-4
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 5,068 kB
  • sloc: ada: 40,393; python: 354; ansic: 310; makefile: 245; sh: 31
file content (174 lines) | stat: -rw-r--r-- 6,268 bytes parent folder | download
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
------------------------------------------------------------------------------
--                             G N A T C O L L                              --
--                                                                          --
--                     Copyright (C) 2010-2017, AdaCore                     --
--                                                                          --
-- This library is free software;  you can redistribute it and/or modify it --
-- under terms of the  GNU General Public License  as published by the Free --
-- Software  Foundation;  either version 3,  or (at your  option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
------------------------------------------------------------------------------

with Ada.Containers;        use Ada.Containers;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with GNATCOLL.Utils;        use GNATCOLL.Utils;

package body GNATCOLL.Paragraph_Filling.Words is

   -----------------
   -- Merge_Lines --
   -----------------

   function Merge_Lines
     (W                 : Words;
      Split_Before_Word : Word_Vector;
      Line_Prefix       : String := "")
      return Ada.Strings.Unbounded.Unbounded_String
   is
      Result : Unbounded_String;
      From   : Integer := 1;
      Start  : Integer;
      To     : Integer;
      Before_Word : Word_Index;
   begin
      for Count in reverse 2 .. Length (Split_Before_Word) - 1 loop
         Before_Word := Element (Split_Before_Word, Word_Index (Count));
         Start := Integer (W.Starts (Before_Word));

         To := Start - 1;
         while Is_Whitespace (Element (W.Paragraph, To)) loop
            To := To - 1;
         end loop;

         Append (Result, Line_Prefix);
         Append (Result, Slice (W.Paragraph, From, To));
         Append (Result, ASCII.LF);
         From := Start;
      end loop;

      To := Length (W.Paragraph);
      while Is_Whitespace (Element (W.Paragraph, To)) loop
         To := To - 1;
      end loop;

      Append (Result, Line_Prefix);
      Append (Result, Slice (W.Paragraph, From, To));
      Append (Result, ASCII.LF);
      return Result;
   end Merge_Lines;

   ---------------------
   -- Index_Paragraph --
   ---------------------

   function Index_Paragraph (Paragraph : String) return Words is
      Fixed_Para : Unbounded_String;
      Count      : Positive := Paragraph'First;
      Result     : Word_Vector;
   begin
      Append (Result, 1);  --  First word always starts on first character

      --  Takes out all spaces, tabs, and new line characters and creates a
      --  string with exactly one space between each word, plus one space at
      --  the end.

      if Paragraph /= "" then
         --  Skip leading whitespaces

         while Is_Whitespace (Paragraph (Count)) loop
            Count := Count + 1;
         end loop;

         while Count <= Paragraph'Last loop
            if Is_Whitespace (Paragraph (Count)) then
               loop
                  Count := Count + 1;
                  exit when Count > Paragraph'Last
                    or else not Is_Whitespace (Paragraph (Count));
               end loop;

               Append (Fixed_Para, ' ');
               Append (Result, Word_Index (Length (Fixed_Para) + 1));

               if Count <= Paragraph'Last then
                  Append (Fixed_Para, Paragraph (Count));
               end if;

            else
               --  ??? Might be more efficient to find the longuest substring
               --  with no multiple-space sequence, and append it at once. If
               --  the paragraph is already correct, we avoid a whole copy.
               Append (Fixed_Para, Paragraph (Count));
            end if;

            Count := Count + 1;
         end loop;

         if Element (Fixed_Para, Length (Fixed_Para)) /= ' ' then
            Append (Fixed_Para, ' ');
         end if;
      end if;

      --  Avoid extra copies of Starts array by building the result in place

      return W : Words (After_Last_Word => Word_Index (Length (Result))) do
         W.Paragraph := Fixed_Para;

         for Count in 1 .. Length (Result) loop
            W.Starts (Word_Index (Count)) :=
              Word_Vectors.Element (Result, Word_Index (Count));
         end loop;
      end return;
   end Index_Paragraph;

   ---------------
   -- Last_Word --
   ---------------

   function Last_Word (W : Words) return Word_Count is
   begin
      return W.After_Last_Word - 1;
   end Last_Word;

   -----------------
   -- Line_Length --
   -----------------

   function Line_Length (W : Words; X, Y : Word_Index) return Positive is
   begin
      return Positive (W.Starts (Y + 1) - W.Starts (X) - 1);
   end Line_Length;

   --------------
   -- Nth_Word --
   --------------

   function Nth_Word (W : Words; N : Word_Index) return String is
   begin
      return Slice (W.Paragraph,
                    Low  => Integer (W.Starts (N)),
                    High => Integer (W.Starts (N + 1) - 2));
   end Nth_Word;

   -----------------
   -- Word_Length --
   -----------------

   function Word_Length (W : Words; N : Word_Index) return Positive is
   begin
      return Integer (W.Starts (N + 1) - W.Starts (N) - 1);
   end Word_Length;

end GNATCOLL.Paragraph_Filling.Words;