Version 1 (modified by xkjq, 2 years ago)

--

GrepSearch Plugin

Unfortunately WikidPads? built-in search can be a little slow when searching a large number of files.

The plugin below is a quick hack to allow searching a via grep from within Wikidpad.

Notes

  • It is not particularly polished code and is missing a few features that I may add in the future.
  • WARNING: your search is passed to the shell 'grep -ni "{--your search term--}" {--your wiki data dir--/*.wiki}' when searching.

Requirements

Grep - Should be installed by default on all *nix based os' (It may well work on windows if you install grep or another compatible clone)

Code

import os, wx, subprocess, re
from collections import defaultdict

WIKIDPAD_PLUGIN = (("MenuFunctions",1),)

def describeMenuItems(wiki):
        global nextnumber
        return ((Grep, "Grep Search\tCtrl-Shift-F", "Search with Grep"),)

class ResultsList(wx.HtmlListBox):
    def __init__(self, parent, pWiki):
        wx.HtmlListBox.__init__(self, parent, -1)

        self.pWiki = pWiki

        wx.EVT_LISTBOX_DCLICK(self, -1, self.OnDClick)

    def SetResults(self, results, results_count):
        self.results = results
        self.results_count = results_count

    def OnGetItem(self, n):
        wikipage, line, string = self.results[n]

        if line is None: # Header
            return "<table><tr><td width=100%></td></tr></table><table><tr><td bgcolor='#0000ff' width='6'></td><td><font color='blue'><b>{0} <u>({1})</u></b></font></td></tr></table>".format(wikipage, self.results_count[wikipage])

        return "<table><tr><td bgcolor='#0000A0' width='6'></td><td><u>Line {0}</u> - {1}</td></tr></table>".format(line, string)


    def GetCount(self):
        return len(self.results)

    def OnDClick(self, evt):
        sel = self.GetSelection()

        if sel == -1 or self.GetCount() == 0:
            return



        wikiWord, line, string = self.results[sel]
        self.pWiki.openWikiPage(wikiWord)

        # Goto line
        #if line:
        #    editor = self.pWiki.getActiveEditor()
        #    if editor is not None:
        #        self.pWiki.getActiveEditor().


class GrepDialog(wx.Dialog):
    def __init__(self, pWiki, id=wx.ID_ANY, title="Grep Search"):
        wx.Dialog.__init__(self, pWiki, id, title, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)

        self.pWiki = pWiki

        search_box = wx.TextCtrl(self, -1)

        results_box = ResultsList(self, pWiki)
        #results_box.SetItemCount(0)
        self.results_box = results_box

        btnFind = wx.Button(self, label="&Search", id=-1)
        btnCancel = wx.Button(self, label="&Cancel", id=-1)

        buttons = wx.BoxSizer(wx.HORIZONTAL)

        buttons.Add(btnFind)
        buttons.Add(btnCancel)

        btnFind.Bind(wx.EVT_BUTTON, self.OnSearch)
        btnCancel.Bind(wx.EVT_BUTTON, self.OnClose)

        btnFind.SetDefault()

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(results_box, 1, wx.EXPAND|wx.ALL, 5)
        sizer.Add(search_box, 0, wx.HORIZONTAL|wx.EXPAND, 5)
        sizer.Add(buttons, 0, wx.EXPAND|wx.ALL, 5)
        self.SetSizerAndFit(sizer)
        self.SetSize((200, 400))

        search_box.SetFocus()

        self.search_box = search_box

    def OnSearch(self, evt):
        self.results_box.SetItemCount(0)
        self.Refresh()

        search_string = self.search_box.GetValue()
        if not search_string:
            return

        data_dir = self.pWiki.dataDir
        l = len(data_dir) + 1

        os.path.join(data_dir, "*.wiki")

        try:
            ret = subprocess.check_output('grep -ni "{0}" {1}'.format(search_string, os.path.join(data_dir, "*.wiki")), shell=True)
        except:
            # No results
            return
        results = []
        pages = set()

        results_count = defaultdict(int)

        for i in ret.split("\n")[:-1]:
            wikipage, line, context_string = i.split(":", 2)
            wikipage = wikipage[l:-5]
            if wikipage not in pages:
                results.append((wikipage, None, None))
                pages.add(wikipage)

            results_count[wikipage] += 1

            context_string = re.sub(r"({0})".format(search_string), r"<font color='red'>\1</font>", context_string, flags=re.IGNORECASE)
            results.append((wikipage, line, context_string))

        self.results_box.SetResults(results, results_count)

        self.results_box.SetItemCount(len(results))

    def OnClose(self, evt):
        #self.Show(False)
        self.Destroy()




def Grep(pWiki, evt):

    search = GrepDialog(pWiki)
    search.Show()
import os, wx, subprocess, re
from collections import defaultdict

WIKIDPAD_PLUGIN = (("MenuFunctions",1),)

def describeMenuItems(wiki):
        global nextnumber
        return ((Grep, "Grep Search\tCtrl-Shift-F", "Search with Grep"),)

class ResultsList(wx.HtmlListBox):
    def __init__(self, parent, pWiki):
        wx.HtmlListBox.__init__(self, parent, -1)

        self.pWiki = pWiki

        wx.EVT_LISTBOX_DCLICK(self, -1, self.OnDClick)

    def SetResults(self, results, results_count):
        self.results = results
        self.results_count = results_count

    def OnGetItem(self, n):
        wikipage, line, string = self.results[n]

        if line is None: # Header
            return "<table><tr><td width=100%></td></tr></table><table><tr><td bgcolor='#0000ff' width='6'></td><td><font color='blue'><b>{0} <u>({1})</u></b></font></td></tr></table>".format(wikipage, self.results_count[wikipage])

        return "<table><tr><td bgcolor='#0000A0' width='6'></td><td><u>Line {0}</u> - {1}</td></tr></table>".format(line, string)


    def GetCount(self):
        return len(self.results)

    def OnDClick(self, evt):
        sel = self.GetSelection()

        if sel == -1 or self.GetCount() == 0:
            return



        wikiWord, line, string = self.results[sel]
        self.pWiki.openWikiPage(wikiWord)

        # Goto line
        #if line:
        #    editor = self.pWiki.getActiveEditor()
        #    if editor is not None:
        #        self.pWiki.getActiveEditor().


class GrepDialog(wx.Dialog):
    def __init__(self, pWiki, id=wx.ID_ANY, title="Grep Search"):
        wx.Dialog.__init__(self, pWiki, id, title, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)

        self.pWiki = pWiki

        search_box = wx.TextCtrl(self, -1)

        results_box = ResultsList(self, pWiki)
        #results_box.SetItemCount(0)
        self.results_box = results_box

        btnFind = wx.Button(self, label="&Search", id=-1)
        btnCancel = wx.Button(self, label="&Cancel", id=-1)

        buttons = wx.BoxSizer(wx.HORIZONTAL)

        buttons.Add(btnFind)
        buttons.Add(btnCancel)

        btnFind.Bind(wx.EVT_BUTTON, self.OnSearch)
        btnCancel.Bind(wx.EVT_BUTTON, self.OnClose)

        btnFind.SetDefault()

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(results_box, 1, wx.EXPAND|wx.ALL, 5)
        sizer.Add(search_box, 0, wx.HORIZONTAL|wx.EXPAND, 5)
        sizer.Add(buttons, 0, wx.EXPAND|wx.ALL, 5)
        self.SetSizerAndFit(sizer)
        self.SetSize((200, 400))

        search_box.SetFocus()

        self.search_box = search_box

    def OnSearch(self, evt):
        self.results_box.SetItemCount(0)
        self.Refresh()

        search_string = self.search_box.GetValue()
        if not search_string:
            return

        data_dir = self.pWiki.dataDir
        l = len(data_dir) + 1

        os.path.join(data_dir, "*.wiki")

        try:
            ret = subprocess.check_output('grep -ni "{0}" {1}'.format(search_string, os.path.join(data_dir, "*.wiki")), shell=True)
        except:
            # No results
            return
        results = []
        pages = set()

        results_count = defaultdict(int)

        for i in ret.split("\n")[:-1]:
            wikipage, line, context_string = i.split(":", 2)
            wikipage = wikipage[l:-5]
            if wikipage not in pages:
                results.append((wikipage, None, None))
                pages.add(wikipage)

            results_count[wikipage] += 1

            context_string = re.sub(r"({0})".format(search_string), r"<font color='red'>\1</font>", context_string, flags=re.IGNORECASE)
            results.append((wikipage, line, context_string))

        self.results_box.SetResults(results, results_count)

        self.results_box.SetItemCount(len(results))

    def OnClose(self, evt):
        #self.Show(False)
        self.Destroy()




def Grep(pWiki, evt):

    search = GrepDialog(pWiki)
    search.Show()