replicant-adb 0.0.1 → 1.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.
@@ -0,0 +1,18 @@
1
+ class EnvCommand < Command
2
+
3
+ def valid_args?
4
+ args.blank?
5
+ end
6
+
7
+ def run
8
+ env = "Package: #{@repl.default_package || 'Not set'}\n"
9
+ env << "Device: "
10
+ device = @repl.default_device
11
+ env << if device
12
+ "#{device.name} (#{device.id})"
13
+ else
14
+ 'Not set'
15
+ end
16
+ output env
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ class ListCommand < Command
2
+ def valid_args?
3
+ args.blank?
4
+ end
5
+
6
+ def description
7
+ "print a list of available commands"
8
+ end
9
+
10
+ def run
11
+ command_list = Command.all.sort_by {|c| c.name}.map do |command|
12
+ padding = 20 - command.name.length
13
+ desc = "#{command.name} #{' ' * padding} -- #{command.description}"
14
+ desc
15
+ end
16
+ output command_list.join("\n")
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ class PackageCommand < Command
2
+
3
+ def description
4
+ "set a default package to work with"
5
+ end
6
+
7
+ def usage
8
+ "#{name} com.mydomain.mypackage"
9
+ end
10
+
11
+ def valid_args?
12
+ args.present? && /^\w+(\.\w+)*$/ =~ args
13
+ end
14
+
15
+ def run
16
+ output "Setting default package to #{args.inspect}"
17
+ @repl.default_package = args
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ class ResetCommand < Command
2
+
3
+ def description
4
+ "clear current device and package"
5
+ end
6
+
7
+ def valid_args?
8
+ args.blank?
9
+ end
10
+
11
+ def run
12
+ @repl.default_device = nil
13
+ @repl.default_package = nil
14
+ end
15
+
16
+ end
@@ -0,0 +1,13 @@
1
+ class RestartCommand < Command
2
+ def description
3
+ "restart ADB"
4
+ end
5
+
6
+ def run
7
+ # Faster than kill-server, and also catches ADB instances launched by
8
+ # IntelliJ. Moreover, start-server after kill-server sometimes makes the
9
+ # server fail to start up unless you sleep for a second or so
10
+ `killall adb`
11
+ AdbCommand.new(@repl, "start-server").execute
12
+ end
13
+ end
@@ -1,7 +1,8 @@
1
1
  class Device
2
- attr_reader :id, :name
2
+ attr_reader :idx, :id, :name
3
3
 
4
- def initialize(id, name)
4
+ def initialize(idx, id, name)
5
+ @idx = idx
5
6
  @id = id
6
7
  @name = name
7
8
  end
@@ -14,6 +15,10 @@ class Device
14
15
  !emulator?
15
16
  end
16
17
 
18
+ def short_name
19
+ "#{@name[0..4]}[#{@idx}]"
20
+ end
21
+
17
22
  def to_s
18
23
  "#{@id} [#{@name}]"
19
24
  end
@@ -0,0 +1,83 @@
1
+ class LogMuncher
2
+
3
+ include Styles
4
+
5
+ LOGFILE = "/tmp/replicant_device"
6
+ TIMESTAMP_PATTERN = /^\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\.\d{3}/
7
+ PROCESS_PATTERN = /(\w){1}\/(.*)\(\s*([0-9]+)\):\s/
8
+
9
+ attr_accessor :current_pid
10
+
11
+ def initialize(repl)
12
+ @repl = repl
13
+ @current_pid = nil
14
+ end
15
+
16
+ # Parses the device logs and reformats / recolors them
17
+ def munch_logs
18
+ logcat = "logcat -v time"
19
+
20
+ i = IO.popen(AdbCommand.new(@repl, logcat).command)
21
+ o = File.open(LOGFILE, 'wt')
22
+
23
+ yield o if block_given?
24
+
25
+ Thread.new do
26
+ begin
27
+ i.each_line do |line|
28
+ log_line(o, line)
29
+ end
30
+ rescue Exception => e
31
+ puts e.inspect
32
+ puts e.backtrace.join("\n")
33
+ raise e
34
+ end
35
+ end
36
+ end
37
+
38
+ private def log_line(o, line)
39
+ transform_line(line).each do |seg|
40
+ text = seg.first
41
+ styles = seg.last
42
+ o.print(create_style(*styles))
43
+ o.print(text)
44
+ o.print(end_style)
45
+ end
46
+ o.flush
47
+ end
48
+
49
+ private def transform_line(line)
50
+ segments = []
51
+
52
+ timestamp = line[TIMESTAMP_PATTERN]
53
+
54
+ if timestamp # found proper log line
55
+ process = PROCESS_PATTERN.match(line)
56
+ pid = process[3]
57
+
58
+ if @current_pid.nil? || @current_pid == pid
59
+ segments << [" #{timestamp} ", [:white_bg, :bold]]
60
+ # log level
61
+ level = process[1]
62
+ level_fg = case level
63
+ when "D" then :yellow_fg
64
+ when "E" then :red_fg
65
+ else :white_fg
66
+ end
67
+ segments << [" #{level} ", [:black_bg, :bold] << level_fg]
68
+ # log tag
69
+ tag = process[2].strip
70
+ segments << ["#{tag} ", [:black_bg, :cyan_fg, :bold]]
71
+ # log remaining line
72
+ remainder = [TIMESTAMP_PATTERN, PROCESS_PATTERN].reduce(line) { |l,r| l.gsub(r, '') }.strip
73
+ segments << [" #{remainder}\n", [:white_fg]]
74
+
75
+ elsif @repl.debug?
76
+ segments << [" #{timestamp} ", [:black_fg]]
77
+ segments << [" [muted]\n", [:black_fg]]
78
+ end
79
+ end
80
+ segments
81
+ end
82
+
83
+ end
@@ -0,0 +1,47 @@
1
+ class ProcessMuncher
2
+
3
+ def initialize(repl)
4
+ @repl = repl
5
+ end
6
+
7
+ def process_table
8
+ result = AdbCommand.new(@repl, "shell ps", :silent => true).execute
9
+ if result.code > 0
10
+ @signal_exit = true
11
+ {}
12
+ else
13
+ processes = result.output
14
+ # Parses something like:
15
+ # u0_a27 1333 123 517564 18668 ffffffff b75a59eb S com.android.musicfx
16
+ processes.lines.map do |pid_line|
17
+ columns = pid_line.split
18
+ [columns[1], columns[-1]]
19
+ end.to_h
20
+ end
21
+ end
22
+
23
+ def find_pid
24
+ process_table.invert[@repl.default_package]
25
+ end
26
+
27
+ def scan_pid
28
+ @last_pid = nil
29
+ t = Thread.new do
30
+ begin
31
+ while @repl.default_package
32
+ pid = find_pid
33
+ t.exit if @signal_exit
34
+ pid_changed = (pid && pid != @last_pid) || (pid.nil? && @last_pid)
35
+ yield pid if block_given? && pid_changed
36
+ @last_pid = pid
37
+ sleep 2
38
+ end
39
+ rescue Exception => e
40
+ puts e.inspect
41
+ puts e.backtrace.join("\n")
42
+ raise e
43
+ end
44
+ end
45
+ end
46
+
47
+ end
@@ -4,6 +4,9 @@ require 'rexml/document'
4
4
  module Replicant
5
5
  class REPL
6
6
 
7
+ Encoding.default_external = Encoding::UTF_8
8
+ Encoding.default_internal = Encoding::UTF_8
9
+
7
10
  include Styles
8
11
 
9
12
  # for auto-complete via rlwrap; should probably go in Rakefile at some point
@@ -34,8 +37,15 @@ module Replicant
34
37
  PackageCommand.new(self, app_package).execute
35
38
  end
36
39
 
40
+ # try to pre-select a device, if any
41
+ connected_devices = DevicesCommand.new(self, nil, :silent => true).execute
42
+ if connected_devices.any?
43
+ output "Found #{connected_devices.size} device(s)"
44
+ DeviceCommand.new(self, "1").execute
45
+ end
46
+
37
47
  # reset terminal colors on exit
38
- at_exit { puts unstyled }
48
+ at_exit { puts end_style }
39
49
 
40
50
  loop do
41
51
  command_loop
@@ -56,12 +66,16 @@ module Replicant
56
66
  command = Command.load(self, command_line)
57
67
  if command
58
68
  command.execute
59
- puts span("OK.", :white_fg, :bold) { unstyled }
69
+ puts styled_text("OK.", :white_fg, :bold)
60
70
  else
61
- puts "No such command"
71
+ output "No such command"
62
72
  end
63
73
  end
64
74
 
75
+ def output(msg)
76
+ puts styled_text(msg, *REPL_OUT)
77
+ end
78
+
65
79
  def debug?
66
80
  ARGV.include?('--debug')
67
81
  end
@@ -70,13 +84,14 @@ module Replicant
70
84
 
71
85
  def prompt
72
86
  prompt = ENV['REPL_PROMPT'] || begin
73
- span('>> ', :white_fg, :bold) { styled(:green_fg) }
87
+ pr = (default_device ? "#{default_device.short_name} " : "") << ">> "
88
+ styled_text(pr, :white_fg, :bold) { create_style(*REPL_OUT) }
74
89
  end.lstrip
75
90
  end
76
91
 
77
92
  def show_greeting
78
- style = styled(:white_fg, :black_bg, :bold)
79
- green = lambda { |text| span(text, :green_fg) { style } }
93
+ style = create_style(:white_fg, :bold)
94
+ green = lambda { |text| styled_text(text, :green_fg) { style } }
80
95
 
81
96
  logo = <<-logo
82
97
  dP oo dP
@@ -86,16 +101,16 @@ module Replicant
86
101
  88 88. ... 88. .88 88 88 88. ... 88. .88 88 88 88
87
102
  dP `88888P' 88Y888P' dP dP `88888P' `88888P8 dP dP dP
88
103
  88
89
- dP (c) 2013 Matthias Kaeppler
104
+ dP (c) 2013-2014 Matthias Kaeppler
90
105
  logo
91
- puts style + ("~" * 70)
106
+ puts style + ("~" * Styles::CONSOLE_WIDTH)
92
107
  puts " v" + Replicant::VERSION
93
108
  puts green[logo]
94
109
  puts ""
95
110
  puts " Type '#{green['!']}' to see a list of commands, '#{green['?']}' for environment info."
96
111
  puts " Commands not starting in '#{green['!']}' are sent to adb verbatim."
97
112
  puts " Use #{green['Ctrl-D']} (i.e. EOF) to exit."
98
- puts ("~" * 70) + unstyled
113
+ puts ("~" * Styles::CONSOLE_WIDTH) + end_style
99
114
  end
100
115
 
101
116
  def show_help
@@ -1,29 +1,43 @@
1
1
  module Styles
2
2
 
3
+ CONSOLE_WIDTH = 70
4
+
3
5
  STYLES = {
4
6
  # foreground text
5
- :white_fg => 37,
6
- :black_fg => 30,
7
- :green_fg => 32,
7
+ :black_fg => 30,
8
+ :red_fg => 31,
9
+ :green_fg => 32,
10
+ :yellow_fg => 33,
11
+ :blue_fg => 34,
12
+ :magenta_fg => 35,
13
+ :cyan_fg => 36,
14
+ :white_fg => 37,
8
15
 
9
16
  # background
10
- :white_bg => 47,
17
+ :black_bg => 40,
18
+ :red_bg => 41,
19
+ :green_bg => 42,
20
+ :yellow_bg => 43,
21
+ :blue_bg => 44,
22
+ :magenta_bg => 45,
23
+ :cyan_bg => 46,
24
+ :white_bg => 47,
11
25
 
12
26
  # text styles
13
27
  :bold => 1
14
28
  }
15
29
 
16
- def span(text, *styles)
17
- styled = "\e[#{STYLES.values_at(*styles).join(';')}m#{text}"
18
- styled << yield if block_given?
19
- styled
30
+ REPL_OUT = [:green_fg, :bold]
31
+
32
+ def styled_text(text, *styles)
33
+ create_style(*styles) + text + if block_given? then yield else end_style end
20
34
  end
21
35
 
22
- def styled(*styles)
36
+ def create_style(*styles)
23
37
  "\e[#{STYLES.values_at(*styles).join(';')}m"
24
38
  end
25
39
 
26
- def unstyled
40
+ def end_style
27
41
  "\e[0m"
28
42
  end
29
43
 
@@ -1,3 +1,3 @@
1
1
  module Replicant
2
- VERSION = "0.0.1"
2
+ VERSION = "1.0.1"
3
3
  end
metadata CHANGED
@@ -1,80 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: replicant-adb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
5
- prerelease:
4
+ version: 1.0.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Matthias Kaeppler
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-11-27 00:00:00.000000000 Z
11
+ date: 2014-10-19 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: activesupport-core-ext
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '4.0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '4.0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
33
  version: '10.1'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
40
  version: '10.1'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: bundler
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ~>
45
+ - - "~>"
52
46
  - !ruby/object:Gem::Version
53
47
  version: '1.0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ~>
52
+ - - "~>"
60
53
  - !ruby/object:Gem::Version
61
54
  version: '1.0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: jeweler
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ~>
59
+ - - "~>"
68
60
  - !ruby/object:Gem::Version
69
- version: 1.8.7
61
+ version: '2.0'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ~>
66
+ - - "~>"
76
67
  - !ruby/object:Gem::Version
77
- version: 1.8.7
68
+ version: '2.0'
78
69
  description: replicant is an interactive shell (a REPL) for ADB, the Android Debug
79
70
  Bridge
80
71
  email: m.kaeppler@gmail.com
@@ -85,53 +76,49 @@ extra_rdoc_files:
85
76
  - LICENSE.txt
86
77
  - README.md
87
78
  files:
88
- - .travis.yml
89
- - Gemfile
90
79
  - LICENSE.txt
91
80
  - README.md
92
- - Rakefile
93
81
  - bin/replicant
94
82
  - lib/replicant.rb
95
- - lib/replicant/command.rb
83
+ - lib/replicant/commands.rb
84
+ - lib/replicant/commands/adb_command.rb
85
+ - lib/replicant/commands/clear_command.rb
86
+ - lib/replicant/commands/command.rb
87
+ - lib/replicant/commands/device_command.rb
88
+ - lib/replicant/commands/devices_command.rb
89
+ - lib/replicant/commands/env_command.rb
90
+ - lib/replicant/commands/list_command.rb
91
+ - lib/replicant/commands/package_command.rb
92
+ - lib/replicant/commands/reset_command.rb
93
+ - lib/replicant/commands/restart_command.rb
96
94
  - lib/replicant/device.rb
95
+ - lib/replicant/log_muncher.rb
96
+ - lib/replicant/process_muncher.rb
97
97
  - lib/replicant/repl.rb
98
98
  - lib/replicant/styles.rb
99
99
  - lib/replicant/version.rb
100
- - test/commands/adb_command_spec.rb
101
- - test/commands/command_spec.rb
102
- - test/commands/command_spec_base.rb
103
- - test/commands/device_command_spec.rb
104
- - test/commands/devices_command_spec.rb
105
- - test/commands/env_command_spec.rb
106
- - test/commands/list_command_spec.rb
107
- - test/commands/package_command_spec.rb
108
- - test/helper.rb
109
100
  homepage: https://github.com/mttkay/replicant
110
101
  licenses:
111
102
  - MIT
103
+ metadata: {}
112
104
  post_install_message:
113
105
  rdoc_options: []
114
106
  require_paths:
115
107
  - lib
116
108
  required_ruby_version: !ruby/object:Gem::Requirement
117
- none: false
118
109
  requirements:
119
- - - ! '>='
110
+ - - ">="
120
111
  - !ruby/object:Gem::Version
121
112
  version: '0'
122
- segments:
123
- - 0
124
- hash: -4199582713992118202
125
113
  required_rubygems_version: !ruby/object:Gem::Requirement
126
- none: false
127
114
  requirements:
128
- - - ! '>='
115
+ - - ">="
129
116
  - !ruby/object:Gem::Version
130
117
  version: '0'
131
118
  requirements: []
132
119
  rubyforge_project:
133
- rubygems_version: 1.8.25
120
+ rubygems_version: 2.2.2
134
121
  signing_key:
135
- specification_version: 3
122
+ specification_version: 4
136
123
  summary: A REPL for the Android Debug Bridge
137
124
  test_files: []