{ |one, step, back| } 1 of 1 article Syndicate: full/short

Using Rake as a Library   26 Aug 06
[ print link all ]

I’ve been exploring using Rake as a Ruby Library.

Find In Code

Lately, I’ve been experimenting with using Rake as a normal library in regular Ruby scripts (rather than in Rakefiles). It turns out there are some very useful things you can do.

For example, to locate a particular piece of code in a not so small Ruby project, I often use the following command line:

    $ find . -name '*.rb' | xargs grep -ni "snippet of code" 

This quickly searches all my Ruby files and displays matching lines with file names and line numbers. However, the line is long to type and won’t work in windows (unless you have cygwin installed).

So I wrote the following Ruby program and saved it in a file called “fic” (Find In Code):

  #!/usr/bin/env ruby
  require 'rake'
  FileList["**/*.rb"].egrep(Regexp.new(ARGV.first))

An Enhanced Version

This proved so useful, that I enhanced the code to allow for searching for files ending in arbitrary extendsions and to handle more matching options on the command line.

Here’s the enhanced version:

  #!/usr/bin/env ruby
  # -*- ruby -*-

  exts = ['.rb']
  if ARGV[0] =~ /^\.[a-zA-Z0-9]+$/
    exts = []
    while ARGV[0] =~ /^\.[a-zA-Z0-9]+$/
      exts << ARGV.shift
    end
  end

  ext = "{" + exts.join(',') + "}" 

  if ARGV.size < 1
    puts "Usage: #{File.basename($0)} [.ext ...] pattern ..." 
    exit 1
  end

  require 'rake'
  FileList["**/*#{ext}"].egrep(Regexp.new(ARGV.join('|')))

And if you are using Emacs …

If you are using Emacs, and you have my “visit source” code loaded, all you need to do is put the cursor on the line you are interested in and press F2.

Oh, you would like to see the elisp code for “visit source”? Let’s see, where did I put that?

  $ cd .elisp/
  $ fic .el jw-visit-source
  ini/ini-cust.el:131:(defun jw-visit-source ()
  ini/ini-zkeys.el:7:(global-set-key [f2] 'jw-visit-source)    

Now, I move the cursor to the first line and press F2, and I find:

  ;;; Source File Visiting =============================================

  (defun jw-current-line ()
    "Return the current line." 
    (let
        ((bol (save-excursion (beginning-of-line)(point)))
         (eol (save-excursion (end-of-line)(point))))
      (buffer-substring bol eol) ))

  (defun jw-extract-file-lines (line)
    "Extract a list of file/line pairs from the given line of text." 
    (let*
        ((unix_fn "[^ \t\n\r\"'([<{]+")
         (dos_fn  "[a-zA-Z]:[^\t\n\r\"'([<{]+")
         (flre (concat "\\(" unix_fn "\\|" dos_fn "\\):\\([0-9]+\\)"))
         (start nil)
         (result nil))
      (while (string-match flre line start)
        (setq start (match-end 0))
        (setq result
              (cons (list 
                     (substring line (match-beginning 1) (match-end 1))
                     (string-to-int (substring line (match-beginning 2) (match-end 2))))
                    result)))
      result))

  (defun jw-select-file-line (candidates)
    "Select a file/line candidate that references an existing file." 
    (cond ((null candidates) nil)
          ((file-readable-p (caar candidates)) (car candidates))
          (t (jw-select-file-line (cdr candidates))) ))

  (defun jw-visit-source ()
    "If the current line contains text like '../src/program.rb:34', visit 
  that file in the other window and position point on that line." 
    (interactive)
    (let* ((line (jw-current-line))
           (candidates (jw-extract-file-lines line))
           (file-line (jw-select-file-line candidates)))
      (cond (file-line
             (find-file-other-window (car file-line))
             (goto-line (cadr file-line)) )
            (t 
             (error "No source location on line.")) )))

blog comments powered by Disqus

 

Formatted: 16-May-12 21:53
Feedback: jim@weirichhouse.org