(context parseContext)
| 118 | } |
| 119 | |
| 120 | func (defaultParser) Parse(context parseContext) (res *parseResult, err error) { |
| 121 | res = &parseResult{} |
| 122 | |
| 123 | flagContext := datastore.FlagContext{ |
| 124 | SubCommand: parseUsageSubCommand(context.args, context.text), |
| 125 | } |
| 126 | |
| 127 | var completions []datastore.Completion |
| 128 | var discoveredFlagMap = make(map[string]bool) |
| 129 | var discoveredFlags []string |
| 130 | for _, line := range context.text.lines { |
| 131 | flagsMatch := flagRegexp.FindAllStringSubmatch(line, -1) |
| 132 | for _, match := range flagsMatch { |
| 133 | flag := match[1] |
| 134 | if !discoveredFlagMap[flag] { |
| 135 | discoveredFlags = append(discoveredFlags, flag) |
| 136 | discoveredFlagMap[flag] = true |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | // Sometimes we find examples of merged single letter options like `-xzf` (== -x -z -f) in help messages. |
| 142 | // We want to distinguish them from java style-options like `-server`. |
| 143 | // We want to guess if we are dealing with gnu style or java style. |
| 144 | isGnuLike := false |
| 145 | for _, flag := range discoveredFlags { |
| 146 | if strings.HasPrefix(flag, "--") { |
| 147 | isGnuLike = true |
| 148 | break |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | for _, flag := range discoveredFlags { |
| 153 | if isGnuLike && isJavaStyleFlag(flag) { |
| 154 | continue |
| 155 | } |
| 156 | completions = append(completions, datastore.Completion{Flag: flag, Context: flagContext}) |
| 157 | } |
| 158 | |
| 159 | // Now we are going to search for sub-commands. |
| 160 | // Idea is following |
| 161 | // 1. We are looking for string that ends with `commands:` (we ignore case) |
| 162 | // 2. Then we check indentation of the next line |
| 163 | // 3. First word of the line that has same indentation as first line is sub-command. |
| 164 | // 4. We skip the line if line indent is bigger than indent of the first line |
| 165 | // (most likely this is continuation of help) |
| 166 | // 5. We stop when we find empty line or line that has indent less than indent of the first line. |
| 167 | const ( |
| 168 | Outer = iota |
| 169 | FirstLineInside = iota |
| 170 | Inside = iota |
| 171 | ) |
| 172 | var state = Outer |
| 173 | var prevIndent = -1 |
| 174 | var currentParagraphIndent = 0 |
| 175 | for _, line := range context.text.lines { |
| 176 | var indent = computeIndent(line) |
| 177 | switch state { |
nothing calls this directly
no test coverage detected