@@ -18,7 +18,8 @@ type Commands map[string]Command
1818
1919type Include struct {
2020 _Position
21- file string
21+ file string
22+ filter * regexp.Regexp
2223}
2324
2425func (i * Include ) getData (p string ) ([]byte , error ) {
@@ -45,8 +46,8 @@ type IncludePat struct {
4546
4647// --- begin example ---
4748// --- begin include args ---
48- var includeExpNum = regexp .MustCompile ("^{([^}]+)}(?:{([0-9]+)?(?::([0-9]+)?)?})?$" )
49- var includeExpPat = regexp .MustCompile ("^{([^}]+)}{([a-zA-Z -]+)}$" )
49+ var includeExpNum = regexp .MustCompile ("^{([^}]+)}(?:{([0-9]+)?(?::([0-9]+)?)?}(?:{(.*)})? )?$" )
50+ var includeExpPat = regexp .MustCompile ("^{([^}]+)}{([a-zA-Z -]+)}(?:{(.*)})? $" )
5051
5152// --- end include args ---
5253// --- end example ---
@@ -70,17 +71,60 @@ func NewInclude(line, col int, args []byte) (Command, error) {
7071 return nil , fmt .Errorf ("invalid start line: %w" , err )
7172 }
7273 }
73- return & IncludeNum {Include {Position {line , col }, string (matches [1 ])}, int (start ), int (end )}, nil
74+ var filter * regexp.Regexp
75+ if matches [4 ] != nil {
76+ filter , err = regexp .Compile (string (matches [4 ]))
77+ if err != nil {
78+ return nil , fmt .Errorf ("invalid filter expression: %w" , err )
79+ }
80+ }
81+ return & IncludeNum {Include {Position {line , col }, string (matches [1 ]), filter }, int (start ), int (end )}, nil
7482 }
7583
7684 matches = includeExpPat .FindSubmatch (args )
7785 if len (matches ) != 0 {
78- return & IncludePat {Include {Position {line , col }, string (matches [1 ])}, string (matches [2 ])}, nil
86+ var filter * regexp.Regexp
87+ if matches [3 ] != nil {
88+ filter , err = regexp .Compile (string (matches [3 ]))
89+ if err != nil {
90+ return nil , fmt .Errorf ("invalid filter expression: %w" , err )
91+ }
92+ }
93+ return & IncludePat {Include {Position {line , col }, string (matches [1 ]), filter }, string (matches [2 ])}, nil
7994 }
8095
8196 return nil , fmt .Errorf ("invalid include arguments %q" , string (args ))
8297}
8398
99+ // --- begin filter ---
100+ // An optional third argument can be used to specify a filter regular
101+ // expression. It must contain one matching group. The
102+ // selected file range is matched by this regular expression and
103+ // the content of the first matching group of the all matches is
104+ // concatenated. If the expression uses the multi-line mode, the matches
105+ // are suffixed with a newline.
106+ // --- end filter ---
107+
108+ func (i * Include ) Filter (data []byte ) ([]byte , error ) {
109+ if i .filter == nil {
110+ return data , nil
111+ }
112+ sep := ""
113+ if strings .HasPrefix (i .filter .String (), "(?m)" ) {
114+ sep = "\n "
115+ }
116+ matches := i .filter .FindAllSubmatch (data , - 1 )
117+ var result []byte
118+ for _ , m := range matches {
119+ if len (m ) != 2 {
120+ return nil , fmt .Errorf ("regular expressin must contain one matching group" )
121+ }
122+ result = append (result , m [1 ]... )
123+ result = append (result , []byte (sep )... )
124+ }
125+ return result , nil
126+ }
127+
84128func (i * IncludeNum ) GetSubstitution (p string ) ([]byte , error ) {
85129 data , err := i .getData (p )
86130 if err != nil {
@@ -102,7 +146,7 @@ func (i *IncludeNum) GetSubstitution(p string) ([]byte, error) {
102146 if end > len (lines ) {
103147 return nil , fmt .Errorf ("end line %d after end of file (%q %d lines" , end , i .file , len (lines ))
104148 }
105- return []byte (strings .Join (lines [start :end ], "\n " )), nil
149+ return i . Filter ( []byte (strings .Join (lines [start :end ], "\n " )))
106150}
107151
108152func (i * IncludePat ) GetSubstitution (p string ) ([]byte , error ) {
@@ -119,7 +163,8 @@ func (i *IncludePat) GetSubstitution(p string) ([]byte, error) {
119163 if err != nil {
120164 return nil , err
121165 }
122- return data [start :end ], nil
166+
167+ return i .Filter (data [start :end ])
123168}
124169
125170func (i * IncludePat ) match (data []byte , key string ) (int , int , error ) {
0 commit comments