Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 3120eddae2836a04c2d30d95b6d81ca1855f6fb9 (plain) (blame)
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*******************************************************************************
 * Copyright (c) 2006-2015 Red Hat Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Kyu Lee <klee@redhat.com> - initial API and implementation
 *******************************************************************************/
package org.eclipse.linuxtools.internal.changelog.core.editors;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.StringTokenizer;

import org.eclipse.jface.text.formatter.IFormattingStrategy;

public class ChangeLogFormattingStrategy implements IFormattingStrategy {

    private static final String NEW_LINE_CHAR = "\n";
    private static final String WHITE_SPACE_CHAR = " ";
    private static final String TAB_SPACE_CHAR = "\t";
    private static final String DELIMITER_CHARS = NEW_LINE_CHAR + WHITE_SPACE_CHAR + TAB_SPACE_CHAR;

    private static final int MAX_WIDTH = 80;
    private static final SimpleDateFormat isoDate = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public String format(String content, boolean isLineStart,
            String indentation, int[] positions) {

        String firstLine = "";

        // if first line is not from the start, ignore it
        if (!isLineStart) {
            int eol;
            if ((eol = content.indexOf(NEW_LINE_CHAR)) == content.length() - 1) {
                return content;
            } else {
                firstLine = content.substring(0, eol + 1);
                content = content.substring(eol + 1);
            }
        }

        content.replaceFirst("(\\s+)?\\n(\\s+)?", NEW_LINE_CHAR);
        StringTokenizer candidateWords = new StringTokenizer(content, DELIMITER_CHARS, true);

        String formattedContent = formatContent(candidateWords, indentation.length());
        return firstLine.concat(formattedContent);
    }

    private String formatContent(StringTokenizer candidateWords, int indentationLength) {
        StringBuilder formattedWords = new StringBuilder();
        int currentLineLength = indentationLength;

        while (candidateWords.hasMoreTokens()) {
            String cword = candidateWords.nextToken();

            if (isDelimeter(cword)) {
                continue;
            }

            // if the word is date, start new line and include
            // names, email, then an empty line.
            else if (isDate(cword)) {

                // see if we are in middle of line and
                // if so, start new line, else continue.
                if (!isOnNewLine(formattedWords)) {
                    formattedWords.append(NEW_LINE_CHAR);
                }

                if (formattedWords.length() > 0) {
                    formattedWords.append(NEW_LINE_CHAR);
                }

                // insert date
                formattedWords.append(cword + WHITE_SPACE_CHAR);

                // insert name/email
                while (candidateWords.hasMoreTokens()) {
                    cword = candidateWords.nextToken();
                    if (cword.equals(NEW_LINE_CHAR)) {
                        formattedWords.append(NEW_LINE_CHAR);
                        break;
                    }
                    if (isEmail(cword)) {
                        formattedWords.append(WHITE_SPACE_CHAR)
                                      .append(WHITE_SPACE_CHAR)
                                      .append(cword)
                                      .append(NEW_LINE_CHAR)
                                      .append(NEW_LINE_CHAR);
                        currentLineLength = indentationLength;
                        break;
                    }
                    if (!isDelimeter(cword)) {
                        formattedWords.append(WHITE_SPACE_CHAR).append(cword);
                    }
                }
            }

            // means beginning of file name, so whole filename should be
            // in one line.
            else if (isStar(cword)) {
                // see if we are in middle of line and
                // if so, start new line, else continue.
                if (!isOnNewLine(formattedWords)) {
                    formattedWords.append(NEW_LINE_CHAR);
                    currentLineLength = indentationLength;
                }

                formattedWords.append(TAB_SPACE_CHAR).append(cword);
                currentLineLength += cword.length() + 1;

                // this should be path name
                if (candidateWords.countTokens() >= 2) {
                    candidateWords.nextToken();
                    cword = candidateWords.nextToken();

                    formattedWords.append(WHITE_SPACE_CHAR).append(cword);
                    currentLineLength += cword.length() + 1;
                }
            }

            else if (cword.startsWith("(")) {

                if (formattedWords.length() > 0) {
                    formattedWords.append(NEW_LINE_CHAR);
                }
                formattedWords.append(TAB_SPACE_CHAR);

                currentLineLength = 1;
                // add until closing bracket

                boolean skipMultiWhiteSpace = false;

                while (!cword.endsWith("):") && candidateWords.hasMoreTokens()) {
                    if (cword.equals(NEW_LINE_CHAR)) {
                        break;
                    }
                    if (cword.equals(WHITE_SPACE_CHAR) && !skipMultiWhiteSpace) {
                        formattedWords.append(cword);
                        currentLineLength += cword.length();
                        skipMultiWhiteSpace = true;
                    }
                    if (!isDelimeter(cword)) {
                        formattedWords.append(cword);
                        currentLineLength += cword.length();
                        skipMultiWhiteSpace = false;
                    }
                    cword = candidateWords.nextToken();
                }

                formattedWords.append(cword);
                currentLineLength += cword.length();
            }

            else if (currentLineLength + cword.length() > MAX_WIDTH) {
                formattedWords.append(NEW_LINE_CHAR)
                              .append(TAB_SPACE_CHAR)
                              .append(cword);
                currentLineLength = indentationLength + cword.length();
            } else {
                if (isOnNewLine(formattedWords)) {
                    formattedWords.append(TAB_SPACE_CHAR);
                } else {
                    formattedWords.append(WHITE_SPACE_CHAR);
                }
                formattedWords.append(cword);
                currentLineLength += cword.length() + 1;
            }
        }
        return formattedWords.toString();
    }

    private boolean isDate(String inputStr) {
        try {
            return isoDate.parse(inputStr) != null;
        } catch (ParseException e) {
            // Don't care
        }
        return false;
    }

    private boolean isEmail(String inputStr) {
        return inputStr.startsWith("<") && inputStr.endsWith(">");
    }

    private boolean isStar(String inputStr) {
        return inputStr.equals("*");
    }

    private boolean isDelimeter(String cword) {
        return DELIMITER_CHARS.contains(cword);
    }

    private boolean isOnNewLine(StringBuilder formattedWords) {
        int len = formattedWords.length();
        return len == 0 || formattedWords.charAt(len - 1) == NEW_LINE_CHAR.charAt(0);
    }

    @Override
    public void formatterStarts(String initialIndentation) {

    }

    @Override
    public void formatterStops() {

    }

}

Back to the top