gitXplorer 1.0.0

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.
@@ -0,0 +1,48 @@
1
+ class GitXplorer::GitObject::File < GitXplorer::GitObject
2
+ def children
3
+ if (@kids.nil?)
4
+ # Initialize
5
+ @kids = Array.new
6
+
7
+ # Create git command
8
+ cmd = [
9
+ "git log --date=format-local:\"%F_%I:%M:%S_%P\"",
10
+ "--diff-filter=AC",
11
+ "--full-history",
12
+ "--pretty=tformat:\"{{%H}}{{%s}}{{%cd}}{{%an}}\"",
13
+ "--",
14
+ absolute_path
15
+ ].join(" ")
16
+
17
+ # Loop thru results creating a revision object for each
18
+ %x(#{cmd}).split("\n").each do |line|
19
+ line.match(/{{(.+)}}{{(.+)}}{{(.+)}}{{(.+)}}/) do |m|
20
+ @kids.push(
21
+ GitXplorer::GitObject::Revision.new(
22
+ m[1],
23
+ self,
24
+ m[2],
25
+ m[3],
26
+ m[4]
27
+ )
28
+ )
29
+ end
30
+ end
31
+ end
32
+
33
+ return @kids
34
+ end
35
+
36
+ def desc
37
+ return "#{newest.name} #{newest.date}" if (newest)
38
+ return nil
39
+ end
40
+
41
+ def initialize(name, parent)
42
+ super(name, parent)
43
+ end
44
+
45
+ def newest
46
+ return children[0]
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ class GitXplorer::GitObject::Revision < GitXplorer::GitObject
2
+ attr_reader :date
3
+ attr_reader :summary
4
+ attr_reader :user
5
+
6
+ def desc
7
+ return "#{@date} #{@user} #{@summary}"
8
+ end
9
+
10
+ def initialize(revision, parent, summary, date, user)
11
+ super(revision, parent)
12
+ @date = date
13
+ @summary = summary
14
+ @user = user
15
+ end
16
+
17
+ def tab_complete(color = false)
18
+ color ||= false
19
+ return {@name => @date}
20
+ end
21
+ end
@@ -0,0 +1,112 @@
1
+ class GitXplorer::GitObject
2
+ attr_reader :name
3
+ attr_reader :parent
4
+
5
+ def absolute_path
6
+ return "" if (@parent.nil?)
7
+ return [@parent.absolute_path, @name].join
8
+ end
9
+
10
+ def children
11
+ @kids ||= Array.new
12
+ return @kids
13
+ end
14
+
15
+ def desc
16
+ return ""
17
+ end
18
+
19
+ def exist?(path)
20
+ return !get(path).nil?
21
+ end
22
+
23
+ def get(path)
24
+ # Return self if path is nil or empty
25
+ return self if (path.nil? || path.empty?)
26
+
27
+ # Split path on /
28
+ child, recurse, grandchild = path.partition("/")
29
+ child, _, grandchild = path.partition(":") if (recurse.empty?)
30
+
31
+ case child
32
+ when "."
33
+ # Same directory
34
+ return self.get(grandchild)
35
+ when ".."
36
+ # Check parent if it exists
37
+ return @parent.get(grandchild) if (@parent)
38
+
39
+ # Otherwise we reached top-level so just keep going
40
+ return self.get(grandchild)
41
+ end
42
+
43
+ # Check child if it exists
44
+ if (has_child?(child))
45
+ kids = children.select do |kid|
46
+ kid.name == child
47
+ end
48
+ return kids[0].get(grandchild) if (!kids.empty?)
49
+ end
50
+
51
+ # Not found
52
+ return nil
53
+ end
54
+
55
+ def get_completions(path)
56
+ # Return all children if path is nil or empty
57
+ return children if (path.nil? || path.empty?)
58
+
59
+ # Split path on / or :
60
+ child, recurse, grandchild = path.partition("/")
61
+ if (recurse.empty?)
62
+ child, recurse, grandchild = path.partition(":")
63
+ end
64
+
65
+ case child
66
+ when "."
67
+ # Same directory
68
+ return get_completions(grandchild)
69
+ when ".."
70
+ # Check parent if it exists
71
+ return @parent.get_completions(grandchild) if (@parent)
72
+
73
+ # Otherwise we reached top-level so just keep going
74
+ return get_completions(grandchild)
75
+ end
76
+
77
+ # Check child if it exists
78
+ if (!recurse.empty? && has_child?(child))
79
+ return get(child).get_completions(grandchild)
80
+ end
81
+
82
+ # Return any children that may match
83
+ return children.select do |kid|
84
+ kid.name.downcase.start_with?(child.downcase)
85
+ end
86
+ end
87
+
88
+ def has_child?(name)
89
+ return children.any? do |child|
90
+ child.name == name
91
+ end
92
+ end
93
+
94
+ def initialize(name, parent)
95
+ @kids = nil
96
+ @name = name
97
+ @parent = parent
98
+ end
99
+
100
+ def tab_complete(color = false)
101
+ color ||= false
102
+ return {@name => desc}
103
+ end
104
+
105
+ def to_s
106
+ return @name
107
+ end
108
+ end
109
+
110
+ require "git_xplorer/git_object/directory"
111
+ require "git_xplorer/git_object/file"
112
+ require "git_xplorer/git_object/revision"
@@ -0,0 +1,40 @@
1
+ require "djinni"
2
+
3
+ class CatWish < Djinni::Wish
4
+ def aliases
5
+ return ["cat"]
6
+ end
7
+
8
+ def description
9
+ return "Display file contents"
10
+ end
11
+
12
+ def execute(args, djinni_env = Hash.new)
13
+ gitx = djinni_env["gitXplorer"]
14
+
15
+ begin
16
+ gitx.show(args)
17
+ rescue GitXplorer::Error => e
18
+ puts e.message
19
+ end
20
+ end
21
+
22
+ def tab_complete(input, djinni_env = Hash.new)
23
+ gitx = djinni_env["gitXplorer"]
24
+
25
+ _, found, partial = input.rpartition(":")
26
+ _, _, partial = input.rpartition("/") if (found.empty?)
27
+
28
+ completions = Hash.new
29
+ gitx.get_completions(input).each do |child|
30
+ completions.merge!(child.tab_complete)
31
+ end
32
+
33
+ return [completions, partial, ""]
34
+ end
35
+
36
+ def usage
37
+ puts "#{aliases.join(", ")} <file>"
38
+ puts " #{description}."
39
+ end
40
+ end
@@ -0,0 +1,44 @@
1
+ require "djinni"
2
+ require "hilighter"
3
+
4
+ class ChangeDirectoryWish < Djinni::Wish
5
+ def aliases
6
+ return ["cd"]
7
+ end
8
+
9
+ def description
10
+ return "Change to new directory"
11
+ end
12
+
13
+ def execute(args, djinni_env = Hash.new)
14
+ gitx = djinni_env["gitXplorer"]
15
+ begin
16
+ gitx.cd(args)
17
+ prompt = "#{gitx.pwd_short}$ ".light_white
18
+ djinni_env["djinni_prompt"] = prompt
19
+ rescue GitXplorer::Error => e
20
+ puts e.message
21
+ end
22
+ end
23
+
24
+ def tab_complete(input, djinni_env = Hash.new)
25
+ gitx = djinni_env["gitXplorer"]
26
+
27
+ _, _, partial = input.rpartition("/")
28
+ partial = "" if (input.end_with?("/"))
29
+
30
+ completions = Hash.new
31
+ gitx.get_completions(input).select do |child|
32
+ child.is_a?(GitXplorer::GitObject::Directory)
33
+ end.each do |child|
34
+ completions.merge!(child.tab_complete)
35
+ end
36
+
37
+ return [completions, partial, ""]
38
+ end
39
+
40
+ def usage
41
+ puts "#{aliases.join(", ")} [directory]"
42
+ puts " #{description}."
43
+ end
44
+ end
@@ -0,0 +1,28 @@
1
+ require "djinni"
2
+
3
+ class FindWish < Djinni::Wish
4
+ def aliases
5
+ return ["find"]
6
+ end
7
+
8
+ def description
9
+ return "Similar to \"find . -iregex PATTERN\""
10
+ end
11
+
12
+ def execute(args, djinni_env = Hash.new)
13
+ gitx = djinni_env["gitXplorer"]
14
+ args.gsub!(/^(["'])(.*)\1$/, "\\2")
15
+ dir = gitx.pwd.gsub(%r{^[^/]+(/|$)}, "")
16
+
17
+ begin
18
+ puts gitx.get_filenames(dir, args)
19
+ rescue GitXplorer::Error => e
20
+ puts e.message
21
+ end
22
+ end
23
+
24
+ def usage
25
+ puts "#{aliases.join(", ")} [PATTERN]"
26
+ puts " #{description}."
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require "djinni"
2
+
3
+ class GitWish < Djinni::Wish
4
+ def aliases
5
+ return ["git"]
6
+ end
7
+
8
+ def description
9
+ return "Run any git command"
10
+ end
11
+
12
+ def execute(args, djinni_env = Hash.new)
13
+ gitx = djinni_env["gitXplorer"]
14
+ begin
15
+ case args
16
+ when /^\s*(diff|ls-files|rev-parse|show|status).*/
17
+ puts gitx.git(args, false)
18
+ else
19
+ puts gitx.git(args)
20
+ end
21
+ rescue GitXplorer::Error => e
22
+ puts e.message
23
+ end
24
+ end
25
+
26
+ def usage
27
+ puts "#{aliases.join(", ")}"
28
+ puts " #{description}."
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ require "djinni"
2
+
3
+ class GrepWish < Djinni::Wish
4
+ def aliases
5
+ return ["grep"]
6
+ end
7
+
8
+ def description
9
+ return "Similar to \"git grep -HIinP PATTERN\""
10
+ end
11
+
12
+ def execute(args, djinni_env = Hash.new)
13
+ gitx = djinni_env["gitXplorer"]
14
+ args.gsub!(/^(["'])(.*)\1$/, "\\2")
15
+ dir = gitx.pwd.gsub(%r{^[^/]+(/|$)}, "")
16
+
17
+ if (args.empty?)
18
+ usage
19
+ return
20
+ end
21
+
22
+ begin
23
+ gitx.search(dir, args).each do |line|
24
+ m = line.match(/^([^:]+):([^:]+):(\d+):(.*)$/)
25
+ if (m && (m.length == 5))
26
+ puts [
27
+ m[1].green,
28
+ m[2].cyan,
29
+ m[3].white,
30
+ m[4].gsub(/(#{args})/i, "\\1".black.on_white)
31
+ ].join(":")
32
+ else
33
+ puts line
34
+ end
35
+ end
36
+ rescue GitXplorer::Error => e
37
+ puts e.message
38
+ end
39
+ end
40
+
41
+ def usage
42
+ puts "#{aliases.join(", ")} <PATTERN>"
43
+ puts " #{description}."
44
+ end
45
+ end
@@ -0,0 +1,93 @@
1
+ require "djinni"
2
+
3
+ class ListDirectoryWish < Djinni::Wish
4
+ def aliases
5
+ return ["ls", "ll"]
6
+ end
7
+
8
+ def description
9
+ return "List directory contents or file revisions"
10
+ end
11
+
12
+ def execute(args, djinni_env = Hash.new)
13
+ gitx = djinni_env["gitXplorer"]
14
+
15
+ long = false
16
+ case djinni_env["djinni_input"]
17
+ when "ll"
18
+ long = true
19
+ end
20
+ if (args.match(/(^| )(-l|--long)( |$)/))
21
+ args.gsub!(/(^| )(-l|--long)( |$)/, "")
22
+ long = true
23
+ end
24
+
25
+ begin
26
+ children = gitx.ls(args)
27
+ if (long)
28
+ long(children)
29
+ else
30
+ children.each do |child|
31
+ puts child
32
+ end
33
+ end
34
+ rescue GitXplorer::Error => e
35
+ puts e.message
36
+ end
37
+ end
38
+
39
+ def initialize
40
+ @space = 4
41
+ end
42
+
43
+ def long(children)
44
+ max = children.max_by do |child|
45
+ child.to_s.length
46
+ end.to_s.length
47
+ nlfill = " " * (max + @space)
48
+ width = %x(tput cols).to_i - (max + @space) - 2
49
+
50
+ children.each do |child|
51
+ name = child.to_s
52
+ desc = child.desc
53
+ fill = " " * (max + @space - name.length)
54
+ fill = "" if ((max + @space - name.length) <= 0)
55
+ lines = Array.new
56
+ if (desc)
57
+ lines = desc.scan(/\S.{0,#{width}}\S(?=\s|$)|\S+/)
58
+ end
59
+ if (lines.empty?)
60
+ puts name
61
+ else
62
+ start = lines.delete_at(0)
63
+ puts "#{name}#{fill}#{start}"
64
+ lines.each do |line|
65
+ puts "#{nlfill}#{line}"
66
+ end
67
+ end
68
+ end
69
+ end
70
+ private :long
71
+
72
+ def tab_complete(input, djinni_env = Hash.new)
73
+ gitx = djinni_env["gitXplorer"]
74
+
75
+ _, found, partial = input.rpartition(":")
76
+ _, _, partial = input.rpartition("/") if (found.empty?)
77
+
78
+ completions = Hash.new
79
+ gitx.get_completions(input).each do |child|
80
+ completions.merge!(child.tab_complete)
81
+ end
82
+
83
+ return [completions, partial, ""]
84
+ end
85
+
86
+ def usage
87
+ puts "#{aliases.join(", ")} [OPTIONS] [directory/file]"
88
+ puts " #{description}."
89
+ puts
90
+ puts "OPTIONS"
91
+ puts " -l, --long Show more info for files"
92
+ end
93
+ end
@@ -0,0 +1,24 @@
1
+ require "djinni"
2
+
3
+ class PwdWish < Djinni::Wish
4
+ def aliases
5
+ return ["pwd"]
6
+ end
7
+
8
+ def description
9
+ return "Show path of current path"
10
+ end
11
+
12
+ def execute(args, djinni_env = Hash.new)
13
+ if (!args.empty?)
14
+ usage
15
+ else
16
+ puts djinni_env["gitXplorer"].pwd
17
+ end
18
+ end
19
+
20
+ def usage
21
+ puts aliases.join(", ")
22
+ puts " #{description}."
23
+ end
24
+ end
@@ -0,0 +1,46 @@
1
+ require "djinni"
2
+
3
+ class ViWish < Djinni::Wish
4
+ def aliases
5
+ return ["vi", "view", "vim"]
6
+ end
7
+
8
+ def description
9
+ return "Open the file in vim"
10
+ end
11
+
12
+ def execute(args, djinni_env = Hash.new)
13
+ gitx = djinni_env["gitXplorer"]
14
+
15
+ readonly = false
16
+ case djinni_env["djinni_input"]
17
+ when "view"
18
+ readonly = true
19
+ end
20
+
21
+ begin
22
+ gitx.vim(args, readonly)
23
+ rescue GitXplorer::Error => e
24
+ puts e.message
25
+ end
26
+ end
27
+
28
+ def tab_complete(input, djinni_env = Hash.new)
29
+ gitx = djinni_env["gitXplorer"]
30
+
31
+ _, found, partial = input.rpartition(":")
32
+ _, _, partial = input.rpartition("/") if (found.empty?)
33
+
34
+ completions = Hash.new
35
+ gitx.get_completions(input).each do |child|
36
+ completions.merge!(child.tab_complete)
37
+ end
38
+
39
+ return [completions, partial, ""]
40
+ end
41
+
42
+ def usage
43
+ puts "#{aliases.join(", ")} <file>"
44
+ puts " #{description}."
45
+ end
46
+ end