<commit_before>var TT = require('./thin-tree');


var SearchTree = {

    searchTree: function(query, op, source) {
        op = op || 'where';
        source = source || this.preOrderTraverse();
        return _[op](source, query);
    },

    searchFollowing: function(query, wrap) {
        return this.search(query, this.getFollowing(wrap));
    },

    searchPreceding: function(query, wrap) {
        return this.search(query, this.getPreceding(wrap))
    },

    searchSubtree: function(query, op) {
        op = op || 'where';
        return this[op](query) || this.reduce(function(targets, node) {
            return targets.concat(node.searchSubtree(query));
        }, [])
    },

    findTree: function(query, source, op) {
        this.search(query, null, 'find');
    },

    findFollowing: function(query, wrap) {
        return this.find(query, this.getFollowing(wrap));
    },

    findPreceding: function(query, wrap) {
        return this.find(query, this.getPreceding(wrap))
    },

    findSubtree: function(query, op) {
        return this.find(query) || this.reduce(function(target, node) {
            return target || node.findSubtree(query);
        }, null)
    },

    getPreceding: function(wrap) {
        var preorder = this.root.preOrderTraverse().reverse();
        var index = preorder.indexOf(this);
        return preorder.slice(index + 1).concat(
            wrap ? preorder.slice(0, index) : []
        );
    },

    getFollowing:  function(wrap) {
        var preorder = this.root.preOrderTraverse();
        var index = preorder.indexOf(this);
        return preorder.slice(index + 1).concat(
            wrap ? preorder.slice(0, index) : []
        );
    }

}


///////////////////////////////////////////////////////////////////////////////
///
///                         Collection Methods
///
///////////////////////////////////////////////////////////////////////////////


var collectionMethods = [
        'chain',
        /**
         * Collection Methods
         */
        'at', 'contains', 'countBy', 'every', 'filter', 'find', 'findLast',
        'forEach', 'forEachRight', 'groupBy', 'indexBy', 'invoke', 'map',
        'max', 'min', 'pluck', 'reduce', 'reduceRight', 'reject', 'sample',
        'shuffle', 'size', 'some', 'sortBy', 'toArray', 'where',
        /**
         * Object method
         */
        'transform',<commit_msg>Allows different op for search and finds.<commit_after>var TT = require('./thin-tree');


var SearchTree = {

    searchTree: function(query, op, source) {
        op = op || 'where';
        source = source || this.preOrderTraverse();
        return _[op](source, query);
    },

    searchFollowing: function(query, wrap) {
        return this.search(query, this.getFollowing(wrap));
    },

    searchPreceding: function(query, wrap) {
        return this.search(query, this.getPreceding(wrap))
    },

    searchSubtree: function(query, op) {
        return this.reduce(function(targets, node) {
            return targets.concat(node.searchSubtree(query));
        }, this[op](query))
    },

    findTree: function(query, source, op) {
        this.search(query, null, 'find');
    },

    findFollowing: function(query, wrap) {
        return this.find(query, this.getFollowing(wrap));
    },

    findPreceding: function(query, wrap) {
        return this.find(query, this.getPreceding(wrap))
    },

    findSubtree: function(query, op) {
        return this[op](query) || this.reduce(function(target, node) {
            return target || node.findSubtree(query);
        }, null)
    },

    findSubtree: function(query, op, iterator, callback) {
        return this[op](query) || this[iterator](function(target, node) {
            return target || node.findSubtree(query);
        }, null);
    },


    getPreceding: function(wrap) {
        var preorder = this.root.preOrderTraverse().reverse();
        var index = preorder.indexOf(this);
        return preorder.slice(index + 1).concat(
            wrap ? preorder.slice(0, index) : []
        );
    },

    getFollowing:  function(wrap) {
        var preorder = this.root.preOrderTraverse();
        var index = preorder.indexOf(this);
        return preorder.slice(index + 1).concat(
            wrap ? preorder.slice(0, index) : []
        );
    }

}

SearchTree.recurse(function(node){
    return node
})


///////////////////////////////////////////////////////////////////////////////
///
///                         Collection Methods
///
///////////////////////////////////////////////////////////////////////////////


var collectionMethods = [
        'chain',
        /**
         * Collection Methods
         */
        'at', 'contains', 'countBy', 'every', 'filter', 'find', 'findLast',
        'forEach', 'forEachRight', 'groupBy', 'indexBy', 'invoke', 'map',
        'max', 'min', 'pluck', 'reduce', 'reduceRight', 'reject', 'sample',
        'shuffle', 'size', 'some', 'sortBy', 'toArray', 'where',
        /**
         * Object method
         */
        'transform',
{'fraction_non_alphanumeric': 0.20955590800951626, 'fraction_numerical': 0.0015860428231562252, 'mean_word_length': 1.8960964408725602, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4358133', 'n_tokens_mistral': 1444, 'n_tokens_neox': 1391, 'n_words': 290}