Skip to content

Commit

Permalink
Hello
Browse files Browse the repository at this point in the history
  • Loading branch information
zimbatm committed Jul 3, 2015
0 parents commit b4fcbf4
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 0 deletions.
22 changes: 22 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
(The MIT License)

Copyright (c) 2014 zimbatm and
[contributors](https://github.com/zimbatm/h/graphs/contributors)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the 'Software'), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# `h` - faster shell navigation of projects

`h` is a small shell utility that I use every day to jump between projects quickly. It is complimentary to the amazing j
([autojump](https://github.com/joelthelion/autojump)) project and both help me
improve my workflow.

`h` is designed to work with a secific filesystem structure where all code is
checked-out in `~/code/<domain>/<path>`. Eg: `~/code/github.com/zimbatm/h` for
this project. This allows to not have to think about project locality.

The goal is that `h h` would find and cd into `~/code/github.com/zimbatm/h` if
it exists. When using the `h zimbatm/h` form it would look for the specific
folder or clone the repo from github. In both cases you will end-up changing
directory in the repo that you want to access. This allows to quickly access
existing and new project.

If projects don't live on github then their full git url can be provided to
clone into `~/code/<domain>/<path>`.

## Usage

`h --setup` prints shell code that setups the alias (see [Installation](#Installation))

`h <name>` searches for a project called `<name>` where `<name>` matches
`^\w\.\-$`. The search is done up to 3 levels deep and the longest match is
returned. If a result is found the path is printed on stdout. The
current directory is printed on stdout.

`h <user>/<repo>` looks for a `~/code/github.com/<user>/<repo>` folder or
clones it from github. The path is output on stdout if the repo exists or has
been cloned successfully. The current directory is printed on stdout
otherwise.

`h <url>` looks for a `~/code/<domain>/<path>` folder or clones it with git.
The path is output on stdout if the repo exists or has been cloned
successfully. The current directory is printed on stdout otherwise.

## Installation

Copy the `h` ruby script to somewhere in the PATH.

In your `~/.zshrc | ~/.bashrc | ..` add the following line:

```bash
eval "$(h --setup)"
```

This installs something really similar to `alias h='cd "$(h "$@")"`

## See also

* [autojump](https://github.com/joelthelion/autojump)
* [hub](https://hub.github.com/)
* [direnv](http://direnv.net/)

## License

MIT - (c) 2015 zimbatm and contributors


97 changes: 97 additions & 0 deletions h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#!/usr/bin/env ruby
#
# Usage: h <term>
#
# term can be of form [\w-]+ for search
# <user>/<repo> for github repos
# url for cloning

require 'find'
require 'pathname'
require 'uri'

# TODO: make that configurable
CODE_ROOT = Pathname.new('~/code').expand_path

def abort(*)
puts Dir.pwd
super
end

abort "Usage: h (--setup | <term>)" unless ARGV.size > 0

term = ARGV[0]
path = nil
url = nil

case term
when "--setup"
puts <<-SH
h() {
_h_dir=$(command h "$@")
_h_ret=$?
[ "$_h_dir" != "$PWD" ] && cd "$_h_dir"
return $_h_ret
}
SH
exit
when %r[\A([\w\.\-]+)/([\w\.\-]+)\z] # github user/repo
url = URI.parse("https://github.com/#{$1}/#{$2}.git")
path = CODE_ROOT.join('github.com', $1, $2)
when %r[://] # URL
url = URI.parse(term)
path = CODE_ROOT.join(url.host, url.path[1..-1])
abort "Missing url scheme" unless url.scheme
when %r[\Agit@([^:]+):(.*)] # git url
url = term
path = CODE_ROOT.join($1, $2)
when %r[\A[\w\.\-]+\z] # just search for repo
path_depth = 0

# Find all matches
CODE_ROOT.find do |curpath|
next unless curpath.directory?

depth = curpath.to_s.sub(CODE_ROOT.to_s, '').split('/').size

# Select deepest result
if curpath.basename.to_s == term && depth > path_depth
path = curpath
path_depth = depth
end

# Don't search below 4
Find.prune if depth > 3
end
else
abort "Unknown pattern for #{term}"
end

abort "#{term} not found" unless path

# Remove .git to path
path = path.sub_ext('') if path.extname == '.git'

unless path.directory?
# Keep note of the existing path
parent = path.parent
dir = parent
dir = dir.parent until dir.directory? || dir.root?
# Make sure the parent directory exists
parent.mkpath
unless system(
'git', 'clone', '--recursive', url.to_s, path.to_s,
out: :err,
close_others: true,
)
# Cleanup the parent directory if created
until parent == dir
parent.rmdir
parent = parent.parent
end

exit $?.exitstatus
end
end

puts path

0 comments on commit b4fcbf4

Please sign in to comment.