alias_metrics 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +27 -0
- data/README +49 -0
- data/Rakefile +11 -0
- data/alias_metrics.gemspec +13 -0
- data/bin/alias_metrics +27 -0
- data/gems/alias_metrics-0.1.gem +0 -0
- data/lib/alias_metrics.rb +4 -0
- data/lib/alias_metrics/alias_list.rb +89 -0
- data/lib/alias_metrics/alias_usage.rb +13 -0
- data/lib/alias_metrics/command_history.rb +79 -0
- data/lib/alias_metrics/shortenable.rb +11 -0
- data/spec/alias_list_spec.rb +50 -0
- data/spec/command_history_spec.rb +70 -0
- metadata +95 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.3)
|
5
|
+
fuubar (1.0.0)
|
6
|
+
rspec (~> 2.0)
|
7
|
+
rspec-instafail (~> 0.2.0)
|
8
|
+
ruby-progressbar (~> 0.0.10)
|
9
|
+
rake (0.9.2.2)
|
10
|
+
rspec (2.8.0)
|
11
|
+
rspec-core (~> 2.8.0)
|
12
|
+
rspec-expectations (~> 2.8.0)
|
13
|
+
rspec-mocks (~> 2.8.0)
|
14
|
+
rspec-core (2.8.0)
|
15
|
+
rspec-expectations (2.8.0)
|
16
|
+
diff-lcs (~> 1.1.2)
|
17
|
+
rspec-instafail (0.2.2)
|
18
|
+
rspec-mocks (2.8.0)
|
19
|
+
ruby-progressbar (0.0.10)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
fuubar (~> 1.0.0)
|
26
|
+
rake (~> 0.9.2.2)
|
27
|
+
rspec (~> 2.0)
|
data/README
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
This tool is to visualize alias usage to parse command history. You can evaluate whether you use alias efficiently or not.
|
2
|
+
* It can show reduced types and more redusable types
|
3
|
+
* It can show how degree you use each alias
|
4
|
+
|
5
|
+
The visabliable shell scripts is the followings:
|
6
|
+
* zsh (${HOME}/.zsh-history)
|
7
|
+
|
8
|
+
|
9
|
+
How to use:
|
10
|
+
|
11
|
+
$ alias | alias_metrics
|
12
|
+
|
13
|
+
|
14
|
+
Case Study:
|
15
|
+
|
16
|
+
$ alias | alias_metrics
|
17
|
+
>>
|
18
|
+
|
19
|
+
You reduce 10.25% types (29814 / 290970)
|
20
|
+
|
21
|
+
If you use alias all, you can reduce more 3.98% types (11575 / 290970)
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
You often forget the following alias
|
26
|
+
|
27
|
+
alias #used #forgot forgot rate(%) command
|
28
|
+
|
29
|
+
g 9 1530 99.42 git
|
30
|
+
|
31
|
+
_ 0 210 100.00 sudo
|
32
|
+
|
33
|
+
gco 24 197 89.14 git checkout
|
34
|
+
|
35
|
+
ga 516 190 26.91 git add
|
36
|
+
|
37
|
+
...
|
38
|
+
<<
|
39
|
+
I regist alias g=`git`, but I often forgot to use this alias. This result show I typed "git" 1530 times. So I can reduce 1530 * 2 = 3060 types by typing "g" instead of "git".
|
40
|
+
|
41
|
+
|
42
|
+
Todo:
|
43
|
+
|
44
|
+
* It can parse other shell scrpt(bash, csh, etc...)
|
45
|
+
* Add the function that recommends alias that can reduce your types by setting it
|
46
|
+
* Add the function that show Gold Standard
|
47
|
+
* Acceleration
|
48
|
+
|
49
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = 'alias_metrics'
|
3
|
+
spec.version = '0.1'
|
4
|
+
spec.summary = "This tool is to visualize alias usage to parse command history. You can evaluate whether you use alias efficiently or not."
|
5
|
+
spec.author = ["Kohei Tomita"]
|
6
|
+
spec.email = "tommy.fmale@gmail.com"
|
7
|
+
spec.executables = %w(alias_metrics)
|
8
|
+
spec.files = `git ls-files`.split("\n") rescue ''
|
9
|
+
spec.homepage = "https://github.com/tomity/alias_metrics"
|
10
|
+
spec.add_development_dependency 'rspec', '~> 2.0'
|
11
|
+
spec.add_development_dependency 'fuubar', "~> 1.0.0"
|
12
|
+
spec.add_development_dependency "rake", "~> 0.9.2.2"
|
13
|
+
end
|
data/bin/alias_metrics
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
lib = File.dirname(__FILE__) + '/../lib/'
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
require "alias_metrics"
|
5
|
+
|
6
|
+
@alias_list = AliasList.load_from_stdin
|
7
|
+
@history = CommandHistory.load_from_zsh_history(@alias_list)
|
8
|
+
command_length_all = @history.commands.map{|command| command.size}.inject(0){|partial_sum, size| partial_sum + size}
|
9
|
+
shorten_count = @history.shorten_count
|
10
|
+
shorten_rate = shorten_count.to_f / command_length_all
|
11
|
+
shortenable_count_all = @history.shortenables.values.inject(0){|partial_sum, shortenable| partial_sum + shortenable.count * [0, (shortenable.command.size - shortenable.alias.size)].max }
|
12
|
+
shortenable_rate = shortenable_count_all.to_f / command_length_all
|
13
|
+
|
14
|
+
puts "You reduce #{sprintf("%0.2f", shorten_rate * 100)}% types (#{shorten_count} types/ #{command_length_all} types)"
|
15
|
+
puts "If you use alias all, you can reduce more #{sprintf("%0.2f", shortenable_rate * 100)}% types (#{shortenable_count_all} types / #{command_length_all} types)"
|
16
|
+
puts
|
17
|
+
|
18
|
+
puts "You often forget the following alias"
|
19
|
+
puts "alias\t#used\t#forgot\tforgot rate(%)\tcommand"
|
20
|
+
keys = @history.shortenables.keys.sort{|a, b| @history.shortenables[a].count <=> @history.shortenables[b].count }.reverse
|
21
|
+
keys.each do |key|
|
22
|
+
shortenable = @history.shortenables[key]
|
23
|
+
alias_usage = @history.alias_usages[shortenable.alias]
|
24
|
+
forgot_rate = shortenable.count.to_f / (alias_usage.count + shortenable.count)
|
25
|
+
puts "#{shortenable.alias}\t#{alias_usage.count}\t#{shortenable.count}\t#{sprintf("%0.2f", forgot_rate*100)}\t#{shortenable.command}"
|
26
|
+
end
|
27
|
+
|
Binary file
|
@@ -0,0 +1,89 @@
|
|
1
|
+
class AliasList
|
2
|
+
attr_accessor :alias_hash
|
3
|
+
|
4
|
+
def self.load_from_lines(lines)
|
5
|
+
alias_hash = Hash::new
|
6
|
+
lines.each do |line|
|
7
|
+
key, value = separate_key_value_from_alias_line(line)
|
8
|
+
alias_hash[key] = value
|
9
|
+
end
|
10
|
+
AliasList.new(alias_hash)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.load_from_stdin
|
14
|
+
alias_hash = Hash::new
|
15
|
+
STDIN.each do |line|
|
16
|
+
line.chomp!
|
17
|
+
key, value = separate_key_value_from_alias_line(line)
|
18
|
+
alias_hash[key] = value
|
19
|
+
end
|
20
|
+
AliasList.new(alias_hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
#NOTE: Since #command >> #alias, this process do fastly
|
24
|
+
def expand_command(command)
|
25
|
+
@alias_hash.each_pair do |key, value|
|
26
|
+
if used_subcommand?(command, key)
|
27
|
+
command = command.sub(key, value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
command
|
31
|
+
end
|
32
|
+
|
33
|
+
#NOTE: Since #command >> #alias, this process do fastly
|
34
|
+
def applied_alias(command)
|
35
|
+
ret = []
|
36
|
+
@alias_hash.each_pair do |key, value|
|
37
|
+
if used_subcommand?(command, key)
|
38
|
+
command = command.sub(key, value)
|
39
|
+
ret << [key, value]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
ret
|
43
|
+
end
|
44
|
+
|
45
|
+
#NOTE: Since #command >> #alias, this process do fastly
|
46
|
+
def shortenable?(command)
|
47
|
+
@alias_hash.values.each do |value|
|
48
|
+
if used_subcommand?(command, value)
|
49
|
+
return true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
def shortenable_alias(command)
|
56
|
+
ret = []
|
57
|
+
@alias_hash.each_pair do |key, value|
|
58
|
+
if used_subcommand?(command, value)
|
59
|
+
ret << [key, value]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
ret
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def initialize(alias_hash)
|
68
|
+
@alias_hash = alias_hash.freeze
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.separate_key_value_from_alias_line(line)
|
72
|
+
key, value = line.split(/=/)
|
73
|
+
value = remove_single_quotes(value)
|
74
|
+
[key, value]
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.remove_single_quotes(value)
|
78
|
+
if value[0, 1] == "'" and value[-1, 1] == "'"
|
79
|
+
value = value[1..-2]
|
80
|
+
end
|
81
|
+
value
|
82
|
+
end
|
83
|
+
|
84
|
+
def used_subcommand?(command, alias_)
|
85
|
+
command == alias_ || command.start_with?(alias_+ " ")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class CommandHistory
|
2
|
+
attr_accessor :commands
|
3
|
+
attr_accessor :shorten_count
|
4
|
+
attr_accessor :shortenables
|
5
|
+
attr_accessor :alias_usages
|
6
|
+
attr_accessor :alias_list
|
7
|
+
|
8
|
+
ZSH_HISTORY_FILE = "#{ENV["HOME"]}/.zsh_history"
|
9
|
+
|
10
|
+
def initialize(commands, alias_list)
|
11
|
+
self.alias_list = alias_list
|
12
|
+
self.commands = []
|
13
|
+
self.shorten_count = 0
|
14
|
+
self.shortenables = Hash.new
|
15
|
+
self.alias_usages = Hash.new
|
16
|
+
alias_list.alias_hash.each_pair do |alias_, value|
|
17
|
+
self.alias_usages[alias_] = AliasUsage.new(alias_, value)
|
18
|
+
self.shortenables[value] = Shortenable.new(alias_, value)
|
19
|
+
end
|
20
|
+
|
21
|
+
commands.each do |command|
|
22
|
+
update_shortenables(command)
|
23
|
+
update_alias_usages(command)
|
24
|
+
command_expanded = self.alias_list.expand_command(command)
|
25
|
+
self.shorten_count += [0, command_expanded.length - command.length].max
|
26
|
+
self.commands << command_expanded
|
27
|
+
end
|
28
|
+
self.alias_list = self.alias_list.freeze
|
29
|
+
self.commands = self.commands.freeze
|
30
|
+
self.shorten_count = self.shorten_count.freeze
|
31
|
+
self.shortenables = self.shortenables.freeze
|
32
|
+
self.alias_usages = self.alias_usages.freeze
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.load_from_zsh_history(alias_list, history_file = ZSH_HISTORY_FILE)
|
36
|
+
commands = []
|
37
|
+
open(history_file) do |fh|
|
38
|
+
fh.each do |line|
|
39
|
+
line.chomp!
|
40
|
+
next if line == ""
|
41
|
+
begin
|
42
|
+
command = parse_command_by_zsh_history_line(line)
|
43
|
+
commands << command if command
|
44
|
+
rescue ArgumentError #invalid byte sequence in UTF-8
|
45
|
+
#do nothing
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
CommandHistory.new(commands, alias_list)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def self.parse_command_by_zsh_history_line(line)
|
55
|
+
command = line.split(/;/)[1]
|
56
|
+
return command
|
57
|
+
end
|
58
|
+
|
59
|
+
def update_shortenables(command)
|
60
|
+
if alias_list.shortenable?(command)
|
61
|
+
shortenable_alias_list = alias_list.shortenable_alias(command)
|
62
|
+
shortenable_alias_list.each do |alias_, extension|
|
63
|
+
self.shortenables[extension].count += 1 if shortenable?(alias_, extension)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def update_alias_usages(command)
|
69
|
+
applied_alias = self.alias_list.applied_alias(command)
|
70
|
+
applied_alias.each do |alias_, value|
|
71
|
+
self.alias_usages[alias_].count += 1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def shortenable?(alias_, command)
|
76
|
+
command.size > alias_.size
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "alias_metrics"
|
2
|
+
|
3
|
+
describe AliasList do
|
4
|
+
before do
|
5
|
+
@alias_list = AliasList.load_from_lines(["l='ls -la'", "sl=ls", "grhh='git reset --hard HEAD\^'"])
|
6
|
+
end
|
7
|
+
describe "expand_command" do
|
8
|
+
it "should output `ls -la` for the command `l` " do
|
9
|
+
@alias_list.expand_command("l").should == "ls -la"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should output `ls -la -h` for the command `l -h` " do
|
13
|
+
@alias_list.expand_command("l -h").should == "ls -la -h"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should output `ls` for the command `sl` " do
|
17
|
+
@alias_list.expand_command("sl").should == "ls"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should output `ls -l` for the command `sl -l` " do
|
21
|
+
@alias_list.expand_command("sl -l").should == "ls -l"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should output `slope` for the command `slope` because this command is slope, but is not sl" do
|
25
|
+
@alias_list.expand_command("slope").should == "slope"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "shortenable" do
|
30
|
+
it "should output `ls -la` is shortenable" do
|
31
|
+
@alias_list.shortenable?("ls -la").should == true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should output `ls -la -h` for the command `l -h` " do
|
35
|
+
@alias_list.shortenable?("ls -la -h").should == true
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should output `git reset --hard` is not shortenable" do
|
39
|
+
@alias_list.shortenable?("git reset --hard").should == false
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should output `git HEAD\^ --hard` is not shortenable" do #Is this specification correct?
|
43
|
+
@alias_list.shortenable?("git reset HEAD\^ --hard").should == false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "alias_metrics"
|
2
|
+
|
3
|
+
describe CommandHistory do
|
4
|
+
before do
|
5
|
+
@alias_list = AliasList.load_from_lines(["l='ls -la'", "ga=git add", "run-help=man"])
|
6
|
+
@history = CommandHistory.new(["l", "l -h", "ls -la", "ls -la -h", "man"], @alias_list)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "can get the number of commands" do
|
10
|
+
@history.commands.size.should == 5
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can count the number of chars shorten" do
|
14
|
+
@history.shorten_count.should == 10 #becaulse (`ls -la` => `l`) * 2
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should be count is 2 when ls -la" do
|
18
|
+
shortenable = @history.shortenables["ls -la"]
|
19
|
+
shortenable.alias.should == "l"
|
20
|
+
shortenable.command.should == "ls -la"
|
21
|
+
shortenable.count.should == 2
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should be count is 0 when git add" do
|
25
|
+
shortenable = @history.shortenables["git add"]
|
26
|
+
shortenable.alias.should == "ga"
|
27
|
+
shortenable.command.should == "git add"
|
28
|
+
shortenable.count.should == 0
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should be count is 0 when ls -la because run-help is longer than man" do
|
32
|
+
shortenable = @history.shortenables["man"]
|
33
|
+
shortenable.alias.should == "run-help"
|
34
|
+
shortenable.command.should == "man"
|
35
|
+
shortenable.count.should == 0
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should be alias usage is 2 when l" do
|
39
|
+
alias_usage = @history.alias_usages["l"]
|
40
|
+
alias_usage.alias.should == "l"
|
41
|
+
alias_usage.command.should == "ls -la"
|
42
|
+
alias_usage.count.should == 2
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should be alias usage is 0 when ga" do
|
46
|
+
alias_usage = @history.alias_usages["ga"]
|
47
|
+
alias_usage.alias.should == "ga"
|
48
|
+
alias_usage.command.should == "git add"
|
49
|
+
alias_usage.count.should == 0
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should be alias usage is 0 when run-help" do
|
53
|
+
alias_usage = @history.alias_usages["run-help"]
|
54
|
+
alias_usage.alias.should == "run-help"
|
55
|
+
alias_usage.command.should == "man"
|
56
|
+
alias_usage.count.should == 0
|
57
|
+
end
|
58
|
+
|
59
|
+
it "can load from ~/.zsh_history" do
|
60
|
+
CommandHistory.load_from_zsh_history(@alias_list)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should store expanded commands" do
|
64
|
+
@history.commands[0].should == "ls -la"
|
65
|
+
@history.commands[1].should == "ls -la -h"
|
66
|
+
@history.commands[2].should == "ls -la"
|
67
|
+
@history.commands[3].should == "ls -la -h"
|
68
|
+
@history.commands[4].should == "man"
|
69
|
+
end
|
70
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: alias_metrics
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kohei Tomita
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &2152591180 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2152591180
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: fuubar
|
27
|
+
requirement: &2152590180 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2152590180
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &2152608520 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.9.2.2
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2152608520
|
47
|
+
description:
|
48
|
+
email: tommy.fmale@gmail.com
|
49
|
+
executables:
|
50
|
+
- alias_metrics
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- .rspec
|
56
|
+
- Gemfile
|
57
|
+
- Gemfile.lock
|
58
|
+
- README
|
59
|
+
- Rakefile
|
60
|
+
- alias_metrics.gemspec
|
61
|
+
- bin/alias_metrics
|
62
|
+
- gems/alias_metrics-0.1.gem
|
63
|
+
- lib/alias_metrics.rb
|
64
|
+
- lib/alias_metrics/alias_list.rb
|
65
|
+
- lib/alias_metrics/alias_usage.rb
|
66
|
+
- lib/alias_metrics/command_history.rb
|
67
|
+
- lib/alias_metrics/shortenable.rb
|
68
|
+
- spec/alias_list_spec.rb
|
69
|
+
- spec/command_history_spec.rb
|
70
|
+
homepage: https://github.com/tomity/alias_metrics
|
71
|
+
licenses: []
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 1.8.10
|
91
|
+
signing_key:
|
92
|
+
specification_version: 3
|
93
|
+
summary: This tool is to visualize alias usage to parse command history. You can evaluate
|
94
|
+
whether you use alias efficiently or not.
|
95
|
+
test_files: []
|