├── .gitignore
├── META-INF
└── plugin.xml
├── README.md
└── src
├── main
└── java
│ └── pipetableformatter
│ ├── ColumnSplitter.java
│ ├── DelimitersCount.java
│ ├── FormatOptions.java
│ ├── LineSplitter.java
│ ├── PipeTable.java
│ ├── PipeTableFormatter.java
│ ├── PipeTableParser.java
│ ├── Range.java
│ ├── TableDetector.java
│ ├── operation
│ ├── AddColumnBefore.java
│ ├── Format.java
│ ├── FormatAllTables.java
│ ├── Operation.java
│ ├── PipeTableEditor.java
│ ├── Select.java
│ └── TableText.java
│ └── plugin
│ ├── AbstractPipeTableFormatAction.java
│ ├── IdeaPipeTableEditor.java
│ ├── PipeTableActionHandler.java
│ ├── PipeTableAddColumnBeforeAction.java
│ ├── PipeTableFormatAction.java
│ ├── PipeTableFormatAllAction.java
│ ├── PipeTableFormatPreservingOuterStateAction.java
│ └── PipeTableSelectAction.java
└── test
├── java
└── pipetableformatter
│ ├── ColumnSplitterTest.java
│ ├── LineSplitterTest.java
│ ├── PipeTableFormatterTest.java
│ ├── PipeTableParserTest.java
│ ├── PipeTableTest.java
│ ├── TableDetectorTest.java
│ ├── operation
│ ├── AddColumnBeforeOperationTest.java
│ ├── FormatAllTablesOperationTest.java
│ ├── FormatOperationTest.java
│ └── SelectOperationTest.java
│ ├── plugin
│ └── PipeTableFormatterFunctionalTest.java
│ └── testsupport
│ ├── PipeTableBuilder.java
│ └── Utils.java
└── resources
├── expected
├── text-with-a-formatted-pipe-table-with-a-lot-commas.txt
├── text-with-all-formatted-table.txt
├── text-with-formatted-table-and-new-column.txt
├── text-with-formatted-table-with-comment.txt
├── text-with-formatted-table-with-indentation-without-outer-pipes.txt
├── text-with-formatted-table-without-outer-pipes.txt
└── text-with-formatted-table.txt
└── input
├── text-with-a-few-not-formatted-table.txt
├── text-with-a-pipe-table-with-a-lot-commas.txt
├── text-with-not-formatted-table-with-comments.txt
├── text-with-not-formatted-table-with-indentation-without-outer-pipes.txt
└── text-with-not-formatted-table.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *~
3 | /build
4 | /out
5 | /local.properties
6 | /.idea
7 | /captures
8 | *.iml
9 | *.jar
10 |
--------------------------------------------------------------------------------
/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | anton_dev_ua.PipeTableFormatter
3 | Pipe Table Formatter
4 | 0.5.1-SNAPSHOT
5 |
6 |
7 |
10 |
11 |
12 | Supported delimiters: pipe, comma, tab.
13 | When formatting, any of supported delimiters are replaced with pipe.
14 |
15 |
16 | Usage
17 | Select text in the editor or place caret inside a table
18 | and choose action "Pipe Table" -> "Format" in Code menu or in editor popup menu.
19 | ]]>
20 |
21 | Version 0.5.1
23 |
26 |
27 | Version 0.5.0
28 |
29 | - Preserves comment in row commented out with "|--"
30 | - Format Without Outer Pipes action is replaced with Format Preserving Outer State - it preserves indentation and presence/absence of leading/trailing pipes
31 |
32 |
33 | Version 0.4.2
34 |
35 | - Pipe is treated as primary delimiter - if table contains pipe any other delimiter is ignored
36 |
37 |
38 | Version 0.4.1
39 |
40 | - Format All Tables action formats only tables delimited with pipe, ignoring tables delimited with comma and tabulation
41 |
42 |
43 | Version 0.4
44 |
45 | - New action: format all tables in the text
46 |
47 |
48 | Version 0.3.1
49 |
50 | - New action: format table without outer pipes
51 |
52 |
53 | Version 0.3
54 |
55 | - Pipe Table actions are added to editor popup menu
56 | - New action: add column
57 | - New action: auto-select table without formatting
58 | - Bug fixes
59 |
60 |
61 | Version 0.2.3
62 |
63 | - Fixed bug: plugin crashed when column has zero width (no values in the column)
64 |
65 |
66 | Version 0.2.2
67 |
68 | - Don't mix delimiters when detecting and parsing table, i.e. if table delimiter is pipe then comma is not treated as a delimiter.
69 | - Support for tab delimiter
70 |
71 |
72 | Version 0.2.1
73 |
74 | - Autoselect table around caret position
75 |
76 |
77 | Version 0.2
78 |
79 | - Support for comma delimited tables (converting to pipe delimited)
80 | - Support for quoted values
81 |
82 |
83 | Version 0.1
84 |
85 | - Formatting pipe delimited table to human readable representation
86 |
87 | ]]>
88 |
89 |
90 |
91 |
92 |
93 |
95 | com.intellij.modules.lang
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
114 |
115 |
118 |
119 |
122 |
123 |
126 |
127 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | PipeTableFormatter
2 | ==================
3 |
4 | Small IDEA plugin for formatting text blocks that represents a table delimited by pipe (|). For example, can be used to format JBehave examples table.
5 |
6 | Thanks to Idris Ahmed ([idrisahmed251] (https://github.com/idrisahmed251)) and to Jesse Kuhnert ([jkuhnert] (https://github.com/jkuhnert)) for ideas to use comma and tab as delimeters.
7 |
8 | Features
9 | --------
10 |
11 | - Formats block of text that represents a table: width of a column becomes constant from top to bottom by adjusting it to most wide value in the column.
12 | - Supported delimiters: pipe, comma, tab.
13 | - Any of supported delimiters, when formatting, are converted to pipe.
14 | - If text is not selected explicitly - automatically detects start and end of a table on base of caret position.
15 | - All tables in the editor can be formatted by one action
16 |
17 | Example
18 | -------
19 |
20 | text like:
21 |
22 |
23 | |Header 1|Header 2|
24 | |val1|val2|
25 |
26 |
27 | or like:
28 |
29 |
30 | Header 1,Header 2
31 | val1,val2
32 |
33 |
34 | is formatted to:
35 |
36 |
37 | | Header 1 | Header 2 |
38 | | val1 | val2 |
39 |
40 |
41 | Installation
42 | -----------
43 |
44 | From Plugin Repository: http://plugins.jetbrains.com/plugin/7550
45 |
46 | Usage
47 | -----
48 |
49 | 1. Select text that should be formatted or just put caret somewhere inside a table.
50 | 2. Choose action `Pipe Table -> Format` in Code menu or popup menu.
51 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/ColumnSplitter.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import java.util.Iterator;
4 |
5 | public class ColumnSplitter implements Iterable, Iterator {
6 | public static final String PIPE = "|";
7 | public static final String PIPE_COMMENT_START = "|--";
8 | public static final String PIPE_COMMENT_END = "--|";
9 | private final int leadingSpaces;
10 | private String line;
11 | private int startIndex = 0;
12 | private int length = 0;
13 | private boolean insideQuoted = false;
14 | private boolean quoted = false;
15 | private Character delimiter;
16 | private int prevStartIndex;
17 | private int columnIndex;
18 | private boolean leadingPipe;
19 | private boolean trailingPipe;
20 | private boolean commented;
21 |
22 | public ColumnSplitter(String line, Character delimiter) {
23 | this.delimiter = delimiter;
24 | this.leadingSpaces = countLeadingSpaces(line);
25 | this.line = line.trim();
26 | init();
27 | }
28 |
29 | private int countLeadingSpaces(String line) {
30 | int charCount = 0;
31 | while (line.length() > charCount && line.charAt(charCount++) <= ' ') ;
32 | return charCount - 1;
33 | }
34 |
35 | private void init() {
36 | length = line.length();
37 | if (line.startsWith(PIPE_COMMENT_START)) {
38 | startIndex = PIPE_COMMENT_START.length();
39 | commented = true;
40 | leadingPipe = true;
41 | } else if (line.startsWith(PIPE)) {
42 | startIndex = 1;
43 | leadingPipe = true;
44 | }
45 | if (line.endsWith(PIPE_COMMENT_END)) {
46 | length -= PIPE_COMMENT_END.length();
47 | trailingPipe = true;
48 | } else if (line.endsWith(PIPE)) {
49 | length--;
50 | trailingPipe = true;
51 | }
52 | columnIndex = -1;
53 | }
54 |
55 | @Override
56 | public String next() {
57 | int endIndex = startIndex;
58 | while (hasMoreChars(endIndex) && notDelimiter(endIndex)) {
59 | detectQuoted(endIndex++);
60 | }
61 | String value = line.substring(startIndex, endIndex);
62 | prevStartIndex = startIndex;
63 | startIndex = endIndex + 1;
64 | columnIndex++;
65 | return openQuotes(value);
66 | }
67 |
68 | private boolean hasMoreChars(int endIndex) {
69 | return endIndex < length;
70 | }
71 |
72 | private boolean notDelimiter(int index) {
73 | return insideQuoted || line.charAt(index) != delimiter;
74 | }
75 |
76 | private void detectQuoted(int index) {
77 | if (line.charAt(index) == '"') {
78 | quoted = true;
79 | insideQuoted = !insideQuoted;
80 | }
81 | }
82 |
83 | private String openQuotes(String value) {
84 | if (quoted) {
85 | quoted = false;
86 | return replaceTwoQuotesWithOne(removeOpenAndCloseQuotes(value));
87 | } else {
88 | return value;
89 | }
90 | }
91 |
92 | private String replaceTwoQuotesWithOne(String value) {
93 | return value.replaceAll("\"\"", "\"");
94 | }
95 |
96 | private String removeOpenAndCloseQuotes(String value) {
97 | return value.replaceAll("(^ *\")|(\" *$)", "");
98 | }
99 |
100 | public int currentColumnStartIndex() {
101 | return prevStartIndex + leadingSpaces;
102 | }
103 |
104 | public int currentColumnEndIndex() {
105 | return startIndex - 1 + leadingSpaces;
106 | }
107 |
108 | @Override
109 | public Iterator iterator() {
110 | return this;
111 | }
112 |
113 | @Override
114 | public boolean hasNext() {
115 | return startIndex < length;
116 | }
117 |
118 | @Override
119 | public void remove() {
120 | throw new UnsupportedOperationException();
121 | }
122 |
123 | public int currentColumnIndex() {
124 | return columnIndex;
125 | }
126 |
127 | public int getLeadingSpaces() {
128 | return leadingSpaces;
129 | }
130 |
131 | public String getIndentetion() {
132 | if(leadingSpaces > 0) {
133 | return String.format("%" + leadingSpaces + "s", " ");
134 | } else {
135 | return "";
136 | }
137 | }
138 |
139 | public boolean hasLeadingPipe() {
140 | return leadingPipe;
141 | }
142 |
143 | public boolean hasTrailingPipe() {
144 | return trailingPipe;
145 | }
146 |
147 | public boolean isCommented() {
148 | return commented;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/DelimitersCount.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | public class DelimitersCount {
9 |
10 | private static final char PIPE = '|';
11 | private static final char[] DEFAULT_DELIMITERS = new char[]{PIPE, ',', '\t'};
12 |
13 | private String text;
14 | private char[] delimiters;
15 | Map counters = new HashMap();
16 |
17 | private DelimitersCount(String text, Range lineRange, char... delimiters) {
18 | this.text = text;
19 | this.delimiters = delimiters;
20 | initCounters();
21 | count(text, lineRange.getStart(), lineRange.getEnd());
22 | }
23 |
24 | public static DelimitersCount delimitersCountIn(String text) {
25 | return new DelimitersCount(text, new Range(0, text.length()), DEFAULT_DELIMITERS);
26 | }
27 |
28 | public static DelimitersCount delimitersCountIn(String text, Range lineRange) {
29 | return new DelimitersCount(text, lineRange, DEFAULT_DELIMITERS);
30 | }
31 |
32 | public static DelimitersCount pipesCountIn(String text, Range lineRange) {
33 | return new DelimitersCount(text, lineRange, PIPE);
34 | }
35 |
36 | private void initCounters() {
37 | for (char delimiter : delimiters) {
38 | counters.put(delimiter, 0);
39 | }
40 | }
41 |
42 | public boolean isSameCount(DelimitersCount another) {
43 | if (pipeIsPresentInThisOr(another)) {
44 | return isNumberOfPipesTheSameAsIn(another);
45 | } else {
46 | return isNumberOfAnyDelimiterTheSameAsIn(another);
47 | }
48 | }
49 |
50 | private boolean isNumberOfAnyDelimiterTheSameAsIn(DelimitersCount another) {
51 | for (char delimiter : counters.keySet()) {
52 | if (counters.get(delimiter).equals(another.counters.get(delimiter)) && counters.get(delimiter) > 0) {
53 | return true;
54 | }
55 | }
56 | return false;
57 | }
58 |
59 | private boolean isNumberOfPipesTheSameAsIn(DelimitersCount another) {
60 | return counters.get(PIPE).equals(another.counters.get(PIPE));
61 | }
62 |
63 | private boolean pipeIsPresentInThisOr(DelimitersCount another) {
64 | return counters.get(PIPE) > 0 || another.counters.get(PIPE) > 0;
65 | }
66 |
67 | public boolean isZero() {
68 | for (int count : counters.values()) {
69 | if (count != 0) return false;
70 | }
71 | return true;
72 | }
73 |
74 | private int count(String text, int start, int end) {
75 | boolean quoted = false;
76 | int count = 0;
77 |
78 | for (int index = start >= 0 ? start : 0; index < end; index++) {
79 | if (text.charAt(index) == '"') quoted = !quoted;
80 | if (quoted) continue;
81 | checkForDelimiter(text.charAt(index));
82 | }
83 |
84 | return count;
85 | }
86 |
87 | private void checkForDelimiter(char character) {
88 | if (counters.containsKey(character)) {
89 | counters.put(character, counters.get(character) + 1);
90 | }
91 | }
92 |
93 | public Character mostFrequent() {
94 | if (atLeastTwoPipesPerLine()) {
95 | return PIPE;
96 | } else {
97 | return findMostFrequentDelimiter();
98 | }
99 | }
100 |
101 | @NotNull
102 | private Character findMostFrequentDelimiter() {
103 | char maxDelimiter = 0;
104 | int maxCount = 0;
105 | for (char delimiter : counters.keySet()) {
106 | if (counters.get(delimiter) > maxCount) {
107 | maxCount = counters.get(delimiter);
108 | maxDelimiter = delimiter;
109 | }
110 | }
111 |
112 | return maxDelimiter;
113 | }
114 |
115 | private boolean atLeastTwoPipesPerLine() {
116 | return text.split("\n").length * 2 <= counters.get(PIPE);
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/FormatOptions.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | public class FormatOptions {
4 |
5 | private boolean preserveOuterState = false;
6 |
7 |
8 | public static FormatOptions formatOptions() {
9 | return new FormatOptions();
10 | }
11 |
12 | public FormatOptions preserveOuterState() {
13 | preserveOuterState = true;
14 | return this;
15 | }
16 |
17 | public boolean shouldPreserveOuterState() {
18 | return preserveOuterState;
19 | }
20 |
21 | public boolean shouldNotPreserveOuterState() {
22 | return !preserveOuterState;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/LineSplitter.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import java.util.Iterator;
4 |
5 | public class LineSplitter implements Iterable, Iterator {
6 | private String notFormattedText;
7 | private int startIndex;
8 | private int endIndex;
9 | private String endOfLine;
10 | private int prevStartIndex;
11 | private int lineIndex;
12 |
13 | public LineSplitter(String notFormattedText) {
14 | this.notFormattedText = notFormattedText;
15 | startIndex = 0;
16 | endIndex = 0;
17 | endOfLine = "";
18 | lineIndex = -1;
19 | }
20 |
21 | @Override
22 | public String next() {
23 |
24 | int winEof = notFormattedText.indexOf(PipeTableParser.WIN_EOF, startIndex);
25 | int linuxEof = notFormattedText.indexOf(PipeTableParser.LINUX_EOF, startIndex);
26 |
27 | if (winEof < 0 && linuxEof < 0) {
28 | endIndex = notFormattedText.length();
29 | endOfLine = "";
30 | } else if (winEof > 0 && winEof < linuxEof) {
31 | endIndex = winEof;
32 | endOfLine = PipeTableParser.WIN_EOF;
33 | } else {
34 | endIndex = linuxEof;
35 | endOfLine = PipeTableParser.LINUX_EOF;
36 | }
37 |
38 | String line = notFormattedText.substring(startIndex, endIndex);
39 | prevStartIndex = startIndex;
40 | startIndex = endIndex + endOfLine.length();
41 | lineIndex++;
42 |
43 | return line;
44 | }
45 |
46 | public String getEndOfLine() {
47 | return endOfLine;
48 | }
49 |
50 | @Override
51 | public Iterator iterator() {
52 | return this;
53 | }
54 |
55 | @Override
56 | public boolean hasNext() {
57 | return startIndex < notFormattedText.length();
58 | }
59 |
60 | @Override
61 | public void remove() {
62 | throw new UnsupportedOperationException();
63 | }
64 |
65 | public int currentLineStartIndex() {
66 | return prevStartIndex;
67 | }
68 |
69 | public int currentLineEndIndex() {
70 | return startIndex - endOfLine.length();
71 | }
72 |
73 | public int currentLineIndex() {
74 | return lineIndex;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/PipeTable.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | //TODO: make it immutable (use builder?)
7 | public class PipeTable {
8 |
9 | List table;
10 | private int selectedRow = -1;
11 | private int selectedColumn = -1;
12 |
13 | public PipeTable(List table) {
14 | this.table = new ArrayList(table);
15 | }
16 |
17 | public int getRowCount() {
18 | return table.size();
19 | }
20 |
21 | public String getValue(int row, int column) {
22 | return table.get(row).get(column);
23 | }
24 |
25 | public Row[] rows() {
26 | return table.toArray(new Row[table.size()]);
27 | }
28 |
29 | public int getColumnCount() {
30 | return table.size() > 0 ? table.get(0).size() : 0;
31 | }
32 |
33 | public void addColumnBefore(int columnIndex) {
34 | for (Row row : table) {
35 | row.add(columnIndex, "");
36 | }
37 | }
38 |
39 | public int getSelectedRow() {
40 | return selectedRow;
41 | }
42 |
43 | public void setSelectedRow(int selectedRow) {
44 | this.selectedRow = selectedRow;
45 | }
46 |
47 | public int getSelectedColumn() {
48 | return selectedColumn;
49 | }
50 |
51 | public void setSelectedColumn(int selectedColumn) {
52 | this.selectedColumn = selectedColumn;
53 | }
54 |
55 | public boolean isRowCommented(int row) {
56 | return table.get(row).isCommented();
57 | }
58 |
59 | //TODO: make it immutable (use builder?)
60 | public static class Row {
61 | List row;
62 | private String endOfLine;
63 | private boolean commented;
64 | private String indentation;
65 | private boolean leadingPipe;
66 | private boolean trailingPipe;
67 |
68 | public Row(List columns, String endOfLine) {
69 | this.endOfLine = endOfLine != null ? endOfLine : "";
70 | row = new ArrayList(columns);
71 | }
72 |
73 | public int size() {
74 | return row.size();
75 | }
76 |
77 | public void add(String value) {
78 | row.add(new Cell(value));
79 | }
80 |
81 | public void add(int column, String value) {
82 | row.add(column, new Cell(value));
83 | }
84 |
85 | public String get(int column) {
86 | return row.get(column).getValue();
87 | }
88 |
89 | public Cell[] columns() {
90 | return row.toArray(new Cell[row.size()]);
91 | }
92 |
93 | public String endOfLine() {
94 | return endOfLine;
95 | }
96 |
97 | public boolean isCommented() {
98 | return commented;
99 | }
100 |
101 | public void setCommented(boolean commented) {
102 | this.commented = commented;
103 | }
104 |
105 | public String getIndentation() {
106 | return indentation;
107 | }
108 |
109 | public void setIndentation(String indentation) {
110 | this.indentation = indentation;
111 | }
112 |
113 | public boolean hasLeadingPipe() {
114 | return leadingPipe;
115 | }
116 |
117 | public boolean hasTrailingPipe() {
118 | return trailingPipe;
119 | }
120 |
121 | public void setLeadingPipe(boolean leadingPipe) {
122 | this.leadingPipe = leadingPipe;
123 | }
124 |
125 | public void setTrailingPipe(boolean trailingPipe) {
126 | this.trailingPipe = trailingPipe;
127 | }
128 | }
129 |
130 | public static class Cell {
131 | private String value;
132 |
133 | public Cell(String value) {
134 | this.value = value != null ? value.trim() : "";
135 | }
136 |
137 | public String getValue() {
138 | return value;
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/PipeTableFormatter.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import pipetableformatter.PipeTable.Cell;
4 |
5 | import static pipetableformatter.FormatOptions.formatOptions;
6 |
7 | public class PipeTableFormatter {
8 |
9 | public static final String PIPE = "|";
10 | public static final String PIPE_COMMENT_START = "|--";
11 | public static final String PIPE_COMMENT_END = "--|";
12 | private FormatOptions formatOptions;
13 |
14 | private PipeTableFormatter() {
15 | }
16 |
17 | public String format(PipeTable pipeTable) {
18 | return formatPipeTable(
19 | pipeTable,
20 | formatOptions != null ? formatOptions : formatOptions()
21 | );
22 | }
23 |
24 | private String formatPipeTable(PipeTable table, FormatOptions options) {
25 |
26 | int[] columnsMaxLength = calculateColumnsMaxLength(table);
27 |
28 | StringBuffer buffer = new StringBuffer();
29 | for (PipeTable.Row row : table.rows()) {
30 | appendFirstPipe(options, buffer, row);
31 | int columnIndex = 0;
32 | for (Cell cell : row.columns()) {
33 | int width = correctWidthForCommentedRow(columnsMaxLength[columnIndex], row, columnIndex);
34 | String formattedValue = padValue(width, cell.getValue());
35 | buffer.append(formattedValue);
36 | columnIndex++;
37 | appendInternalPipe(buffer, row, columnIndex);
38 | }
39 | appendLastPipe(options, buffer, row);
40 | buffer.append(row.endOfLine());
41 | }
42 | return buffer.toString();
43 | }
44 |
45 | private int correctWidthForCommentedRow(int maxWidth, PipeTable.Row row, int columnIndex) {
46 | return maxWidth - (row.isCommented() && (columnIndex == 0 || columnIndex == row.size() - 1) ? 2 : 0);
47 | }
48 |
49 | private void appendFirstPipe(FormatOptions options, StringBuffer buffer, PipeTable.Row row) {
50 | String pipe = row.isCommented() ? PIPE_COMMENT_START : PIPE;
51 | if (options.shouldPreserveOuterState()) {
52 | buffer.append(row.getIndentation());
53 | }
54 | if (options.shouldNotPreserveOuterState() || row.hasLeadingPipe()) {
55 | buffer.append(pipe).append(" ");
56 | }
57 | }
58 |
59 | private void appendLastPipe(FormatOptions options, StringBuffer buffer, PipeTable.Row row) {
60 | String pipe = row.isCommented() ? PIPE_COMMENT_END : PIPE;
61 | if (options.shouldNotPreserveOuterState() || row.hasTrailingPipe()) {
62 | buffer.append(" ").append(pipe);
63 | }
64 | }
65 |
66 |
67 | private void appendInternalPipe(StringBuffer buffer, PipeTable.Row row, int columnIndex) {
68 | if (columnIndex < row.size()) {
69 | buffer.append(" ").append(PIPE).append(" ");
70 | }
71 | }
72 |
73 | private String padValue(int width, String value) {
74 | if (width > 0) {
75 | return String.format("%-" + width + "s", value);
76 | } else {
77 | return "";
78 | }
79 | }
80 |
81 | private int[] calculateColumnsMaxLength(PipeTable table) {
82 | int[] columnsMaxLength = new int[table.getColumnCount()];
83 |
84 | for (PipeTable.Row row : table.rows()) {
85 | int columnIndex = 0;
86 | for (Cell cell : row.columns()) {
87 | int length = cellValueLength(row, columnIndex, cell);
88 | if (length > columnsMaxLength[columnIndex]) {
89 | columnsMaxLength[columnIndex] = length;
90 | }
91 | columnIndex++;
92 | }
93 | }
94 | return columnsMaxLength;
95 | }
96 |
97 | private int cellValueLength(PipeTable.Row row, int columnIndex, Cell cell) {
98 | return cell.getValue().length() + (row.isCommented() && (columnIndex == 0 || columnIndex == row.size() - 1) ? 2 : 0);
99 | }
100 |
101 | public static PipeTableFormatter formatter() {
102 | return new PipeTableFormatter();
103 | }
104 |
105 | public PipeTableFormatter withOptions(FormatOptions options) {
106 | this.formatOptions = options;
107 | return this;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/PipeTableParser.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import static pipetableformatter.DelimitersCount.*;
7 |
8 | public class PipeTableParser {
9 | public static final String WIN_EOF = "\r\n";
10 | public static final String LINUX_EOF = "\n";
11 | public List tableRows = new ArrayList();
12 | public int maxRowSize = 0;
13 | private int caretPosition = -1;
14 | private int selectedRow = -1;
15 | private Character delimiter;
16 | private int selectedColumn = -1;
17 | private int currentLineStartIndex;
18 | private String notFormattedText;
19 |
20 | public PipeTableParser(String notFormattedText) {
21 | this.notFormattedText = notFormattedText;
22 | }
23 |
24 | public PipeTableParser detectingCellByPosition(int caretPosition) {
25 | this.caretPosition = caretPosition;
26 | return this;
27 | }
28 |
29 | public PipeTable parse() {
30 | parseText();
31 | PipeTable pipeTable = new PipeTable(tableRows);
32 | pipeTable.setSelectedRow(selectedRow);
33 | pipeTable.setSelectedColumn(selectedColumn);
34 | return pipeTable;
35 | }
36 |
37 | private void parseText() {
38 |
39 | delimiter = detectDelimiter(notFormattedText);
40 | LineSplitter lineSplitter = new LineSplitter(notFormattedText);
41 |
42 | for (String line : lineSplitter) {
43 | boolean rowWithCaret = false;
44 | if (caretPosition >= lineSplitter.currentLineStartIndex() && caretPosition <= lineSplitter.currentLineEndIndex()) {
45 | selectedRow = lineSplitter.currentLineIndex();
46 | currentLineStartIndex = lineSplitter.currentLineStartIndex();
47 | rowWithCaret = true;
48 | }
49 | parseLine(line, lineSplitter.getEndOfLine(), rowWithCaret);
50 | }
51 |
52 | normalizeRows();
53 | }
54 |
55 | private void normalizeRows() {
56 | for (PipeTable.Row row : tableRows) {
57 | for (int i = row.size(); i < maxRowSize; i++) {
58 | row.add("");
59 | }
60 | }
61 | }
62 |
63 | private Character detectDelimiter(String text) {
64 | return delimitersCountIn(text).mostFrequent();
65 | }
66 |
67 | private void parseLine(String line, String endOfLine, boolean rowWithCaret) {
68 | PipeTable.Row row = splitForColumns(line, rowWithCaret, endOfLine);
69 |
70 | rememberMaxLength(row.size());
71 |
72 | tableRows.add(row);
73 | }
74 |
75 | private PipeTable.Row splitForColumns(String line, boolean rowWithCaret, String endOfLine) {
76 | List cells = new ArrayList();
77 | int rowCaretPosition = caretPosition - currentLineStartIndex;
78 |
79 | ColumnSplitter tableRow = new ColumnSplitter(line, delimiter);
80 | for (String value : tableRow) {
81 | cells.add(new PipeTable.Cell(value));
82 | if (rowWithCaret) {
83 | if (rowCaretPosition >= tableRow.currentColumnStartIndex() && rowCaretPosition <= tableRow.currentColumnEndIndex()) {
84 | selectedColumn = tableRow.currentColumnIndex();
85 | } else if (tableRow.currentColumnIndex() == 0 && rowCaretPosition < tableRow.currentColumnStartIndex()) {
86 | selectedColumn = 0;
87 | }
88 | }
89 | }
90 | if (rowWithCaret && selectedColumn == -1) {
91 | selectedColumn = cells.size();
92 | }
93 |
94 | PipeTable.Row row = new PipeTable.Row(cells, endOfLine);
95 | row.setCommented(tableRow.isCommented());
96 | row.setIndentation(tableRow.getIndentetion());
97 | row.setLeadingPipe(tableRow.hasLeadingPipe());
98 | row.setTrailingPipe(tableRow.hasTrailingPipe());
99 |
100 | return row;
101 | }
102 |
103 | private void rememberMaxLength(int size) {
104 | if (size > maxRowSize) {
105 | maxRowSize = size;
106 | }
107 | }
108 | }
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/Range.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | public class Range {
4 |
5 | public static final Range EMPTY = new Range(0, 0);
6 |
7 | private int start;
8 | private int end;
9 |
10 | public Range(int start, int end) {
11 |
12 | this.start = start;
13 | this.end = end;
14 | }
15 |
16 | public int getStart() {
17 | return start;
18 | }
19 |
20 | public int getEnd() {
21 | return end;
22 | }
23 |
24 | public boolean isNotEmpty() {
25 | return end - start > 0;
26 | }
27 |
28 | public boolean isEmpty() {
29 | return end - start == 0;
30 | }
31 |
32 | @Override
33 | public boolean equals(Object o) {
34 | if (this == o) return true;
35 | if (!(o instanceof Range)) return false;
36 |
37 | Range range = (Range) o;
38 |
39 | if (end != range.end) return false;
40 | if (start != range.start) return false;
41 |
42 | return true;
43 | }
44 |
45 | @Override
46 | public int hashCode() {
47 | int result = start;
48 | result = 31 * result + end;
49 | return result;
50 | }
51 |
52 | @Override
53 | public String toString() {
54 | return "Range{" +
55 | "start=" + start +
56 | ", end=" + end +
57 | '}';
58 | }
59 |
60 | public Range plus(int offset) {
61 | return new Range(start + offset, end + offset);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/TableDetector.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import static pipetableformatter.DelimitersCount.*;
4 |
5 | public class TableDetector {
6 |
7 | private String text;
8 | private DelimitersCount baseLineDelimitersCount;
9 | private boolean onlyPipe;
10 |
11 | private TableDetector(String text) {
12 | this.text = "\n" + text + "\n";
13 | }
14 |
15 | public static TableDetector detectTableIn(String text) {
16 | return new TableDetector(text);
17 | }
18 |
19 | public Range around(int position) {
20 | Range baseLine = findBaseLine(position + 1);
21 | baseLineDelimitersCount = asIn(baseLine);
22 | return baseLineDelimitersCount.isZero() ? Range.EMPTY : findTableRange(baseLine);
23 | }
24 |
25 | private Range findBaseLine(int position) {
26 | return new Range(findSOL(position), findEOL(position));
27 | }
28 |
29 | private Range findTableRange(Range baseLine) {
30 | return new Range(findStartOfTableOn(baseLine), findEndOfTableOn(baseLine) - 1);
31 | }
32 |
33 | private int findStartOfTableOn(Range line) {
34 | return tableContains(line) ? findStartOfTableOn(previous(line)) : line.getEnd();
35 | }
36 |
37 | private int findEndOfTableOn(Range line) {
38 | return tableContains(line) ? findEndOfTableOn(next(line)) : line.getStart();
39 | }
40 |
41 | private int findEOL(int position) {
42 | return text.indexOf("\n", position);
43 | }
44 |
45 | private int findSOL(int position) {
46 | return text.lastIndexOf("\n", position - 1);
47 | }
48 |
49 | private boolean tableContains(Range line) {
50 | return baseLineDelimitersCount.isSameCount(asIn(line));
51 | }
52 |
53 | private DelimitersCount asIn(Range currLine) {
54 | return onlyPipe ? pipesCountIn(text, currLine) : delimitersCountIn(text, currLine);
55 | }
56 |
57 | private Range previous(Range line) {
58 | return new Range(findSOL(line.getStart() - 1), line.getStart());
59 | }
60 |
61 | private Range next(Range line) {
62 | return new Range(line.getEnd(), findEOL(line.getEnd() + 1));
63 | }
64 |
65 | public TableDetector usingOnlyPipe() {
66 | this.onlyPipe = true;
67 | return this;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/operation/AddColumnBefore.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | import pipetableformatter.PipeTable;
4 | import pipetableformatter.PipeTableParser;
5 |
6 | import static pipetableformatter.PipeTableFormatter.formatter;
7 |
8 | public class AddColumnBefore extends Operation {
9 |
10 | private final PipeTableEditor editor;
11 |
12 | public AddColumnBefore(PipeTableEditor editor) {
13 | this.editor = editor;
14 | }
15 |
16 | @Override
17 | protected void perform() {
18 | TableText tableText = getSelectedTable(editor);
19 | if (tableText.isNotEmpty()) {
20 | PipeTable pipeTable = parseTable(tableText, editor.getCaretPosition());
21 | pipeTable.addColumnBefore(pipeTable.getSelectedColumn());
22 | String formattedText = formatter().format(pipeTable);
23 | editor.replaceText(formattedText, tableText.getRange());
24 | }
25 | }
26 |
27 | private PipeTable parseTable(TableText tableText, int caretPosition) {
28 | return new PipeTableParser(tableText.getText())
29 | .detectingCellByPosition(caretPosition - tableText.getRange().getStart())
30 | .parse();
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/operation/Format.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | import pipetableformatter.FormatOptions;
4 | import pipetableformatter.PipeTable;
5 | import pipetableformatter.PipeTableParser;
6 |
7 | import static pipetableformatter.FormatOptions.formatOptions;
8 | import static pipetableformatter.PipeTableFormatter.formatter;
9 |
10 | public class Format extends Operation {
11 |
12 | private final PipeTableEditor editor;
13 | private final FormatOptions options;
14 |
15 | public Format(PipeTableEditor editor) {
16 | this(editor, formatOptions());
17 | }
18 |
19 | public Format(PipeTableEditor editor, FormatOptions formatOptions) {
20 | this.editor = editor;
21 | this.options = formatOptions;
22 | }
23 |
24 | protected void perform() {
25 | TableText tableText = getSelectedTable(editor);
26 | if (tableText.isNotEmpty()) {
27 | PipeTable pipeTable = new PipeTableParser(tableText.getText()).parse();
28 | String formattedText = formatter().withOptions(options).format(pipeTable);
29 | editor.replaceText(formattedText, tableText.getRange());
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/operation/FormatAllTables.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | import pipetableformatter.PipeTable;
4 | import pipetableformatter.PipeTableParser;
5 | import pipetableformatter.Range;
6 |
7 | import static pipetableformatter.PipeTableFormatter.formatter;
8 | import static pipetableformatter.TableDetector.detectTableIn;
9 |
10 | public class FormatAllTables extends Operation {
11 |
12 | private PipeTableEditor editor;
13 |
14 | public FormatAllTables(PipeTableEditor editor) {
15 | this.editor = editor;
16 | }
17 |
18 | @Override
19 | protected void perform() {
20 | formatNext(editor.getText(), editor.getText().length() - 1);
21 | editor.setSelection(new Range(0, 0));
22 | }
23 |
24 | private void formatNext(String text, int position) {
25 | if (position < 0) return;
26 |
27 | Range tableRange = detectTableIn(text).usingOnlyPipe().around(position);
28 | if (tableRange.isNotEmpty()) {
29 | formatAndReplace(text, tableRange);
30 | formatNext(text, tableRange.getStart() - 1);
31 | } else {
32 | formatNext(text, text.lastIndexOf("\n", position) - 1);
33 | }
34 | }
35 |
36 | private void formatAndReplace(String text, Range tableRange) {
37 | String textToFormat = text.substring(tableRange.getStart(), tableRange.getEnd());
38 | PipeTable pipeTable = parse(textToFormat);
39 | if (pipeTable.getRowCount() > 1) {
40 | String formattedText = formatter().format(pipeTable);
41 | editor.replaceText(formattedText, tableRange);
42 | }
43 | }
44 |
45 | private PipeTable parse(String textToFormat) {
46 | return new PipeTableParser(textToFormat).parse();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/operation/Operation.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | import pipetableformatter.Range;
4 | import pipetableformatter.TableDetector;
5 |
6 | import static pipetableformatter.TableDetector.detectTableIn;
7 |
8 | public abstract class Operation implements Runnable {
9 |
10 | @Override
11 | final public void run() {
12 | perform();
13 | }
14 |
15 | protected abstract void perform();
16 |
17 | final protected TableText getSelectedTable(PipeTableEditor editor) {
18 | TableText tableText = editor.getSelectedText();
19 | if(tableText.isEmpty()) {
20 | String text = editor.getText();
21 | int caretPosition = editor.getCaretPosition();
22 | Range range = detectTableIn(text).around(caretPosition);
23 | tableText = new TableText(text.substring(range.getStart(), range.getEnd()), range);
24 | }
25 | return tableText;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/operation/PipeTableEditor.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | import pipetableformatter.Range;
4 |
5 | public interface PipeTableEditor {
6 | TableText getSelectedText();
7 | String getText();
8 | int getCaretPosition();
9 | void replaceText(String formattedText, Range tableRange);
10 | void setSelection(Range range);
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/operation/Select.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | public class Select extends Operation {
4 |
5 | private final PipeTableEditor editor;
6 |
7 | public Select(PipeTableEditor editor) {
8 | this.editor = editor;
9 | }
10 |
11 | @Override
12 | protected void perform() {
13 | TableText tableText = getSelectedTable(editor);
14 | if(tableText.isNotEmpty()) {
15 | editor.setSelection(tableText.getRange());
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/operation/TableText.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | import pipetableformatter.Range;
4 |
5 | public class TableText {
6 | private final String text;
7 | private final Range range;
8 |
9 | public TableText(String text, Range range) {
10 | this.text = text;
11 | this.range = range;
12 | }
13 |
14 | public String getText() {
15 | return text;
16 | }
17 |
18 | public Range getRange() {
19 | return range;
20 | }
21 |
22 | public boolean isNotEmpty() {
23 | return range.isNotEmpty();
24 | }
25 |
26 | public boolean isEmpty() {
27 | return range.isEmpty();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/plugin/AbstractPipeTableFormatAction.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.plugin;
2 |
3 | import com.intellij.openapi.actionSystem.ActionPlaces;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.editor.actionSystem.EditorAction;
6 | import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
7 |
8 | public class AbstractPipeTableFormatAction extends EditorAction {
9 | public AbstractPipeTableFormatAction(EditorActionHandler defaultHandler) {
10 | super(defaultHandler);
11 | }
12 |
13 | @Override
14 | public void update(AnActionEvent e) {
15 | super.update(e);
16 | if (ActionPlaces.isPopupPlace(e.getPlace())) {
17 | e.getPresentation().setVisible(e.getPresentation().isEnabled());
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/plugin/IdeaPipeTableEditor.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.plugin;
2 |
3 | import com.intellij.openapi.editor.Editor;
4 | import com.intellij.openapi.editor.SelectionModel;
5 | import pipetableformatter.Range;
6 | import pipetableformatter.operation.PipeTableEditor;
7 | import pipetableformatter.operation.TableText;
8 |
9 | public class IdeaPipeTableEditor implements PipeTableEditor {
10 | protected final Editor editor;
11 |
12 | public IdeaPipeTableEditor(Editor editor) {
13 | this.editor = editor;
14 | }
15 |
16 | private SelectionModel getSelectionModel() {
17 | return editor.getSelectionModel();
18 | }
19 |
20 | @Override
21 | public TableText getSelectedText() {
22 | return new TableText(
23 | getSelectionModel().getSelectedText(),
24 | new Range(getSelectionModel().getSelectionStart(), getSelectionModel().getSelectionEnd())
25 | );
26 | }
27 |
28 | @Override
29 | public String getText() {
30 | return editor.getDocument().getText();
31 | }
32 |
33 | @Override
34 | public int getCaretPosition() {
35 | return editor.getCaretModel().getOffset();
36 | }
37 |
38 | @Override
39 | public void replaceText(String newText, Range tableRange) {
40 | getSelectionModel().setSelection(tableRange.getStart(), tableRange.getEnd());
41 | editor.getDocument().replaceString(tableRange.getStart(), tableRange.getEnd(), newText);
42 | }
43 |
44 | @Override
45 | public void setSelection(Range range) {
46 | getSelectionModel().setSelection(range.getStart(), range.getEnd());
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/plugin/PipeTableActionHandler.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.plugin;
2 |
3 | import com.intellij.openapi.actionSystem.DataContext;
4 | import com.intellij.openapi.application.ApplicationManager;
5 | import com.intellij.openapi.editor.Caret;
6 | import com.intellij.openapi.editor.Editor;
7 | import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
8 | import org.jetbrains.annotations.Nullable;
9 |
10 | abstract class PipeTableActionHandler extends EditorActionHandler {
11 |
12 | @Override
13 | protected void doExecute(Editor editor, @Nullable Caret caret, final DataContext dataContext) {
14 | ApplicationManager.getApplication().runWriteAction(action(editor));
15 | }
16 |
17 | abstract protected Runnable action(Editor editor);
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/plugin/PipeTableAddColumnBeforeAction.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.plugin;
2 |
3 | import com.intellij.openapi.editor.Editor;
4 | import pipetableformatter.operation.AddColumnBefore;
5 |
6 | public class PipeTableAddColumnBeforeAction extends AbstractPipeTableFormatAction {
7 | public PipeTableAddColumnBeforeAction() {
8 | super(new PipeTableActionHandler() {
9 | @Override
10 | protected Runnable action(Editor editor) {
11 | return new AddColumnBefore(new IdeaPipeTableEditor(editor));
12 | }
13 | });
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/plugin/PipeTableFormatAction.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.plugin;
2 |
3 | import com.intellij.openapi.editor.Editor;
4 | import pipetableformatter.operation.Format;
5 |
6 | public class PipeTableFormatAction extends AbstractPipeTableFormatAction {
7 |
8 | public PipeTableFormatAction() {
9 | super(new PipeTableActionHandler() {
10 | @Override
11 | protected Runnable action(Editor editor) {
12 | return new Format(new IdeaPipeTableEditor(editor));
13 | }
14 | });
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/plugin/PipeTableFormatAllAction.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.plugin;
2 |
3 | import com.intellij.openapi.editor.Editor;
4 | import pipetableformatter.operation.FormatAllTables;
5 |
6 | public class PipeTableFormatAllAction extends AbstractPipeTableFormatAction {
7 |
8 | public PipeTableFormatAllAction() {
9 | super(new PipeTableActionHandler() {
10 | @Override
11 | protected Runnable action(Editor editor) {
12 | return new FormatAllTables(new IdeaPipeTableEditor(editor));
13 | }
14 | });
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/plugin/PipeTableFormatPreservingOuterStateAction.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.plugin;
2 |
3 | import com.intellij.openapi.editor.Editor;
4 | import pipetableformatter.operation.Format;
5 |
6 | import static pipetableformatter.FormatOptions.formatOptions;
7 |
8 | public class PipeTableFormatPreservingOuterStateAction extends AbstractPipeTableFormatAction {
9 |
10 | public PipeTableFormatPreservingOuterStateAction() {
11 | super(new PipeTableActionHandler() {
12 | @Override
13 | protected Runnable action(Editor editor) {
14 | return new Format(new IdeaPipeTableEditor(editor), formatOptions().preserveOuterState());
15 | }
16 | });
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/pipetableformatter/plugin/PipeTableSelectAction.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.plugin;
2 |
3 | import com.intellij.openapi.editor.Editor;
4 | import pipetableformatter.operation.Select;
5 |
6 | public class PipeTableSelectAction extends AbstractPipeTableFormatAction {
7 | public PipeTableSelectAction() {
8 | super(new PipeTableActionHandler() {
9 | @Override
10 | protected Runnable action(Editor editor) {
11 | return new Select(new IdeaPipeTableEditor(editor));
12 | }
13 | });
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/ColumnSplitterTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.hamcrest.CoreMatchers.is;
6 | import static org.junit.Assert.*;
7 |
8 | public class ColumnSplitterTest {
9 |
10 | @Test
11 | public void iteratesTroughColumns() {
12 | ColumnSplitter columnSplitter = new ColumnSplitter("|col1|col2|col3|", '|');
13 | assertThat(columnSplitter.next(), is("col1"));
14 | assertThat(columnSplitter.next(), is("col2"));
15 | assertThat(columnSplitter.next(), is("col3"));
16 | }
17 |
18 | @Test
19 | public void returnsTrueIfThereAreMoreColumns() {
20 | ColumnSplitter columnSplitter = new ColumnSplitter("|col1|col2|col3|", '|');
21 | assertThat(columnSplitter.hasNext(), is(true));
22 | }
23 |
24 | @Test
25 | public void returnsFalseIfThereAreNoMoreColumns() {
26 | ColumnSplitter columnSplitter = new ColumnSplitter("|col1|col2|col3|", '|');
27 | columnSplitter.next();
28 | columnSplitter.next();
29 | columnSplitter.next();
30 |
31 | assertThat(columnSplitter.hasNext(), is(false));
32 | }
33 |
34 | @Test
35 | public void returnsColumnStartIndex() {
36 | ColumnSplitter columnSplitter = new ColumnSplitter("|col1|col2|col3|", '|');
37 | columnSplitter.next();
38 | columnSplitter.next();
39 |
40 | assertThat(columnSplitter.currentColumnStartIndex(), is(6));
41 | }
42 |
43 | @Test
44 | public void returnsColumnEndIndex() {
45 | ColumnSplitter columnSplitter = new ColumnSplitter("|col1|col2|col3|", '|');
46 | columnSplitter.next();
47 | columnSplitter.next();
48 |
49 | assertThat(columnSplitter.currentColumnEndIndex(), is(10));
50 | }
51 |
52 | @Test
53 | public void incrementsColumnIndex() {
54 | ColumnSplitter columnSplitter = new ColumnSplitter("|col1|col2|col3|", '|');
55 | int index = 0;
56 | for (String value : columnSplitter) {
57 | assertThat(columnSplitter.currentColumnIndex(), is(index));
58 | index++;
59 | }
60 | }
61 |
62 | @Test
63 | public void includesLeadingSpaceInLineWhenDeterminesColumnStartIndex() {
64 | ColumnSplitter columnSplitter = new ColumnSplitter(" |col1|col2|col3|", '|');
65 | columnSplitter.next();
66 |
67 | assertThat(columnSplitter.currentColumnStartIndex(), is(5));
68 | }
69 |
70 | @Test
71 | public void returnsLeadingSpaces() {
72 | assertThat(new ColumnSplitter(" |val|val|", '|').getLeadingSpaces(), is(4));
73 | }
74 |
75 | @Test
76 | public void returnsPresenceLeadingPipe() {
77 | assertThat(new ColumnSplitter(" |val|val|", '|').hasLeadingPipe(), is(true));
78 | assertThat(new ColumnSplitter(" val|val|", '|').hasLeadingPipe(), is(false));
79 | }
80 |
81 | @Test
82 | public void returnsPresenceTrailingPipe() {
83 | assertThat(new ColumnSplitter(" |val|val|", '|').hasTrailingPipe(), is(true));
84 | assertThat(new ColumnSplitter(" |val|val", '|').hasTrailingPipe(), is(false));
85 | }
86 |
87 | }
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/LineSplitterTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.hamcrest.core.Is.is;
6 | import static org.junit.Assert.*;
7 |
8 | public class LineSplitterTest {
9 |
10 | @Test
11 | public void iteratesThrowLines() {
12 | LineSplitter lineSplitter = new LineSplitter("row1\nrow2\n");
13 | assertThat(lineSplitter.next(), is("row1"));
14 | assertThat(lineSplitter.next(), is("row2"));
15 | }
16 |
17 | @Test
18 | public void returnTrueIfThereAreMoreLines() {
19 | LineSplitter lineSplitter = new LineSplitter("row1\nrow2\n");
20 | assertThat(lineSplitter.hasNext(), is(true));
21 | }
22 |
23 | @Test
24 | public void returnFalseIfThereAreNoMoreLines() {
25 | LineSplitter lineSplitter = new LineSplitter("row1\nrow2\n");
26 | lineSplitter.next();
27 | lineSplitter.next();
28 |
29 | assertThat(lineSplitter.hasNext(), is(false));
30 | }
31 |
32 | @Test
33 | public void returnsStartLineIndex() {
34 | LineSplitter lineSplitter = new LineSplitter("row1\nrow2\nrow3\n");
35 | lineSplitter.next();
36 | lineSplitter.next();
37 |
38 | assertThat(lineSplitter.currentLineStartIndex(), is(5));
39 | }
40 |
41 | @Test
42 | public void returnsEndLineIndex() {
43 | LineSplitter lineSplitter = new LineSplitter("row1\nrow2\nrow3\n");
44 | lineSplitter.next();
45 | lineSplitter.next();
46 |
47 | assertThat(lineSplitter.currentLineEndIndex(), is(9));
48 | }
49 |
50 | @Test
51 | public void incrementsLineIndex() {
52 | LineSplitter lineSplitter = new LineSplitter("row1\nrow2\nrow3\n");
53 | int index = 0;
54 | for(String line : lineSplitter){
55 | assertThat(lineSplitter.currentLineIndex(), is(index));
56 | index++;
57 | }
58 | }
59 |
60 |
61 | }
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/PipeTableFormatterTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.hamcrest.CoreMatchers.is;
6 | import static org.junit.Assert.assertThat;
7 | import static pipetableformatter.FormatOptions.formatOptions;
8 | import static pipetableformatter.testsupport.PipeTableBuilder.aPipeTable;
9 | import static pipetableformatter.PipeTableFormatter.formatter;
10 |
11 | public class PipeTableFormatterTest {
12 |
13 | private static final String FORMATTED_TABLE =
14 | "" +
15 | "| Header 1 | Header 2 | Header 3 | Header 4 | Header 5 |\n" +
16 | "| val 11 | val 12 | val 13 | val 14 | val 15 |\n" +
17 | "| some value longer then previous | val 22 | val 33 | val34 | and last value with extra space |\n";
18 |
19 | private static final String FORMATTED_TABLE_WITH_COMMENT =
20 | "" +
21 | "| Header 1 | Header 2 | Header 3 | Header 4 | Header 5 |\n" +
22 | "|-- this is commented row that should be left commented | val 12 | val 13 | val 14 | this is commented row that should be left commented --|\n" +
23 | "| some value longer then previous | val 22 | val 33 | val34 | val35 |\n";
24 |
25 | @Test
26 | public void formatsTableDelimitingColumnsWithPipes() {
27 | PipeTable pipeTable = aPipeTable()
28 | .addRow("Header 1", "Header 2", "Header 3", "Header 4", "Header 5")
29 | .addRow("val 11", "val 12", "val 13", "val 14", "val 15")
30 | .addRow("some value longer then previous", "val 22", "val 33", "val34", "and last value with extra space")
31 | .build();
32 |
33 | String formattedText = formatter().format(pipeTable);
34 |
35 | assertThat(formattedText, is(FORMATTED_TABLE));
36 | }
37 |
38 | @Test
39 | public void preservesCommentedRow() {
40 | PipeTable pipeTable = aPipeTable()
41 | .addRow("Header 1", "Header 2", "Header 3", "Header 4", "Header 5")
42 | .addRow("this is commented row that should be left commented", "val 12", "val 13", "val 14", "this is commented row that should be left commented").commented()
43 | .addRow("some value longer then previous", "val 22", "val 33", "val34", "val35")
44 | .build();
45 |
46 | String formattedText = formatter().format(pipeTable);
47 |
48 | assertThat(formattedText, is(FORMATTED_TABLE_WITH_COMMENT));
49 | }
50 |
51 | @Test
52 | public void preservesIndentation() {
53 | PipeTable pipeTable = aPipeTable()
54 | .addRow("row1.val1", "row1.val2", "row1.val3").withIndentation(" ")
55 | .addRow("row2.val1", "row2.val2", "row2.val3").withIndentation(" ")
56 | .addRow("row3.val1", "row3.val2", "row3.val3").withIndentation(" ")
57 | .build();
58 |
59 | String formattedText = formatter().withOptions(formatOptions().preserveOuterState()).format(pipeTable);
60 |
61 | assertThat(formattedText, is("" +
62 | " | row1.val1 | row1.val2 | row1.val3 |\n" +
63 | " | row2.val1 | row2.val2 | row2.val3 |\n" +
64 | " | row3.val1 | row3.val2 | row3.val3 |\n"
65 | ));
66 | }
67 |
68 |
69 | @Test
70 | public void preservesAbsenceOfOuterPipes() {
71 | PipeTable pipeTable = aPipeTable()
72 | .addRow("row1.val1", "row1.val2", "row1.val3").withIndentation(" ").withoutLeadingPipe().withoutTrailingPipe()
73 | .addRow("row2.val1", "row2.val2", "row2.val3").withIndentation(" ").withoutLeadingPipe().withoutTrailingPipe()
74 | .addRow("row3.val1", "row3.val2", "row3.val3").withIndentation(" ").withoutLeadingPipe().withoutTrailingPipe()
75 | .build();
76 |
77 | String formattedText = formatter().withOptions(formatOptions().preserveOuterState()).format(pipeTable);
78 |
79 | assertThat(formattedText, is("" +
80 | " row1.val1 | row1.val2 | row1.val3\n" +
81 | " row2.val1 | row2.val2 | row2.val3\n" +
82 | " row3.val1 | row3.val2 | row3.val3\n"
83 | ));
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/PipeTableParserTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.hamcrest.CoreMatchers.is;
6 | import static org.junit.Assert.assertThat;
7 |
8 | public class PipeTableParserTest {
9 |
10 | private final static String TABLE =
11 | "" +
12 | " | Header 1 | Header 2 | Header 3 | Header 4 | Header 5 | \n" +
13 | " | val 11 | val 12 | val 13 | val 14 | val 15 | \n" +
14 | " | some value longer then previous | val 22 | val 33 | val34 | and last value with extra space | ";
15 |
16 |
17 | @Test
18 | public void convertsEachLineOfTextToRowOfTable() {
19 | PipeTable pipeTable = new PipeTableParser("row1\nrow2").parse();
20 | assertThat(pipeTable.getRowCount(), is(2));
21 | assertThat(pipeTable.getValue(0, 0), is("row1"));
22 | assertThat(pipeTable.getValue(1, 0), is("row2"));
23 | }
24 |
25 | @Test
26 | public void understandsWindowsLineDelimiter() {
27 | PipeTable pipeTable = new PipeTableParser("row1\r\nrow2").parse();
28 | assertThat(pipeTable.getRowCount(), is(2));
29 | assertThat(pipeTable.getValue(0, 0), is("row1"));
30 | assertThat(pipeTable.getValue(1, 0), is("row2"));
31 | }
32 |
33 | @Test
34 | public void splitsLineForColumnsByPipe() {
35 | PipeTable pipeTable = new PipeTableParser("|column1|column2|").parse();
36 | assertThat(pipeTable.getValue(0, 0), is("column1"));
37 | assertThat(pipeTable.getValue(0, 1), is("column2"));
38 | }
39 |
40 | @Test
41 | public void splitsLineForColumnsByTab() {
42 | PipeTable pipeTable = new PipeTableParser("column1\tcolumn2").parse();
43 | assertThat(pipeTable.getValue(0, 0), is("column1"));
44 | assertThat(pipeTable.getValue(0, 1), is("column2"));
45 | }
46 |
47 | @Test
48 | public void removesLeadingAndTrailingSpacesOfValues() {
49 | PipeTable pipeTable = new PipeTableParser("| column1 | column2 | column3 |").parse();
50 | assertThat(pipeTable.getValue(0, 0), is("column1"));
51 | assertThat(pipeTable.getValue(0, 1), is("column2"));
52 | assertThat(pipeTable.getValue(0, 2), is("column3"));
53 | }
54 |
55 | @Test
56 | public void extendsShorterRowsToMaxSizeWithEmptyValues() {
57 | PipeTable pipeTable = new PipeTableParser("|val11|val12|\n|val21|val22|val23|").parse();
58 | assertThat(pipeTable.getValue(0, 2), is(""));
59 | }
60 |
61 | @Test
62 | public void preservesLineEndSeparatorForEachLine() {
63 | PipeTable pipeTable = new PipeTableParser("row1\r\nrow2\nrow3").parse();
64 | assertThat(pipeTable.rows()[0].endOfLine(), is("\r\n"));
65 | assertThat(pipeTable.rows()[1].endOfLine(), is("\n"));
66 | assertThat(pipeTable.rows()[2].endOfLine(), is(""));
67 | }
68 |
69 | @Test
70 | public void splitsLineForColumnsByComma() {
71 | PipeTable pipeTable = new PipeTableParser(",column1,column2").parse();
72 | assertThat(pipeTable.getValue(0, 0), is(""));
73 | assertThat(pipeTable.getValue(0, 1), is("column1"));
74 | assertThat(pipeTable.getValue(0, 2), is("column2"));
75 | }
76 |
77 | @Test
78 | public void ignoresCommasInsideDoubleQuotes() {
79 | PipeTable pipeTable = new PipeTableParser(" \"col1val1,col1val2\",column2").parse();
80 | assertThat(pipeTable.getValue(0, 0), is("col1val1,col1val2"));
81 | assertThat(pipeTable.getValue(0, 1), is("column2"));
82 | }
83 |
84 | @Test
85 | public void ignoresPipeInsideDoubleQuotes() {
86 | PipeTable pipeTable = new PipeTableParser(" |\"col1val1|col1val2\"|column2|").parse();
87 | assertThat(pipeTable.getValue(0, 0), is("col1val1|col1val2"));
88 | assertThat(pipeTable.getValue(0, 1), is("column2"));
89 | }
90 |
91 | @Test
92 | public void treatsTwoDoubleQuotesInsideQuotesAsOne() {
93 | PipeTable pipeTable = new PipeTableParser(" |\"val1\"\"val2\"|column2|").parse();
94 | assertThat(pipeTable.getValue(0, 0), is("val1\"val2"));
95 | }
96 |
97 | @Test
98 | public void doesNotTreatCommaAsDelimiterInPipeDelimitedTable() {
99 | PipeTable pipeTable = new PipeTableParser("|value 1|value 2.1, value 2.2|").parse();
100 | assertThat(pipeTable.getColumnCount(), is(2));
101 | assertThat(pipeTable.getValue(0, 1), is("value 2.1, value 2.2"));
102 | }
103 |
104 | @Test
105 | public void doesNotTreatPipeAsDelimiterInCommaDelimitedTable() {
106 | PipeTable pipeTable = new PipeTableParser("value 1, value 2.1| value 2.2, value 3").parse();
107 | assertThat(pipeTable.getColumnCount(), is(3));
108 | assertThat(pipeTable.getValue(0, 1), is("value 2.1| value 2.2"));
109 | }
110 |
111 | @Test
112 | public void usesPipeAsPriorityDelimiter() {
113 | PipeTable pipeTable = new PipeTableParser("|{color:red, length:10, strength:2}|{color:green, length:2, strength:5}|").parse();
114 | assertThat(pipeTable.getColumnCount(), is(2));
115 | assertThat(pipeTable.getValue(0, 0), is("{color:red, length:10, strength:2}"));
116 | assertThat(pipeTable.getValue(0, 1), is("{color:green, length:2, strength:5}"));
117 | }
118 |
119 | @Test
120 | public void determinesRowWhereRowIsPlaced() {
121 | PipeTableParser pipeTableParser = new PipeTableParser(TABLE).detectingCellByPosition(167);
122 | PipeTable pipeTable = pipeTableParser.parse();
123 |
124 | assertThat(pipeTable.getSelectedRow(), is(1));
125 | }
126 |
127 | @Test
128 | public void determinesColumnWhereRowIsPlaced() {
129 | PipeTableParser pipeTableParser = new PipeTableParser(TABLE).detectingCellByPosition(167);
130 | PipeTable pipeTable = pipeTableParser.parse();
131 |
132 | assertThat(pipeTable.getSelectedColumn(), is(3));
133 | }
134 |
135 | @Test
136 | public void determinesColumnIfCaretPlacedRightBeforeDelimiter() {
137 | PipeTableParser pipeTableParser = new PipeTableParser(TABLE).detectingCellByPosition(159);
138 | PipeTable pipeTable = pipeTableParser.parse();
139 |
140 | assertThat(pipeTable.getSelectedColumn(), is(2));
141 | }
142 |
143 | @Test
144 | public void determinesRowIfCaretPlacedRightAfterLastDelimiter() {
145 | PipeTableParser pipeTableParser = new PipeTableParser(TABLE).detectingCellByPosition(103);
146 | PipeTable pipeTable = pipeTableParser.parse();
147 |
148 | assertThat(pipeTable.getSelectedRow(), is(0));
149 | }
150 |
151 | @Test
152 | public void interpretsAsExtraColumnWhenCaretPlacedRightAfterLastDelimiter() {
153 | PipeTableParser pipeTableParser = new PipeTableParser(TABLE).detectingCellByPosition(103);
154 | PipeTable pipeTable = pipeTableParser.parse();
155 |
156 | assertThat(pipeTable.getSelectedColumn(), is(5));
157 | }
158 |
159 | @Test
160 | public void interpretsAsExtraColumnWhenCaretPlacedAtTheEndOfLine() {
161 | PipeTableParser pipeTableParser = new PipeTableParser(TABLE).detectingCellByPosition(104);
162 | PipeTable pipeTable = pipeTableParser.parse();
163 |
164 | assertThat(pipeTable.getSelectedColumn(), is(5));
165 | }
166 |
167 | @Test
168 | public void interpretsAsFirstColumnIfCaretPlacedRightBeforeDelimiter() {
169 | PipeTableParser pipeTableParser = new PipeTableParser(TABLE).detectingCellByPosition(106);
170 | PipeTable pipeTable = pipeTableParser.parse();
171 |
172 | assertThat(pipeTable.getSelectedColumn(), is(0));
173 | }
174 |
175 | @Test
176 | public void interpretsAsFirstColumnIfCaretPlacedAtStartOfLine() {
177 | PipeTableParser pipeTableParser = new PipeTableParser(TABLE).detectingCellByPosition(105);
178 | PipeTable pipeTable = pipeTableParser.parse();
179 |
180 | assertThat(pipeTable.getSelectedColumn(), is(0));
181 | }
182 |
183 | @Test
184 | public void interpretsAsExtraColumnIfCaretPlacedAtEndOfLastLine() {
185 | PipeTableParser pipeTableParser = new PipeTableParser(TABLE).detectingCellByPosition(314);
186 | PipeTable pipeTable = pipeTableParser.parse();
187 |
188 | assertThat(pipeTable.getSelectedColumn(), is(5));
189 | }
190 |
191 | @Test
192 | public void detectsCommentedRow() {
193 | PipeTable pipeTable = new PipeTableParser("" +
194 | "|row1.col1|row1.col2|\n" +
195 | "|-- row2.col1|row2.col2--|\n" +
196 | "|row3.col1|row3.col2|")
197 | .parse();
198 |
199 | assertThat(pipeTable.isRowCommented(0), is(false));
200 | assertThat(pipeTable.isRowCommented(1), is(true));
201 | assertThat(pipeTable.getValue(1,0), is("row2.col1"));
202 | assertThat(pipeTable.getValue(1,1), is("row2.col2"));
203 | assertThat(pipeTable.isRowCommented(2), is(false));
204 |
205 | }
206 |
207 | @Test
208 | public void savesOuterStates() {
209 | PipeTable pipeTable = new PipeTableParser("" +
210 | " |row1.col1|row1.col2|\n" +
211 | " row2.col1|row2.col2|\n" +
212 | " |row3.col1|row3.col2 ")
213 | .parse();
214 |
215 | assertThat(pipeTable.rows()[1].getIndentation(), is(" "));
216 | assertThat(pipeTable.rows()[0].hasLeadingPipe(), is(true));
217 | assertThat(pipeTable.rows()[0].hasTrailingPipe(), is(true));
218 | assertThat(pipeTable.rows()[1].hasLeadingPipe(), is(false));
219 | assertThat(pipeTable.rows()[2].hasTrailingPipe(), is(false));
220 |
221 | }
222 |
223 | @Test
224 | public void detectsPresenceOfOuterPipeInCommentedRow() {
225 | PipeTable pipeTable = new PipeTableParser("|--row2.col1|row2.col2--|").parse();
226 |
227 | assertThat(pipeTable.rows()[0].hasLeadingPipe(), is(true));
228 | assertThat(pipeTable.rows()[0].hasTrailingPipe(), is(true));
229 |
230 | }
231 |
232 | }
233 |
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/PipeTableTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 |
6 | import static org.hamcrest.CoreMatchers.is;
7 | import static org.junit.Assert.*;
8 | import static pipetableformatter.testsupport.PipeTableBuilder.aPipeTable;
9 |
10 | public class PipeTableTest {
11 |
12 | private PipeTable pipeTable;
13 | private PipeTable expectedTable;
14 |
15 | @Before
16 | public void setUp() {
17 | pipeTable = aPipeTable()
18 | .addRow("row11", "row12", "row13")
19 | .addRow("row21", "row22", "row23")
20 | .build();
21 |
22 | expectedTable = aPipeTable()
23 | .addRow("row11", "", "row12", "row13")
24 | .addRow("row21", "", "row22", "row23")
25 | .build();
26 | }
27 |
28 | @Test
29 | public void addsColumnBefore() {
30 | pipeTable.addColumnBefore(1);
31 |
32 | assertThat(pipeTable.getColumnCount(), is(4));
33 |
34 | PipeTable.Row[] rows = pipeTable.rows();
35 | PipeTable.Row[] expectedRows = expectedTable.rows();
36 | for (int rowIndex = 0; rowIndex < rows.length; rowIndex++) {
37 | for (int cellIndex = 0; cellIndex < rows[rowIndex].size(); cellIndex++) {
38 | assertThat(rows[rowIndex].get(cellIndex), is(expectedRows[rowIndex].get(cellIndex)));
39 | }
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/TableDetectorTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.hamcrest.CoreMatchers.is;
6 | import static org.junit.Assert.assertThat;
7 | import static pipetableformatter.TableDetector.detectTableIn;
8 |
9 | public class TableDetectorTest {
10 |
11 | public static final String TEXT_WITH_TABLE_PIPE = "" +
12 | "this line not in table\n" +
13 | "\n" +
14 | "|header 1|header 2|header 3|\n" +
15 | "|value 11|value 12|value 13|\n" +
16 | "|value 21|value 22|value 33|\n";
17 |
18 | public static final String TEXT_WITH_TABLE_NO_LAST_EOL = "" +
19 | "this line not in table\n" +
20 | "\n" +
21 | "|header 1|header 2|header 3|\n" +
22 | "|value 11|value 12|value 13|\n" +
23 | "|value 21|value 22|value 33|";
24 |
25 | public static final String TEXT_WITH_TABLE_COMMA = "" +
26 | "this line not in table\n" +
27 | "\n" +
28 | "header 1,header 2,header 3\n" +
29 | "value 11,value 12,value 13\n" +
30 | "value 21,value 22,value 33\n";
31 |
32 | public static final String TEXT_WITH_TABLE_TAB = "" +
33 | "this line not in table\n" +
34 | "\n" +
35 | "header 1\theader 2\theader 3\n" +
36 | "value 11\tvalue 12\tvalue 13\n" +
37 | "value 21\tvalue 22\tvalue 33\n";
38 |
39 | public static final String TEXT_WITH_COMMA_INSIDE_QUOTES = "" +
40 | "header 1,header 2,header 3\n" +
41 | "value 11,\"val1,val2\",value 13\n";
42 |
43 | public static final String TEXT_WITH_PIPE_INSIDE_QUOTES = "" +
44 | "|header 1|header 2|header 3|\n" +
45 | "|value 11|\"val1|val2\"|value 13|\n";
46 |
47 | public static final String PIPE_TABLE_CONTAINS_VALUE_WITH_COMMA = "" +
48 | "|header 1|header 2|header 3|\n" +
49 | "|value 11|val1,val2|value 13|\n";
50 |
51 | public static final String TEXT_WITH_PIPES_AND_COMMAS = "" +
52 | "this, line, not, in table\n" +
53 | "|header, 1|header, 2|header, 3|\n" +
54 | "|value, 11|value, 12|value, 13|\n" +
55 | "|value, 21|value, 22|value, 33|\n" +
56 | "after, the, table";
57 |
58 | public static final int PIPE_TABLE_START_POS = 24;
59 | public static final int PIPE_TABLE_END_POS = 110;
60 | public static final int COMMA_TABLE_START_POS = 24;
61 | public static final int COMMA_TABLE_END_POS = 104;
62 | public static final int TAB_TABLE_START_POS = 24;
63 | public static final int TAB_TABLE_END_POS = 104;
64 |
65 | @Test
66 | public void detectsStartOfTheTableDelimitedWithPipe() {
67 |
68 | Range range = detectTableIn(TEXT_WITH_TABLE_PIPE).around(67);
69 |
70 | assertThat(range.getStart(), is(PIPE_TABLE_START_POS));
71 | }
72 |
73 | @Test
74 | public void detectsEndOfTheTableDelimitedWithPipe(){
75 | Range range = detectTableIn(TEXT_WITH_TABLE_PIPE).around(67);
76 |
77 | assertThat(range.getEnd(), is(PIPE_TABLE_END_POS));
78 | }
79 |
80 | @Test
81 | public void detectsStartOfTheTableDelimitedWithComma() {
82 |
83 | Range range = detectTableIn(TEXT_WITH_TABLE_COMMA).around(67);
84 |
85 | assertThat(range.getStart(), is(COMMA_TABLE_START_POS));
86 | }
87 |
88 | @Test
89 | public void detectsEndOfTheTableDelimitedWithComma(){
90 | Range range = detectTableIn(TEXT_WITH_TABLE_COMMA).around(67);
91 |
92 | assertThat(range.getEnd(), is(COMMA_TABLE_END_POS));
93 | }
94 |
95 | @Test
96 | public void ignoresNonPipeTablesWhenAppropriateOptionIsSpecified() {
97 | Range range = detectTableIn(TEXT_WITH_TABLE_COMMA).usingOnlyPipe().around(67);
98 |
99 | assertThat(range.isEmpty(), is(true));
100 | }
101 |
102 | @Test
103 | public void detectsStartOfTheTableDelimitedWithTab() {
104 |
105 | Range range = detectTableIn(TEXT_WITH_TABLE_TAB).around(67);
106 |
107 | assertThat(range.getStart(), is(TAB_TABLE_START_POS));
108 | }
109 |
110 | @Test
111 | public void detectsEndOfTheTableDelimitedWithTab(){
112 | Range range = detectTableIn(TEXT_WITH_TABLE_TAB).around(67);
113 |
114 | assertThat(range.getEnd(), is(TAB_TABLE_END_POS));
115 | }
116 |
117 | @Test
118 | public void ignoresCommasInsideQuotes() {
119 | Range range = detectTableIn(TEXT_WITH_COMMA_INSIDE_QUOTES).around(37);
120 |
121 | assertThat(range.getStart(), is(0));
122 | assertThat(range.getEnd(), is(TEXT_WITH_COMMA_INSIDE_QUOTES.length()-1));
123 | }
124 |
125 | @Test
126 | public void ignoresPipeInsideQuotes() {
127 | Range range = detectTableIn(TEXT_WITH_PIPE_INSIDE_QUOTES).around(37);
128 |
129 | assertThat(range.getStart(), is(0));
130 | assertThat(range.getEnd(), is(TEXT_WITH_PIPE_INSIDE_QUOTES.length()-1));
131 | }
132 |
133 | @Test
134 | public void canDetectTableIfNoLastEOL(){
135 | Range range = detectTableIn(TEXT_WITH_TABLE_NO_LAST_EOL).around(67);
136 |
137 | assertThat(range.getEnd(), is(TEXT_WITH_TABLE_NO_LAST_EOL.length()));
138 | }
139 |
140 | @Test
141 | public void canDetectTableIfNoLastEOLAndCaretAtLastLine(){
142 | Range range = detectTableIn(TEXT_WITH_TABLE_NO_LAST_EOL).around(98);
143 |
144 | assertThat(range.getEnd(), is(TEXT_WITH_TABLE_NO_LAST_EOL.length()));
145 | }
146 |
147 | @Test
148 | public void ignoresCommaInsidePipeTable() {
149 | Range range = detectTableIn(PIPE_TABLE_CONTAINS_VALUE_WITH_COMMA).around(37);
150 |
151 | assertThat(range.getStart(), is(0));
152 | assertThat(range.getEnd(), is(PIPE_TABLE_CONTAINS_VALUE_WITH_COMMA.length()-1));
153 | }
154 |
155 | @Test
156 | public void detectsTableWhenCaretPlacedAtStartOfALine() {
157 | Range range = detectTableIn(TEXT_WITH_TABLE_PIPE).around(53);
158 |
159 | assertThat(range.getStart(), is(PIPE_TABLE_START_POS));
160 | }
161 |
162 | @Test
163 | public void detectsTableWhenCaretPlacedAtEndOfALine() {
164 | Range range = detectTableIn(TEXT_WITH_TABLE_PIPE).around(52);
165 |
166 | assertThat(range.getStart(), is(PIPE_TABLE_START_POS));
167 | }
168 |
169 | @Test
170 | public void usesPipesAsPrimaryDelimiter() {
171 | Range range = detectTableIn(TEXT_WITH_PIPES_AND_COMMAS).around(53);
172 |
173 | assertThat(range.getStart(), is(26));
174 | assertThat(range.getEnd(), is(121));
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/operation/AddColumnBeforeOperationTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 | import pipetableformatter.Range;
6 |
7 | import static org.mockito.Mockito.*;
8 |
9 | public class AddColumnBeforeOperationTest {
10 |
11 | private static final String NOT_FORMATTED_TABLE = "" +
12 | "|Country|Currency|Population|Area|\n" +
13 | "|United States of America|US dollar|316 million|9.8 million sq km|\n" +
14 | "|Canada|Canadian dollar|34.7 million|9.9 million sq km|\n" +
15 | "|United Kingdom|pound sterling|62.8 million|242,514 sq km|\n" +
16 | "|Republic of Poland|zloty|38.3 million|312,685 sq km|";
17 |
18 |
19 | protected static final String FORMATTED_TABLE_WITH_NEW_COLUMN = "" +
20 | "| Country | | Currency | Population | Area |\n" +
21 | "| United States of America | | US dollar | 316 million | 9.8 million sq km |\n" +
22 | "| Canada | | Canadian dollar | 34.7 million | 9.9 million sq km |\n" +
23 | "| United Kingdom | | pound sterling | 62.8 million | 242,514 sq km |\n" +
24 | "| Republic of Poland | | zloty | 38.3 million | 312,685 sq km |";
25 |
26 | PipeTableEditor utility;
27 |
28 | @Before
29 | public void before() {
30 | utility = mock(PipeTableEditor.class);
31 | when(utility.getSelectedText()).thenReturn(new TableText(NOT_FORMATTED_TABLE, new Range(1, 200)));
32 | when(utility.getCaretPosition()).thenReturn(65);
33 | }
34 |
35 |
36 | @Test
37 | public void addsColumn() {
38 | new AddColumnBefore(utility).run();
39 |
40 | verify(utility).replaceText(FORMATTED_TABLE_WITH_NEW_COLUMN, new Range(1, 200));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/operation/FormatAllTablesOperationTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 | import pipetableformatter.Range;
6 |
7 | import static org.mockito.Mockito.*;
8 |
9 | public class FormatAllTablesOperationTest {
10 |
11 | private static final String TEXT_WITH_A_FEW_NOT_FORMATTED_TABLES = "" +
12 | "Story: Countries\n" +
13 | "\n" +
14 | "Scenario: Country currency\n" +
15 | "When country is \n" +
16 | "Then currency is \n" +
17 | "\n" +
18 | "Examples:\n" +
19 | "|Country|Currency|\n" +
20 | "|United States of America|US dollar|\n" +
21 | "|Canada|Canadian dollar|\n" +
22 | "|United Kingdom|pound sterling|\n" +
23 | "|Republic of Poland|zloty|\n" +
24 | "\n" +
25 | "\n" +
26 | "Scenario: Country Population\n" +
27 | "When country is , see examples\n" +
28 | "Then currency is , see examples\n" +
29 | "\n" +
30 | "Examples:\n" +
31 | "Country|Population\n" +
32 | "United States of America|316 million\n" +
33 | "Canada|34.7 million\n" +
34 | "United Kingdom|62.8 million\n" +
35 | "Republic of Poland|38.3 million\n" +
36 | "\n" +
37 | "\n" +
38 | "Scenario: Country Area\n" +
39 | "When country is \n" +
40 | "Then currency is \n" +
41 | "\n" +
42 | "Examples:\n" +
43 | "|Country|Area|\n" +
44 | "|United States of America|9.8 million sq km|\n" +
45 | "|Canada|9.9 million sq km|\n" +
46 | "|United Kingdom|242,514 sq km|\n" +
47 | "|Republic of Poland|312,685 sq km|\n";
48 |
49 | private static final String FORMATTED_TABLE_1 = "" +
50 | "| Country | Currency |\n" +
51 | "| United States of America | US dollar |\n" +
52 | "| Canada | Canadian dollar |\n" +
53 | "| United Kingdom | pound sterling |\n" +
54 | "| Republic of Poland | zloty |";
55 |
56 | private static final String FORMATTED_TABLE_2 = "" +
57 | "| Country | Population |\n" +
58 | "| United States of America | 316 million |\n" +
59 | "| Canada | 34.7 million |\n" +
60 | "| United Kingdom | 62.8 million |\n" +
61 | "| Republic of Poland | 38.3 million |";
62 |
63 | private static final String FORMATTED_TABLE_3 = "" +
64 | "| Country | Area |\n" +
65 | "| United States of America | 9.8 million sq km |\n" +
66 | "| Canada | 9.9 million sq km |\n" +
67 | "| United Kingdom | 242,514 sq km |\n" +
68 | "| Republic of Poland | 312,685 sq km |";
69 |
70 | private static final String TEXT_WITH_SINGLE_LINE_WITH_DELIMITERS = "" +
71 | "Scenario: Country strength\n" +
72 | "\n" +
73 | "When Country has raising GDP, export over import\n" +
74 | "Then Country is prosperous\n" +
75 | "\n";
76 |
77 | PipeTableEditor editor;
78 |
79 | @Before
80 | public void before() {
81 | editor = mock(PipeTableEditor.class);
82 | }
83 |
84 | @Test
85 | public void formatsAllTablesInTheText() {
86 | when(editor.getText()).thenReturn(TEXT_WITH_A_FEW_NOT_FORMATTED_TABLES);
87 |
88 | new FormatAllTables(editor).run();
89 |
90 | verify(editor, times(3)).replaceText(anyString(), any(Range.class));
91 | verify(editor).replaceText(FORMATTED_TABLE_1, new Range(110, 256));
92 | verify(editor).replaceText(FORMATTED_TABLE_2, new Range(383, 518));
93 | verify(editor).replaceText(FORMATTED_TABLE_3, new Range(605, 757));
94 | }
95 |
96 | @Test
97 | public void ignoresSingleLineWithDelimiters() {
98 | when(editor.getText()).thenReturn(TEXT_WITH_SINGLE_LINE_WITH_DELIMITERS);
99 |
100 | new FormatAllTables(editor).run();
101 |
102 | verify(editor, times(0)).replaceText(anyString(), any(Range.class));
103 | }
104 |
105 | }
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/operation/FormatOperationTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 | import pipetableformatter.Range;
6 |
7 | import static org.mockito.Mockito.*;
8 | import static pipetableformatter.FormatOptions.formatOptions;
9 |
10 | public class FormatOperationTest {
11 |
12 | private static final String TEXT_WITH_NOT_FORMATTED_TABLE = "" +
13 | "Story: Countries\n" +
14 | "\n" +
15 | "Scenario: Country currency\n" +
16 | "When country is \n" +
17 | "Then currency is \n" +
18 | "\n" +
19 | "Examples:\n" +
20 | "|Country|Currency|Population|Area|\n" +
21 | "|United States of America|US dollar|316 million|9.8 million sq km|\n" +
22 | "|Canada|Canadian dollar|34.7 million|9.9 million sq km|\n" +
23 | "|United Kingdom|pound sterling|62.8 million|242,514 sq km|\n" +
24 | "|Republic of Poland|zloty|38.3 million|312,685 sq km|";
25 |
26 | private static final String NOT_FORMATTED_TABLE = "" +
27 | "|Country|Currency|Population|Area|\n" +
28 | "|United States of America|US dollar|316 million|9.8 million sq km|\n" +
29 | "|Canada|Canadian dollar|34.7 million|9.9 million sq km|\n" +
30 | "|United Kingdom|pound sterling|62.8 million|242,514 sq km|\n" +
31 | "|Republic of Poland|zloty|38.3 million|312,685 sq km|";
32 |
33 | private static final String NOT_FORMATTED_TABLE_WITHOUT_OUTER_PIPES = "" +
34 | "Country|Currency|Population|Area\n" +
35 | "United States of America|US dollar|316 million|9.8 million sq km\n" +
36 | "Canada|Canadian dollar|34.7 million|9.9 million sq km\n" +
37 | "United Kingdom|pound sterling|62.8 million|242,514 sq km\n" +
38 | "Republic of Poland|zloty|38.3 million|312,685 sq km";
39 |
40 | protected static final String FORMATTED_TABLE = "" +
41 | "| Country | Currency | Population | Area |\n" +
42 | "| United States of America | US dollar | 316 million | 9.8 million sq km |\n" +
43 | "| Canada | Canadian dollar | 34.7 million | 9.9 million sq km |\n" +
44 | "| United Kingdom | pound sterling | 62.8 million | 242,514 sq km |\n" +
45 | "| Republic of Poland | zloty | 38.3 million | 312,685 sq km |";
46 |
47 |
48 | private static final String NOT_FORMATTED_CSV_TABLE = "" +
49 | "Header 1,Header 2, Header 3,Header 4 ,Header 5\n" +
50 | "val 11, val 12,val 13, val 14,val 15\n" +
51 | "some value longer then previous, val 22,val 33,val34,and last value with extra space \n";
52 |
53 | private static final String FORMATTED_CSV_TABLE = "" +
54 | "| Header 1 | Header 2 | Header 3 | Header 4 | Header 5 |\n" +
55 | "| val 11 | val 12 | val 13 | val 14 | val 15 |\n" +
56 | "| some value longer then previous | val 22 | val 33 | val34 | and last value with extra space |\n";
57 |
58 | protected static final String FORMATTED_TABLE_WITHOUT_OUTER_PIPES = "" +
59 | "Country | Currency | Population | Area \n" +
60 | "United States of America | US dollar | 316 million | 9.8 million sq km\n" +
61 | "Canada | Canadian dollar | 34.7 million | 9.9 million sq km\n" +
62 | "United Kingdom | pound sterling | 62.8 million | 242,514 sq km \n" +
63 | "Republic of Poland | zloty | 38.3 million | 312,685 sq km ";
64 |
65 |
66 | PipeTableEditor utility;
67 |
68 | @Before
69 | public void before() {
70 | utility = mock(PipeTableEditor.class);
71 | }
72 |
73 | @Test
74 | public void formatsSelectedTable() {
75 | when(utility.getSelectedText()).thenReturn(new TableText(NOT_FORMATTED_TABLE, new Range(110, 380)));
76 |
77 | new Format(utility).run();
78 |
79 | verify(utility).replaceText(FORMATTED_TABLE, new Range(110, 380));
80 | }
81 |
82 | @Test
83 | public void findsAndFormatsTable() {
84 | when(utility.getSelectedText()).thenReturn(new TableText(null, new Range(0, 0)));
85 | when(utility.getText()).thenReturn(TEXT_WITH_NOT_FORMATTED_TABLE);
86 | when(utility.getCaretPosition()).thenReturn(229);
87 |
88 | new Format(utility).run();
89 |
90 | verify(utility).replaceText(FORMATTED_TABLE, new Range(110, 380));
91 | }
92 |
93 | @Test
94 | public void formatsCsvTableAndReplaceCommaWithPipe() {
95 | when(utility.getSelectedText()).thenReturn(new TableText(NOT_FORMATTED_CSV_TABLE, new Range(110, 380)));
96 |
97 | new Format(utility).run();
98 |
99 | verify(utility).replaceText(FORMATTED_CSV_TABLE, new Range(110, 380));
100 | }
101 |
102 | @Test
103 | public void formatsTableWithoutOuterPipes() {
104 | when(utility.getSelectedText()).thenReturn(new TableText(NOT_FORMATTED_TABLE_WITHOUT_OUTER_PIPES, new Range(110, 380)));
105 |
106 | new Format(utility, formatOptions().preserveOuterState()).run();
107 |
108 | verify(utility).replaceText(FORMATTED_TABLE_WITHOUT_OUTER_PIPES, new Range(110, 380));
109 | }
110 |
111 | }
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/operation/SelectOperationTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.operation;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 | import pipetableformatter.Range;
6 |
7 | import static org.mockito.Mockito.*;
8 |
9 | public class SelectOperationTest {
10 |
11 | private static final String TEXT_WITH_NOT_FORMATTED_TABLE = "" +
12 | "Story: Countries\n" +
13 | "\n" +
14 | "Scenario: Country currency\n" +
15 | "When country is \n" +
16 | "Then currency is \n" +
17 | "\n" +
18 | "Examples:\n" +
19 | "|Country|Currency|Population|Area|\n" +
20 | "|United States of America|US dollar|316 million|9.8 million sq km|\n" +
21 | "|Canada|Canadian dollar|34.7 million|9.9 million sq km|\n" +
22 | "|United Kingdom|pound sterling|62.8 million|242,514 sq km|\n" +
23 | "|Republic of Poland|zloty|38.3 million|312,685 sq km|";
24 |
25 | PipeTableEditor utility;
26 |
27 | @Before
28 | public void before() {
29 | utility = mock(PipeTableEditor.class);
30 | }
31 |
32 | @Test
33 | public void selectsTable() {
34 | when(utility.getSelectedText()).thenReturn(new TableText(null, new Range(0, 0)));
35 | when(utility.getText()).thenReturn(TEXT_WITH_NOT_FORMATTED_TABLE);
36 | when(utility.getCaretPosition()).thenReturn(229);
37 |
38 | new Select(utility).run();
39 |
40 | verify(utility).setSelection(new Range(110, 380));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/plugin/PipeTableFormatterFunctionalTest.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.plugin;
2 |
3 | import com.intellij.openapi.editor.SelectionModel;
4 | import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
5 | import com.intellij.testFramework.fixtures.*;
6 | import org.jetbrains.annotations.NotNull;
7 | import org.junit.After;
8 | import org.junit.Before;
9 | import org.junit.Test;
10 |
11 | import static org.hamcrest.CoreMatchers.is;
12 | import static org.junit.Assert.assertThat;
13 | import static pipetableformatter.testsupport.Utils.loadFile;
14 |
15 | public class PipeTableFormatterFunctionalTest {
16 |
17 | private static final String TEXT_WITH_NOT_FORMATTED_TABLE = loadFile("input/text-with-not-formatted-table.txt");
18 | private static final String TEXT_WITH_NOT_FORMATTED_TABLE_WITH_COMMENT = loadFile("input/text-with-not-formatted-table-with-comments.txt");
19 | private static final String TEXT_WITH_A_FEW_NOT_FORMATTED_TABLE = loadFile("input/text-with-a-few-not-formatted-table.txt");
20 | private static final String TEXT_WITH_A_PIPE_TABLE_WITH_A_LOT_OF_COMMAS = loadFile("input/text-with-a-pipe-table-with-a-lot-commas.txt");
21 | private static final String TEXT_WITH_NOT_FORMATTED_TABLE_WITH_INDENTATION_WITHOUT_OUTER_PIPES = loadFile("input/text-with-not-formatted-table-with-indentation-without-outer-pipes.txt");
22 |
23 | private static final String TEXT_WITH_FORMATTED_TABLE = loadFile("expected/text-with-formatted-table.txt");
24 | private static final String TEXT_WITH_FORMATTED_TABLE_WITH_COMMENT = loadFile("expected/text-with-formatted-table-with-comment.txt");
25 | private static final String TEXT_WITH_FORMATTED_TABLE_AND_NEW_COLUMN = loadFile("expected/text-with-formatted-table-and-new-column.txt");
26 | private static final String TEXT_WITH_FORMATTED_TABLE_WITHOUT_OUTER_PIPES = loadFile("expected/text-with-formatted-table-without-outer-pipes.txt");
27 | private static final String TEXT_WITH_ALL_FORMATTED_TABLES = loadFile("expected/text-with-all-formatted-table.txt");
28 | private static final String TEXT_WITH_A_FORMATTED_PIPE_TABLE_WITH_A_LOT_OF_COMMAS = loadFile("expected/text-with-a-formatted-pipe-table-with-a-lot-commas.txt");
29 | private static final String TEXT_WITH_FORMATTED_TABLE_WITH_INDENTATION_WITHOUT_OUTER_PIPES = loadFile("expected/text-with-formatted-table-with-indentation-without-outer-pipes.txt");
30 |
31 | private CodeInsightTestFixture myFixture;
32 |
33 | @Before
34 | public void before() throws Exception {
35 | final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory();
36 | final TestFixtureBuilder testFixtureBuilder = fixtureFactory.createFixtureBuilder("PipeTableFormatter");
37 | myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(testFixtureBuilder.getFixture());
38 | final JavaModuleFixtureBuilder builder = testFixtureBuilder.addModule(JavaModuleFixtureBuilder.class);
39 |
40 | builder.addContentRoot(myFixture.getTempDirPath()).addSourceRoot("");
41 | builder.setMockJdkLevel(JavaModuleFixtureBuilder.MockJdkLevel.jdk15);
42 |
43 | myFixture.setUp();
44 | }
45 |
46 | @After
47 | public void after() throws Exception {
48 | myFixture.tearDown();
49 | }
50 |
51 | @Test
52 | public void formatsTableAroundCaret() throws Exception {
53 | myFixture.configureByText("test.story", TEXT_WITH_NOT_FORMATTED_TABLE);
54 |
55 | myFixture.performEditorAction("PipeTableFormatter.Format");
56 |
57 | assertThat(textAfterActionApplied(), is(TEXT_WITH_FORMATTED_TABLE));
58 | }
59 |
60 | @Test
61 | public void formatsTableAroundCaretWithComments() throws Exception {
62 | myFixture.configureByText("test.story", TEXT_WITH_NOT_FORMATTED_TABLE_WITH_COMMENT);
63 |
64 | myFixture.performEditorAction("PipeTableFormatter.Format");
65 |
66 | assertThat(textAfterActionApplied(), is(TEXT_WITH_FORMATTED_TABLE_WITH_COMMENT));
67 | }
68 |
69 |
70 | @Test
71 | public void formatsPipeTableIgnoringCommas() {
72 | myFixture.configureByText("test.story", TEXT_WITH_A_PIPE_TABLE_WITH_A_LOT_OF_COMMAS);
73 |
74 | myFixture.performEditorAction("PipeTableFormatter.Format");
75 |
76 | assertThat(textAfterActionApplied(), is(TEXT_WITH_A_FORMATTED_PIPE_TABLE_WITH_A_LOT_OF_COMMAS));
77 | }
78 |
79 | @Test
80 | public void selectsTableAroundCaret() throws Exception {
81 | myFixture.configureByText("test.story", TEXT_WITH_NOT_FORMATTED_TABLE);
82 |
83 | myFixture.performEditorAction("PipeTableFormatter.SelectTable");
84 |
85 | SelectionModel selection = myFixture.getEditor().getSelectionModel();
86 | assertThat(selection.getSelectionStart(), is(110));
87 | assertThat(selection.getSelectionEnd(), is(380));
88 | }
89 |
90 | @Test
91 | public void addsColumn() {
92 | myFixture.configureByText("test.story", TEXT_WITH_NOT_FORMATTED_TABLE);
93 |
94 | myFixture.performEditorAction("PipeTableFormatter.AddColumnBefore");
95 |
96 | assertThat(textAfterActionApplied(), is(TEXT_WITH_FORMATTED_TABLE_AND_NEW_COLUMN));
97 | }
98 |
99 | @Test
100 | public void formatsTablePreservingOuterStates() throws Exception {
101 | myFixture.configureByText("test.story", TEXT_WITH_NOT_FORMATTED_TABLE_WITH_INDENTATION_WITHOUT_OUTER_PIPES);
102 |
103 | myFixture.performEditorAction("PipeTableFormatter.FormatPreservingOuterState");
104 |
105 | assertThat(textAfterActionApplied(), is(TEXT_WITH_FORMATTED_TABLE_WITH_INDENTATION_WITHOUT_OUTER_PIPES));
106 | }
107 |
108 | @Test
109 | public void formatsAllTablesInEditor() throws Exception {
110 | myFixture.configureByText("test.story", TEXT_WITH_A_FEW_NOT_FORMATTED_TABLE);
111 |
112 | myFixture.performEditorAction("PipeTableFormatter.FormatAllTables");
113 |
114 | assertThat(textAfterActionApplied(), is(TEXT_WITH_ALL_FORMATTED_TABLES));
115 | }
116 |
117 | @NotNull
118 | private String textAfterActionApplied() {
119 | return myFixture.getEditor().getDocument().getText();
120 | }
121 | }
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/testsupport/PipeTableBuilder.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.testsupport;
2 |
3 | import com.sun.jna.platform.win32.WinBase;
4 | import pipetableformatter.PipeTable;
5 | import pipetableformatter.PipeTable.Row;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | public class PipeTableBuilder {
11 |
12 |
13 | private List rows = new ArrayList();
14 |
15 | public static PipeTableBuilder aPipeTable() {
16 | return new PipeTableBuilder();
17 | }
18 |
19 | public RowBuilder addRow(String... values) {
20 | Row row = row(values);
21 | rows.add(row);
22 | return new RowBuilder(row);
23 | }
24 |
25 | public PipeTable build() {
26 | return new PipeTable(rows);
27 | }
28 |
29 | private Row row(String... values) {
30 | List cellList = new ArrayList();
31 | for (String cell : values) {
32 | cellList.add(new PipeTable.Cell(cell));
33 | }
34 | Row row = new Row(cellList, "\n");
35 | return row;
36 | }
37 |
38 | public class RowBuilder {
39 | private Row row;
40 |
41 | private RowBuilder(Row row) {
42 | this.row = row;
43 | row.setIndentation("");
44 | row.setLeadingPipe(true);
45 | row.setTrailingPipe(true);
46 | }
47 |
48 | public RowBuilder commented() {
49 | row.setCommented(true);
50 | return this;
51 | }
52 |
53 | public RowBuilder withIndentation(String indentation) {
54 | row.setIndentation(indentation);
55 | return this;
56 | }
57 |
58 | public RowBuilder withoutLeadingPipe() {
59 | row.setLeadingPipe(false);
60 | return this;
61 | }
62 |
63 | public RowBuilder withoutTrailingPipe() {
64 | row.setTrailingPipe(false);
65 | return this;
66 | }
67 |
68 | public RowBuilder addRow(String... values) {
69 | return PipeTableBuilder.this.addRow(values);
70 | }
71 |
72 | public PipeTable build() {
73 | return PipeTableBuilder.this.build();
74 | }
75 |
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/test/java/pipetableformatter/testsupport/Utils.java:
--------------------------------------------------------------------------------
1 | package pipetableformatter.testsupport;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.nio.charset.Charset;
6 |
7 | public class Utils {
8 |
9 | public static String loadFile(String fileName) {
10 | InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName);
11 |
12 | StringBuilder stringBuilder = new StringBuilder();
13 | try {
14 | byte[] chunk = new byte[512];
15 | for (int count = inputStream.read(chunk); count >= 0; count = inputStream.read(chunk)) {
16 | stringBuilder.append(new String(chunk, 0, count, Charset.defaultCharset()));
17 | }
18 | } catch (IOException e) {
19 | throw new RuntimeException(e);
20 | } finally {
21 | try {
22 | inputStream.close();
23 | } catch (IOException e) {
24 | throw new RuntimeException(e);
25 | }
26 | }
27 |
28 | return stringBuilder.toString();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/test/resources/expected/text-with-a-formatted-pipe-table-with-a-lot-commas.txt:
--------------------------------------------------------------------------------
1 | | header1 | header2 |
2 | | value1 | [{a:1, b:1}, {a:1, b:1}, {a:1, b:1}] |
3 | | value2 | [{a:2, b:2}, {a:2, b:2}, {a:2, b:2}] |
4 | a,s,d,f,g,h
--------------------------------------------------------------------------------
/src/test/resources/expected/text-with-all-formatted-table.txt:
--------------------------------------------------------------------------------
1 | Story: Countries, currencies, etc
2 |
3 | Scenario: Country currency
4 | When country is
5 | Then currency is
6 |
7 | Examples:
8 | | Country | Currency |
9 | | United States of America | US dollar |
10 | | Canada | Canadian dollar |
11 | | United Kingdom | pound sterling |
12 | | Republic of Poland | zloty |
13 |
14 |
15 | Scenario: Country Population
16 | When country is , see examples
17 | Then currency is , see examples
18 |
19 | Examples:
20 | | Country | Population |
21 | | United States of America | 316 million |
22 | | Canada | 34.7 million |
23 | | United Kingdom | 62.8 million |
24 | | Republic of Poland | 38.3 million |
25 |
26 |
27 | Scenario: Country Area
28 | When country is
29 | Then currency is
30 |
31 | Examples:
32 | | Country | Area |
33 | | United States of America | 9.8 million sq km |
34 | | Canada | 9.9 million sq km |
35 | | United Kingdom | 242,514 sq km |
36 | | Republic of Poland | 312,685 sq km |
--------------------------------------------------------------------------------
/src/test/resources/expected/text-with-formatted-table-and-new-column.txt:
--------------------------------------------------------------------------------
1 | Story: Countries
2 |
3 | Scenario: Country currency
4 | When country is
5 | Then currency is
6 |
7 | Examples:
8 | | Country | | Currency | Population | Area |
9 | | United States of America | | US dollar | 316 million | 9.8 million sq km |
10 | | Canada | | Canadian dollar | 34.7 million | 9.9 million sq km |
11 | | United Kingdom | | pound sterling | 62.8 million | 242,514 sq km |
12 | | Republic of Poland | | zloty | 38.3 million | 312,685 sq km |
--------------------------------------------------------------------------------
/src/test/resources/expected/text-with-formatted-table-with-comment.txt:
--------------------------------------------------------------------------------
1 | Story: Countries
2 |
3 | Scenario: Country currency
4 | When country is
5 | Then currency is
6 |
7 | Examples:
8 | | Country | Currency | Population | Area |
9 | |-- comment | | | --|
10 | | United States of America | US dollar | 316 million | 9.8 million sq km |
11 | | Canada | Canadian dollar | 34.7 million | 9.9 million sq km |
12 | | United Kingdom | pound sterling | 62.8 million | 242,514 sq km |
13 | | Republic of Poland | zloty | 38.3 million | 312,685 sq km |
--------------------------------------------------------------------------------
/src/test/resources/expected/text-with-formatted-table-with-indentation-without-outer-pipes.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 | table:
4 | Country | Currency | Population | Area
5 | United States of America | US dollar | 316 million | 9.8 million sq km
6 | Canada | Canadian dollar | 34.7 million | 9.9 million sq km
7 | United Kingdom | pound sterling | 62.8 million | 242,514 sq km
8 | Republic of Poland | zloty | 38.3 million | 312,685 sq km
--------------------------------------------------------------------------------
/src/test/resources/expected/text-with-formatted-table-without-outer-pipes.txt:
--------------------------------------------------------------------------------
1 | Story: Countries
2 |
3 | Scenario: Country currency
4 | When country is
5 | Then currency is
6 |
7 | Examples:
8 | Country | Currency | Population | Area
9 | United States of America | US dollar | 316 million | 9.8 million sq km
10 | Canada | Canadian dollar | 34.7 million | 9.9 million sq km
11 | United Kingdom | pound sterling | 62.8 million | 242,514 sq km
12 | Republic of Poland | zloty | 38.3 million | 312,685 sq km
--------------------------------------------------------------------------------
/src/test/resources/expected/text-with-formatted-table.txt:
--------------------------------------------------------------------------------
1 | Story: Countries
2 |
3 | Scenario: Country currency
4 | When country is
5 | Then currency is
6 |
7 | Examples:
8 | | Country | Currency | Population | Area |
9 | | United States of America | US dollar | 316 million | 9.8 million sq km |
10 | | Canada | Canadian dollar | 34.7 million | 9.9 million sq km |
11 | | United Kingdom | pound sterling | 62.8 million | 242,514 sq km |
12 | | Republic of Poland | zloty | 38.3 million | 312,685 sq km |
--------------------------------------------------------------------------------
/src/test/resources/input/text-with-a-few-not-formatted-table.txt:
--------------------------------------------------------------------------------
1 | Story: Countries, currencies, etc
2 |
3 | Scenario: Country currency
4 | When country is
5 | Then currency is
6 |
7 | Examples:
8 | |Country|Currency|
9 | |United States of America|US dollar|
10 | |Canada|Canadian dollar|
11 | |United Kingdom|pound sterling|
12 | |Republic of Poland|zloty|
13 |
14 |
15 | Scenario: Country Population
16 | When country is , see examples
17 | Then currency is , see examples
18 |
19 | Examples:
20 | |Country|Population|
21 | |United States of America|316 million|
22 | |Canada|34.7 million|
23 | |United Kingdom|62.8 million|
24 | |Republic of Poland|38.3 million|
25 |
26 |
27 | Scenario: Country Area
28 | When country is
29 | Then currency is
30 |
31 | Examples:
32 | |Country|Area|
33 | |United States of America|9.8 million sq km|
34 | |Canada|9.9 million sq km|
35 | |United Kingdom|242,514 sq km|
36 | |Republic of Poland|312,685 sq km|
--------------------------------------------------------------------------------
/src/test/resources/input/text-with-a-pipe-table-with-a-lot-commas.txt:
--------------------------------------------------------------------------------
1 | |header1|header2|
2 | |value1|[{a:1, b:1}, {a:1, b:1}, {a:1, b:1}]|
3 | |value2|[{a:2, b:2}, {a:2, b:2}, {a:2, b:2}]|
4 | a,s,d,f,g,h
--------------------------------------------------------------------------------
/src/test/resources/input/text-with-not-formatted-table-with-comments.txt:
--------------------------------------------------------------------------------
1 | Story: Countries
2 |
3 | Scenario: Country currency
4 | When country is
5 | Then currency is
6 |
7 | Examples:
8 | |Country|Currency|Population|Area|
9 | |-- comment | | | --|
10 | |United States of America|US dollar|316 million|9.8 million sq km|
11 | |Canada|Canadian dollar|34.7 million|9.9 million sq km|
12 | |United Kingdom|pound sterling|62.8 million|242,514 sq km|
13 | |Republic of Poland|zloty|38.3 million|312,685 sq km|
--------------------------------------------------------------------------------
/src/test/resources/input/text-with-not-formatted-table-with-indentation-without-outer-pipes.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 | table:
4 | Country|Currency|Population|Area
5 | United States of America|US dollar|316 million|9.8 million sq km
6 | Canada|Canadian dollar|34.7 million|9.9 million sq km
7 | United Kingdom|pound sterling|62.8 million|242,514 sq km
8 | Republic of Poland|zloty|38.3 million|312,685 sq km
--------------------------------------------------------------------------------
/src/test/resources/input/text-with-not-formatted-table.txt:
--------------------------------------------------------------------------------
1 | Story: Countries
2 |
3 | Scenario: Country currency
4 | When country is
5 | Then currency is
6 |
7 | Examples:
8 | |Country|Currency|Population|Area|
9 | |United States of America|US dollar|316 million|9.8 million sq km|
10 | |Canada|Canadian dollar|34.7 million|9.9 million sq km|
11 | |United Kingdom|pound sterling|62.8 million|242,514 sq km|
12 | |Republic of Poland|zloty|38.3 million|312,685 sq km|
--------------------------------------------------------------------------------
| | |