@@ -28,7 +28,6 @@ type NLPToken struct {
2828type Sequence struct {
2929 Definition `mapstructure:",squash"`
3030 Tokens []NLPToken
31- history []int
3231 Ignorecase bool
3332 needsTagging bool
3433}
@@ -134,7 +133,7 @@ func tokensMatch(token NLPToken, word tag.Token) bool {
134133 return true
135134}
136135
137- func sequenceMatches (idx int , chk Sequence , target NLPToken , words []tag.Token ) ([]string , int ) {
136+ func sequenceMatches (idx int , chk Sequence , target NLPToken , words []tag.Token , history [] int ) ([]string , int ) {
138137 var text []string
139138
140139 toks := chk .Tokens
@@ -144,7 +143,7 @@ func sequenceMatches(idx int, chk Sequence, target NLPToken, words []tag.Token)
144143 index := 0
145144
146145 for jdx , tok := range words {
147- if tokensMatch (target , tok ) && ! core .IntInSlice (jdx , chk . history ) {
146+ if tokensMatch (target , tok ) && ! core .IntInSlice (jdx , history ) {
148147 index = jdx
149148 // We've found our context.
150149 //
@@ -213,21 +212,41 @@ func sequenceMatches(idx int, chk Sequence, target NLPToken, words []tag.Token)
213212}
214213
215214func stepsToString (steps []string ) string {
216- s := ""
217- for _ , step := range steps {
218- if strings .HasPrefix (step , "'" ) {
219- s += step
215+ var sb strings.Builder
216+
217+ for i , step := range steps {
218+ if step == "." || step == "," || step == ":" || step == ";" || step == "!" || step == "?" || step == "'" || step == `"` || step == ")" {
219+ // No space before punctuation or closing parenthesis
220+ sb .WriteString (step )
221+ } else if step == "(" {
222+ // No space before or after an opening parenthesis
223+ if i > 0 && sb .Len () > 0 {
224+ lastChar := sb .String ()[sb .Len ()- 1 ]
225+ if lastChar != ' ' {
226+ sb .WriteString (" " )
227+ }
228+ }
229+ sb .WriteString (step )
230+ } else if strings .HasPrefix (step , "'" ) {
231+ // If the step starts with an apostrophe, attach it without space
232+ sb .WriteString (step )
220233 } else {
221- s += " " + step
234+ // Otherwise, add space before the word
235+ if sb .Len () > 0 {
236+ sb .WriteString (" " )
237+ }
238+ sb .WriteString (step )
222239 }
223240 }
224- return strings .Trim (s , " " )
241+
242+ return strings .TrimSpace (sb .String ())
225243}
226244
227245// Run looks for the user-defined sequence of tokens.
228246func (s Sequence ) Run (blk nlp.Block , f * core.File , _ * core.Config ) ([]core.Alert , error ) {
229247 var alerts []core.Alert
230248 var offset []string
249+ var history []int
231250
232251 // This is *always* sentence-scoped.
233252 words := nlp .TextToTokens (blk .Text , & f .NLP )
@@ -238,8 +257,8 @@ func (s Sequence) Run(blk nlp.Block, f *core.File, _ *core.Config) ([]core.Alert
238257 // We're looking for our "anchor" ...
239258 for _ , loc := range tok .re .FindAllStringIndex (txt , - 1 ) {
240259 // These are all possible violations in `txt`:
241- steps , index := sequenceMatches (idx , s , tok , words )
242- s . history = append (s . history , index ) //nolint:staticcheck
260+ steps , index := sequenceMatches (idx , s , tok , words , history )
261+ history = append (history , index )
243262
244263 if len (steps ) > 0 {
245264 seq := stepsToString (steps )
0 commit comments