NGrep

From Niki

Jump to: navigation, search

This is yet another grep wrapper I wrote for finding stuff in NEdit's code tree. You can search in the current file, the current directory and in parallel directories, great if you don't remember whether something is in source/ or util/. The result is cleaned of various bits (binaries, backup files, cvs update files), and presented in a dialog. You can then select one line and go there.

The command line expects grep to understand the parameters '-n' and '--'. If yours doesn't, consider installing some GNU tools.

I use this macro with the following entry in the menu:

if (-1 == $selection_start)
{
    nGrep()
} else
{
    nGrep(get_selection())
}

Here goes:

define nGrep
{
    #   The NEdit Grep
    #
    #   Copyright 2004, 2005 Thorsten Haude
    #
    #   This is free software; you may modify and redistribute it under
    #   the terms of the GNU General Public License, Version 2 or, at your
    #   option, any later version.
    #   (http://www.gnu.org/licenses/gpl.html)
    #
    #   v1.1
    #
    #   nGrep([text[, scope]])
    #
    #   Calls grep(1) on either:
    #   - The current file (scope = file)
    #   - All files in the same directory (scope = dir)
    #   - All files in the same and parallel directories (scope = parallel)
    #   If the scope is not provided, a dialog is presented
    #
    #   The result of grep is presented in a list dialog. If the user
    #   selects a line, the respective file is opened, focused and the
    #   line is selected.
    #   The command line expects grep to understand the parameters '-n'
    #   and '--'. If yours don't, consider installing some GNU tools.
    #
    #   If text is not provided, it will be dialoged for

    maxLineLength = 200

    if ($n_args > 2)
    {
        #   Too many arguments
        beep()
        return
    }

    if ($n_args == 0)
    {
        #   Neither text nor scope
        text = string_dialog("Grep what?", "OK", "Cancel")
        if ($string_dialog_button != 1)
        {
            return
        }
    } else
    {
        #   We have a text to search for
        text = $1
    }

    if ($n_args < 2)
    {
        #   We have to present a dialog to request grep scope.
        rc = dialog("Where do you want to search?", \
                "This File", \
                "Directory", \
                "Parallel Dirs", \
                "Cancel")
        #   scope is set according to the button pressed.
        if (rc == 1)
        {
            scope = "file"
        } else if (rc == 2)
        {
            scope = "dir"
        } else if (rc == 3)
        {
            scope = "parallel"
        } else
        {
            #   Dialog is closed or canceled
            return
        }
    } else
    {
        #   The scope is set by parameter; if this is an illegal scope,
        #   we catch it below
        scope = $2
    }

    #   Build the grep path
    if (scope == "file")
    {
        grepPath = $file_path $file_name
    } else if (scope == "dir")
    {
        grepPath = $file_path "*"
    } else if (scope == "parallel")
    {
        grepPath = $file_path "../*/*"
    } else
    {
        #   Someone submitted a wrong scope
        beep()
        return
    }

    text = replace_in_string(text, "\\", "\\\\", "copy")

    #   Build the command for executing and display
    command = "grep -sn -- \'" text "\' " grepPath

    #   Do it.
    list = shell_command(command, "")

    if ($shell_cmd_status == 1)
    {
        dialog("No Hits!")
        return
    } else
    {
        #   Don't show the file path, we know already
        list = replace_in_string(list, "^" $file_path, "", "regex")

        #   Show only the first maxLineLength characters.
        list = replace_in_string(list, "^(.{1," maxLineLength "}).*$", "\\1", "regex")

        #   Delete Backup files
        list = replace_in_string(list, "^.*~\\d+~.*$", "\n", "regex", "copy")

        #   Remove entries about binary files
        list = replace_in_string(list, "^.bereinstimmungen in Bin.rdatei.*\n", "", "regex", "copy")
        list = replace_in_string(list, "^Binary file.*matches\n", "", "regex", "copy")

        #   Delete entries about CVS files
        list = replace_in_string(list, "^\\.#.*?\\.\\d+\\.\\d+:\\d+.*$", "\n", "regex", "copy")

        #   clean up empty lines
        list = replace_in_string(list, "\n+", "\n", "regex", "copy")

        if ("" == list)
        {
            dialog("No Hits!")
            return
        }

        #   Let the user choose
        line = list_dialog("Choose line: \n(" command "): ", list, "Go to Line", "Open list in new Document", "Cancel")
    }

    if (1 == $list_dialog_button && "" != line)
    {
        #   Put the result elements in an array
        result = split(line, ":")

        if (scope == "file")
        {
            #   Just go to the line
            goto_line_number(result[0])
        } else
        {
            #   Open file, change focus, goto the line
            open($file_path result[0])
            focus_window($file_path result[0])
            goto_line_number(result[1])
        }
    } else if (2 == $list_dialog_button)
    {
        new("transient")
        focus_window("last")
        insert_string(list)
    }

    return
}