huffshell 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/Gemfile.lock +26 -0
- data/Rakefile +6 -0
- data/Readme.md +34 -0
- data/bin/huffshell +14 -0
- data/lib/command/command_suggestion.rb +42 -0
- data/lib/command/command_suggestor.rb +24 -0
- data/lib/command/command_word.rb +11 -0
- data/lib/huffshell.rb +13 -0
- data/lib/readers/oh_my_zsh_reader.rb +35 -0
- data/lib/shell/alias_checker.rb +18 -0
- data/lib/shell/alias_line.rb +16 -0
- data/lib/shell/binary_checker.rb +11 -0
- data/lib/shell/script_line.rb +27 -0
- data/lib/tree/word_tree.rb +21 -0
- data/lib/tree/word_tree_node.rb +68 -0
- metadata +62 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
huffshell (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
colorize (0.5.8)
|
10
|
+
diff-lcs (1.1.3)
|
11
|
+
rspec (2.10.0)
|
12
|
+
rspec-core (~> 2.10.0)
|
13
|
+
rspec-expectations (~> 2.10.0)
|
14
|
+
rspec-mocks (~> 2.10.0)
|
15
|
+
rspec-core (2.10.1)
|
16
|
+
rspec-expectations (2.10.0)
|
17
|
+
diff-lcs (~> 1.1.3)
|
18
|
+
rspec-mocks (2.10.1)
|
19
|
+
|
20
|
+
PLATFORMS
|
21
|
+
ruby
|
22
|
+
|
23
|
+
DEPENDENCIES
|
24
|
+
colorize
|
25
|
+
huffshell!
|
26
|
+
rspec
|
data/Rakefile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
HuffShell
|
2
|
+
====================
|
3
|
+
|
4
|
+
HuffShell is a gem for optimizing your ZSH aliases, programtically.
|
5
|
+
|
6
|
+
The gems looks at your history which can be automatically stored and generates aliases based on your usage. Your history is used to determine what you use the most and generate the shortest commands based on usage.
|
7
|
+
|
8
|
+
For example, you use 'git' 500 times and you use 'ls -l' 100 times. You should add aliases that are 'g' and 'll'. It could save you hundreds of keystokes.
|
9
|
+
|
10
|
+
In order to do that, huffshell generates stats of your usage and gives them to you, as you might hope.
|
11
|
+
|
12
|
+
Features
|
13
|
+
---------------------
|
14
|
+
|
15
|
+
* Alias suggestion based on history.
|
16
|
+
* Examines your system for binaries and aliases and avoids reassigning them.
|
17
|
+
* Huffman inspired symbol generation.
|
18
|
+
* Handy gem packaging.
|
19
|
+
* Works out of the box with oh-my-zsh.
|
20
|
+
|
21
|
+
Installation
|
22
|
+
---------------------
|
23
|
+
|
24
|
+
```script
|
25
|
+
# install it
|
26
|
+
gem install huffman
|
27
|
+
|
28
|
+
# need to be able to access this from the gem
|
29
|
+
alias > ~/.aliases.cache
|
30
|
+
huffshell
|
31
|
+
|
32
|
+
# cleanup
|
33
|
+
alias > ~/.aliases.cache
|
34
|
+
```
|
data/bin/huffshell
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'huffshell'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
cs = CommandSuggestor.new
|
7
|
+
history_filename = '~/.zsh_history'
|
8
|
+
|
9
|
+
OhMyZshReader.new(history_filename).
|
10
|
+
shell_commands.
|
11
|
+
each{ |l| cs.add(l) }
|
12
|
+
|
13
|
+
cs.truncate!(30)
|
14
|
+
puts cs.to_print
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
|
3
|
+
class CommandSuggestion
|
4
|
+
attr_accessor :wordlist
|
5
|
+
|
6
|
+
SHORT_ENOUGH = 3
|
7
|
+
|
8
|
+
def initialize(wordlist)
|
9
|
+
@wordlist = wordlist
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
if exists?
|
14
|
+
"'#{command}' => #{abbreviation} taken :("
|
15
|
+
else
|
16
|
+
"'#{command}' => " + "#{abbreviation}".green
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def abbreviation
|
21
|
+
wordlist.map{|w| CommandWord.suggested_letter(w) }.join.downcase
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def command
|
27
|
+
wordlist.join(" ")
|
28
|
+
end
|
29
|
+
|
30
|
+
def exists?
|
31
|
+
binary_checker.exist? || alias_checker.exist?(abbreviation)
|
32
|
+
end
|
33
|
+
|
34
|
+
def binary_checker
|
35
|
+
BinaryChecker.new(abbreviation)
|
36
|
+
end
|
37
|
+
|
38
|
+
def alias_checker
|
39
|
+
AliasChecker.new("~/.aliases.cache")
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class CommandSuggestor
|
2
|
+
attr_accessor :wordtree
|
3
|
+
|
4
|
+
def initialize()
|
5
|
+
@wordtree = WordTree.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(line)
|
9
|
+
sl = ScriptLine.new(line)
|
10
|
+
return unless sl.valid?
|
11
|
+
wordtree.add(sl)
|
12
|
+
end
|
13
|
+
|
14
|
+
def truncate!(minimum)
|
15
|
+
wordtree.root.truncate!(minimum)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_print
|
19
|
+
wordtree.root.map do |n|
|
20
|
+
cs = CommandSuggestion.new(n.word_list)
|
21
|
+
"#{n.to_print.chomp} #{cs.to_s}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/huffshell.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'readers/oh_my_zsh_reader'
|
2
|
+
|
3
|
+
require 'command/command_word'
|
4
|
+
require 'command/command_suggestor'
|
5
|
+
require 'command/command_suggestion'
|
6
|
+
|
7
|
+
require 'shell/alias_line'
|
8
|
+
require 'shell/script_line'
|
9
|
+
require 'shell/alias_checker'
|
10
|
+
require 'shell/binary_checker'
|
11
|
+
|
12
|
+
require 'tree/word_tree'
|
13
|
+
require 'tree/word_tree_node'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'iconv' unless String.method_defined?(:encode)
|
2
|
+
|
3
|
+
class OhMyZshReader
|
4
|
+
attr_accessor :file_name, :file_contents
|
5
|
+
|
6
|
+
def initialize(file_name)
|
7
|
+
@file_name = file_name
|
8
|
+
@file_contents = File.open(File.expand_path(file_name), 'r').read
|
9
|
+
|
10
|
+
if String.method_defined?(:encode)
|
11
|
+
@file_contents.encode!('UTF-8', 'UTF-8', :invalid => :replace)
|
12
|
+
else
|
13
|
+
ic = Iconv.new('UTF-8', 'UTF-8//IGNORE')
|
14
|
+
@file_contents = ic.iconv(@file_contents)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def shell_commands
|
19
|
+
filtered_lines.map {|l| l.split(";").last.strip }
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def filtered_lines
|
25
|
+
raw_lines(file_contents).select{|l| valid_line?(l) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid_line?(line)
|
29
|
+
line[0] == ":"
|
30
|
+
end
|
31
|
+
|
32
|
+
def raw_lines(file_contents)
|
33
|
+
file_contents.split("\n")
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class AliasChecker
|
2
|
+
attr_accessor :filename, :aliases
|
3
|
+
|
4
|
+
def initialize(filename)
|
5
|
+
@filename = filename
|
6
|
+
file_contents = File.open(File.expand_path(filename), 'r').read
|
7
|
+
lines = file_contents.split("\n")
|
8
|
+
@aliases = {}
|
9
|
+
lines.each do |l|
|
10
|
+
al = AliasLine.new(l)
|
11
|
+
@aliases[al.alias_name] = al.command
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def exist?(alias_name)
|
16
|
+
!!@aliases[alias_name]
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class ScriptLine
|
2
|
+
attr_accessor :line, :words, :clean_words
|
3
|
+
|
4
|
+
def initialize(l)
|
5
|
+
@line = l.strip
|
6
|
+
@words = l.split(/[ \t]+/)
|
7
|
+
@clean_words = @words.map{|w| CommandWord.clean(w) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def command
|
11
|
+
clean_words.first
|
12
|
+
end
|
13
|
+
|
14
|
+
def valid?
|
15
|
+
!(comment? || empty?)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def comment?
|
21
|
+
@line[0] == "#"
|
22
|
+
end
|
23
|
+
|
24
|
+
def empty?
|
25
|
+
@line.size == 0
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class WordTree
|
2
|
+
attr_accessor :root, :line_count
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@root = WordTreeNode.new
|
6
|
+
@line_count = 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(line)
|
10
|
+
@line_count += 1
|
11
|
+
root.add(line, 0)
|
12
|
+
end
|
13
|
+
|
14
|
+
def truncate!(minimum)
|
15
|
+
root.truncate!(minimum)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_print
|
19
|
+
root.to_print
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
|
3
|
+
class WordTreeNode
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
attr_accessor :word, :cleanword, :children, :line_count, :level, :parent
|
7
|
+
|
8
|
+
def initialize(word = nil, level = 0, parent = nil)
|
9
|
+
@word = word
|
10
|
+
@cleanword = CommandWord.clean(word) if word
|
11
|
+
@children = {}
|
12
|
+
@line_count = 0
|
13
|
+
@level = level
|
14
|
+
@parent = parent
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(line, level = 0)
|
18
|
+
word = line.words[level]
|
19
|
+
clean_word = line.clean_words[level]
|
20
|
+
@line_count += 1
|
21
|
+
return unless word
|
22
|
+
|
23
|
+
@children[word] ||= WordTreeNode.new(word, level + 1, self)
|
24
|
+
@children[word].add(line, level + 1)
|
25
|
+
end
|
26
|
+
|
27
|
+
def each &block
|
28
|
+
children.values.sort.each do |v|
|
29
|
+
block.call(v)
|
30
|
+
v.each do |q|
|
31
|
+
block.call(q)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def <=> b
|
37
|
+
b.line_count <=> line_count
|
38
|
+
end
|
39
|
+
|
40
|
+
def words
|
41
|
+
children.keys.uniq
|
42
|
+
end
|
43
|
+
|
44
|
+
def root?
|
45
|
+
word.nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
def truncate!(minimum)
|
49
|
+
children.select!{|k, v| v.line_count >= minimum }
|
50
|
+
children.each{|k, v| v.truncate!(minimum) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def word_list
|
54
|
+
list = [self.word]
|
55
|
+
node = self
|
56
|
+
while node = node.parent
|
57
|
+
next if node.word.nil?
|
58
|
+
list << node.word
|
59
|
+
end
|
60
|
+
list.reverse
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_print
|
64
|
+
return "" if root?
|
65
|
+
"#{("\t" * (level - 1))}" + "#{word}".green + " #{line_count}:\n"
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: huffshell
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Paul McKellar
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-18 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A parser and recommendation system for your shell aliases based on your
|
15
|
+
shell history
|
16
|
+
email: paul.mckellar@gmail.com
|
17
|
+
executables:
|
18
|
+
- huffshell
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- lib/command/command_suggestion.rb
|
23
|
+
- lib/command/command_suggestor.rb
|
24
|
+
- lib/command/command_word.rb
|
25
|
+
- lib/huffshell.rb
|
26
|
+
- lib/readers/oh_my_zsh_reader.rb
|
27
|
+
- lib/shell/alias_checker.rb
|
28
|
+
- lib/shell/alias_line.rb
|
29
|
+
- lib/shell/binary_checker.rb
|
30
|
+
- lib/shell/script_line.rb
|
31
|
+
- lib/tree/word_tree.rb
|
32
|
+
- lib/tree/word_tree_node.rb
|
33
|
+
- bin/huffshell
|
34
|
+
- Gemfile
|
35
|
+
- Gemfile.lock
|
36
|
+
- Rakefile
|
37
|
+
- Readme.md
|
38
|
+
homepage: http://rubygems.org/gems/huffshell
|
39
|
+
licenses: []
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.8.10
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: Automatic shell alias recommondations based on usage!
|
62
|
+
test_files: []
|