#!/usr/bin/env ruby
require 'yaml'
HELP = <<-EOH
*j* [*-@*_mark_|_mark_|*--list*|*--help*]
*j* *@*_mark_ _path_
Bookmark your favorite directories.
--list: list your current available marks.
--help: show this help message.
*j* _mark_: jumps to a mark.
*j* *@*_mark_ _path_: add a mark to path (path will be expanded).
*j* *-@*_mark_: remove a mark.
Marks must be composed of alphanumerical characters and underscores/dashes.
When you jump to a mark, you can append a trailing folder like this:
*j* _mark_/foo
and j will append foo to the resolved mark.
This program is WTFPL-licensed, see the LICENSE file distributed with it.
EOH
HELP.gsub! /(_|\*)([@a-z_-]+)(?:_|\*)/ do
[$~[1][0..0].eql?("*") ? "\e[1m" : "\e[4m" , $~[2], "\e[0m"].join('')
end
MARKS = File.expand_path("~/.jumprc")
class Jumpr
class << self
def load(file)
@rc = file
@marks = YAML.load(File.read(file)) || {}
end
def add(mark, target)
@marks[mark] = File.expand_path(target)
dump
end
def remove(mark)
if @marks.delete(mark)
dump
puts "Deleted mark #{mark}"
else
puts "No such mark #{mark}"
end
end
def jump(expr, rest="")
expr = Regexp.new(expr, Regexp::IGNORECASE)
matches = @marks.select {|k,v| k =~ expr }
if matches.size.zero?
puts "No matches."
elsif matches.size == 1
puts File.join(matches.first.last, *rest)
exit 0
else
puts "Multiple matches:"
list_matches(matches)
end
end
def list
list_matches(@marks)
end
private
def dump
File.open(@rc, "w+") {|f| f.write YAML.dump(@marks) }
end
def list_matches(matches)
matches.each do |mark,target|
puts "#{mark}: #{target}"
end
end
end
end
begin
File.open(MARKS, "w+") {|f| f.write "--- {}"} unless File.exist? MARKS
Jumpr.load(MARKS)
if ARGV[0] && mark = ARGV[0].dup
case mark
when /^@(?:(?:\w|[_-])+)$/
target = ARGV[1] || "."
mark.slice!(0)
Jumpr.add(mark, target)
puts "Added #{File.expand_path(target)} as #{mark}"
when /^-@.+/
mark.slice!(0..1)
Jumpr.remove(mark)
when /^--list$/
Jumpr.list
when /^--help$/
puts HELP
else
mark, *rest = mark.split("/")
Jumpr.jump(mark, rest)
end
else
raise ArgumentError, HELP.lines.to_a[0..1]
end
rescue => e
puts e.message
end
exit 1