Skip to content

Commit

Permalink
Exclude file path (hound-search#347)
Browse files Browse the repository at this point in the history
* index: add a search option to exclude files given a regexp

* api: add the excludeFiles query parameter

Set the index search options ExcludeFileRegexp with this parameter
to allow excluding files from the search via a regexp.

* js: add the excludeFiles search parameter

* css: increase the label width to fit 'Exclude file path'

* js: correctly check that advanced is empty
  • Loading branch information
vrischmann committed Sep 27, 2020
1 parent fcb4ffd commit e14bb29
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 14 deletions.
1 change: 1 addition & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ func Setup(m *http.ServeMux, idx map[string]*searcher.Searcher) {
query := r.FormValue("q")
opt.Offset, opt.Limit = parseRangeValue(r.FormValue("rng"))
opt.FileRegexp = r.FormValue("files")
opt.ExcludeFileRegexp = r.FormValue("excludeFiles")
opt.IgnoreCase = parseAsBool(r.FormValue("i"))
opt.LinesOfContext = parseAsUintValue(
r.FormValue("ctx"),
Expand Down
24 changes: 19 additions & 5 deletions index/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ type IndexOptions struct {
}

type SearchOptions struct {
IgnoreCase bool
LinesOfContext uint
FileRegexp string
Offset int
Limit int
IgnoreCase bool
LinesOfContext uint
FileRegexp string
ExcludeFileRegexp string
Offset int
Limit int
}

type Match struct {
Expand Down Expand Up @@ -167,6 +168,14 @@ func (n *Index) Search(pat string, opt *SearchOptions) (*SearchResponse, error)
}
}

var excludeFre *regexp.Regexp
if opt.ExcludeFileRegexp != "" {
excludeFre, err = regexp.Compile(opt.ExcludeFileRegexp)
if err != nil {
return nil, err
}
}

files := n.idx.PostingQuery(index.RegexpQuery(re.Syntax))
for _, file := range files {
var matches []*Match
Expand All @@ -178,6 +187,11 @@ func (n *Index) Search(pat string, opt *SearchOptions) (*SearchResponse, error)
continue
}

// reject files that match the exclude file pattern
if excludeFre != nil && excludeFre.MatchString(name, true, true) > 0 {
continue
}

filesOpened++
if err := g.grep2File(filepath.Join(n.Ref.dir, "raw", name), re, int(opt.LinesOfContext),
func(line []byte, lineno int, before [][]byte, after [][]byte) (bool, error) {
Expand Down
2 changes: 1 addition & 1 deletion ui/assets/css/hound.css
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ button:focus {
#adv > .field > label {
/* Media object left */
float: left;
width: 90px;
width: 100px;
color: #999;
}

Expand Down
51 changes: 43 additions & 8 deletions ui/assets/js/hound.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ var ParamsFromUrl = function(params) {
q: '',
i: 'nope',
files: '',
excludeFiles: '',
repos: '*'
};
return ParamsFromQueryString(location.search, params);
Expand Down Expand Up @@ -360,7 +361,7 @@ var SearchBar = React.createClass({
switch (event.keyCode) {
case 38:
// if advanced is empty, close it up.
if (this.refs.files.getDOMNode().value.trim() === '') {
if (this.isAdvancedEmpty()) {
this.hideAdvanced();
}
this.refs.q.getDOMNode().focus();
Expand All @@ -373,6 +374,23 @@ var SearchBar = React.createClass({
filesGotFocus: function(event) {
this.showAdvanced();
},
excludeFilesGotKeydown: function(event) {
switch (event.keyCode) {
case 38:
// if advanced is empty, close it up.
if (this.isAdvancedEmpty()) {
this.hideAdvanced();
}
this.refs.q.getDOMNode().focus();
break;
case 13:
this.submitQuery();
break;
}
},
excludeFilesGotFocus: function(event) {
this.showAdvanced();
},
submitQuery: function() {
this.props.onSearchRequested(this.getParams());
},
Expand All @@ -392,37 +410,40 @@ var SearchBar = React.createClass({
return {
q : this.refs.q.getDOMNode().value.trim(),
files : this.refs.files.getDOMNode().value.trim(),
excludeFiles : this.refs.excludeFiles.getDOMNode().value.trim(),
repos : repos.join(','),
i: this.refs.icase.getDOMNode().checked ? 'fosho' : 'nope'
};
},
setParams: function(params) {
var q = this.refs.q.getDOMNode(),
i = this.refs.icase.getDOMNode(),
files = this.refs.files.getDOMNode();
files = this.refs.files.getDOMNode(),
excludeFiles = this.refs.excludeFiles.getDOMNode();

q.value = params.q;
i.checked = ParamValueToBool(params.i);
files.value = params.files;
excludeFiles.value = params.excludeFiles;
},
hasAdvancedValues: function() {
return this.refs.files.getDOMNode().value.trim() !== '' || this.refs.icase.getDOMNode().checked || this.refs.repos.getDOMNode().value !== '';
return this.refs.files.getDOMNode().value.trim() !== '' || this.refs.excludeFiles.getDOMNode().value.trim() !== '' || this.refs.icase.getDOMNode().checked || this.refs.repos.getDOMNode().value !== '';
},
isAdvancedEmpty: function() {
return this.refs.files.getDOMNode().value.trim() === '' && this.refs.excludeFiles.getDOMNode().value.trim() === '';
},
showAdvanced: function() {
var adv = this.refs.adv.getDOMNode(),
ban = this.refs.ban.getDOMNode(),
q = this.refs.q.getDOMNode(),
files = this.refs.files.getDOMNode();
files = this.refs.files.getDOMNode(),
excludeFiles = this.refs.excludeFiles.getDOMNode();

css(adv, 'height', 'auto');
css(adv, 'padding', '10px 0');

css(ban, 'max-height', '0');
css(ban, 'opacity', '0');

if (q.value.trim() !== '') {
files.focus();
}
},
hideAdvanced: function() {
var adv = this.refs.adv.getDOMNode(),
Expand Down Expand Up @@ -499,6 +520,17 @@ var SearchBar = React.createClass({
onFocus={this.filesGotFocus} />
</div>
</div>
<div className="field">
<label htmlFor="excludeFiles">Exclude File Path</label>
<div className="field-input">
<input type="text"
id="excludeFiles"
placeholder="regexp"
ref="excludeFiles"
onKeyDown={this.excludeFilesGotKeydown}
onFocus={this.excludeFilesGotFocus} />
</div>
</div>
<div className="field">
<label htmlFor="ignore-case">Ignore Case</label>
<div className="field-input">
Expand Down Expand Up @@ -763,6 +795,7 @@ var App = React.createClass({
q: params.q,
i: params.i,
files: params.files,
excludeFiles: params.excludeFiles,
repos: repos
});

Expand Down Expand Up @@ -817,6 +850,7 @@ var App = React.createClass({
'?q=' + encodeURIComponent(params.q) +
'&i=' + encodeURIComponent(params.i) +
'&files=' + encodeURIComponent(params.files) +
'&excludeFiles=' + encodeURIComponent(params.excludeFiles) +
'&repos=' + params.repos;
history.pushState({path:path}, '', path);
},
Expand All @@ -827,6 +861,7 @@ var App = React.createClass({
q={this.state.q}
i={this.state.i}
files={this.state.files}
excludeFiles={this.state.excludeFiles}
repos={this.state.repos}
onSearchRequested={this.onSearchRequested} />
<ResultView ref="resultView" q={this.state.q} />
Expand Down

0 comments on commit e14bb29

Please sign in to comment.