appear 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.
- checksums.yaml +7 -0
- data/.doc-coverage +1 -0
- data/.gitignore +51 -0
- data/.rspec +2 -0
- data/.travis.yml +19 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +101 -0
- data/Rakefile +53 -0
- data/appear.gemspec +44 -0
- data/bin/appear +7 -0
- data/bin/console +14 -0
- data/bin/pparents +23 -0
- data/bin/setup +7 -0
- data/lib/appear.rb +14 -0
- data/lib/appear/command.rb +57 -0
- data/lib/appear/config.rb +24 -0
- data/lib/appear/constants.rb +17 -0
- data/lib/appear/instance.rb +54 -0
- data/lib/appear/join.rb +100 -0
- data/lib/appear/lsof.rb +153 -0
- data/lib/appear/mac_os.rb +42 -0
- data/lib/appear/output.rb +30 -0
- data/lib/appear/processes.rb +88 -0
- data/lib/appear/revealers.rb +183 -0
- data/lib/appear/runner.rb +101 -0
- data/lib/appear/service.rb +65 -0
- data/lib/appear/tmux.rb +77 -0
- data/screenshot.gif +0 -0
- data/tools/macOS-helper.js +349 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 49e7e4587f6725e9cf308bd49827e9b4a155904d
|
4
|
+
data.tar.gz: b62a655a7a4173118aa423bf8247c3407c39bd56
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 276900ee030c9bdeba0fe2c85fd60034d7f6e34e976651525809b334afe9075ab74fe3c9555e6eaf3b29ff0b64d9f579eb804cd085539ee0babb23d2f92d3542
|
7
|
+
data.tar.gz: 10859c80d30ad2c950a3f809b0c6a260faf4233436c533f668802af4426c0f0265ec53293d01153ef8984828f685babaec34853dc3d849c7bfeeb820a1585c48
|
data/.doc-coverage
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
73.05
|
data/.gitignore
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
/logs/
|
13
|
+
|
14
|
+
# Used by dotenv library to load environment variables.
|
15
|
+
# .env
|
16
|
+
|
17
|
+
## Specific to RubyMotion:
|
18
|
+
.dat*
|
19
|
+
.repl_history
|
20
|
+
build/
|
21
|
+
*.bridgesupport
|
22
|
+
build-iPhoneOS/
|
23
|
+
build-iPhoneSimulator/
|
24
|
+
|
25
|
+
## Specific to RubyMotion (use of CocoaPods):
|
26
|
+
#
|
27
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
28
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
29
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
30
|
+
#
|
31
|
+
# vendor/Pods/
|
32
|
+
|
33
|
+
## Documentation cache and generated files:
|
34
|
+
/.yardoc/
|
35
|
+
/_yardoc/
|
36
|
+
/doc/
|
37
|
+
/rdoc/
|
38
|
+
|
39
|
+
## Environment normalization:
|
40
|
+
/.bundle/
|
41
|
+
/vendor/bundle
|
42
|
+
/lib/bundler/man/
|
43
|
+
|
44
|
+
# for a library or gem, you might want to ignore these files since the code is
|
45
|
+
# intended to run in multiple environments; otherwise, check them in:
|
46
|
+
Gemfile.lock
|
47
|
+
.ruby-version
|
48
|
+
.ruby-gemset
|
49
|
+
|
50
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
51
|
+
.rvmrc
|
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
language: ruby
|
2
|
+
matrix:
|
3
|
+
# see https://docs.travis-ci.com/user/customizing-the-build/#Build-Matrix
|
4
|
+
# see https://docs.travis-ci.com/user/osx-ci-environment/
|
5
|
+
allow_failures:
|
6
|
+
- os: linux
|
7
|
+
include:
|
8
|
+
- os: linux
|
9
|
+
rvm: 1.9.3
|
10
|
+
- os: linux
|
11
|
+
rvm: 2.2.3
|
12
|
+
- os: osx
|
13
|
+
osx_image: xcode7 # 10.10
|
14
|
+
# - os: osx
|
15
|
+
# - osx_image: xcode7.2 # 10.11
|
16
|
+
script:
|
17
|
+
# Please add to Rakefile instead of this section.
|
18
|
+
- bundle exec rake
|
19
|
+
before_install: gem install bundler -v 1.10.6
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2016 Airbnb
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# Appear
|
2
|
+
|
3
|
+
Appear your terminal programs in your gui!
|
4
|
+
|
5
|
+
[](http://travis-ci.org/airbnb/appear)
|
6
|
+
|
7
|
+

|
8
|
+
|
9
|
+
Appear is a tool for revealing a given process in your terminal. Given a
|
10
|
+
process ID, `appear` finds the terminal emulator view (be it a window, tab, or
|
11
|
+
pane) containing that process and shows it to you. Appear understands terminal
|
12
|
+
multiplexers like `tmux`, so if your target process is in a multiplexer
|
13
|
+
session, `appear` will reveal a client connected to that session, or start one
|
14
|
+
if needed.
|
15
|
+
|
16
|
+
This project intends to support all POSIX operating systems eventually, but
|
17
|
+
currently only supports macOS.
|
18
|
+
|
19
|
+
## usage
|
20
|
+
|
21
|
+
```
|
22
|
+
Usage: appear [options] PID - appear PID in your user interface
|
23
|
+
-l, --log-file [PATH] log to a file
|
24
|
+
-v, --verbose tell many tales about how the appear process is going
|
25
|
+
--record-runs record every executed command as a JSON file
|
26
|
+
```
|
27
|
+
|
28
|
+
Appear will exit 0 if it managed to reveal something.
|
29
|
+
Appear will exit 1 if an exception occured.
|
30
|
+
Appear will exit 2 if there were no errors, but nothing was revealed.
|
31
|
+
|
32
|
+
## supported terminal emulators
|
33
|
+
|
34
|
+
macOS:
|
35
|
+
|
36
|
+
- iTerm2
|
37
|
+
- Terminal
|
38
|
+
|
39
|
+
cross-platform:
|
40
|
+
|
41
|
+
- tmux
|
42
|
+
|
43
|
+
GNU Screen support is a non-goal. It's time for screen users to switch to tmux.
|
44
|
+
|
45
|
+
## system requirements
|
46
|
+
|
47
|
+
- `ruby` >= 2
|
48
|
+
- `lsof` command
|
49
|
+
- `ps` command
|
50
|
+
- `pgrep` command
|
51
|
+
- if you're a mac, then you should have macOS >= 10.10
|
52
|
+
|
53
|
+
Appear depends only on the Ruby standard library.
|
54
|
+
|
55
|
+
## how it works
|
56
|
+
|
57
|
+
Here's how Appear works in a nutshell, given a `target_pid`
|
58
|
+
|
59
|
+
1. get all the parent processes of `target_pid`, up to pid1. We end up with a
|
60
|
+
list of ProcessInfos, which have fields `{pid, parent_pid, command, name}`
|
61
|
+
2. go through our list of "revealers", one for each terminal emulator (tmux,
|
62
|
+
iterm2, terminal.app) and ask the revealer if it can apply itself to the
|
63
|
+
process tree.
|
64
|
+
3. if a revealer finds an associated process in the tree (eg, tmux revealer
|
65
|
+
finds the tmux server process), it performs its reveal action
|
66
|
+
- this usually involves invoking `lsof` on a `/dev/ttys*` device to see what
|
67
|
+
processes are talking on what ttys to each other, which takes a bunch of
|
68
|
+
time
|
69
|
+
- `lsof` in Appear is parallel, so grouped lsof calls are less expensive
|
70
|
+
- the Tmux revealer is smart enough to both focus the pane that the
|
71
|
+
`target_pid` is running in, AND to recurse the revealing process with the
|
72
|
+
tmux client id, to reveal the tmux client.
|
73
|
+
4. the revealer sends some instructions to the terminal emulator that contains
|
74
|
+
the view for the PID
|
75
|
+
- for our Mac apps, this involves a helper process using [Javascript for
|
76
|
+
Automation][jfora], a JavaScript x Applescript crossover episode.
|
77
|
+
- for tmux this is just some shell commands, super easy.
|
78
|
+
|
79
|
+
[jfora]: https://developer.apple.com/library/mac/releasenotes/InterapplicationCommunication/RN-JavaScriptForAutomation/Articles/OSX10-10.html#//apple_ref/doc/uid/TP40014508-CH109-SW1
|
80
|
+
|
81
|
+
## ruby api
|
82
|
+
|
83
|
+
The method documented here is the only part of Appear that should be considered
|
84
|
+
stable.
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
require 'appear'
|
88
|
+
|
89
|
+
# super simple
|
90
|
+
Appear.appear(pid)
|
91
|
+
|
92
|
+
# You may customize logging, if needed, using the Config class
|
93
|
+
config = Appear::Config.new
|
94
|
+
|
95
|
+
# print debug info to STDOUT
|
96
|
+
config.silent = false
|
97
|
+
# also write to a log file
|
98
|
+
config.log_file = '/tmp/my-app-appear.log'
|
99
|
+
|
100
|
+
Appear.appear(pid, config)
|
101
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "yard"
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
module BasicDocCoverage
|
8
|
+
MINIMUM_COVERAGE = 25.0
|
9
|
+
YARD_COVERAGE_REGEX = /\s(?<percent>[\d\.]+)% documented/
|
10
|
+
|
11
|
+
ROOT_PATH = Pathname.new(File.dirname(File.expand_path(__FILE__)))
|
12
|
+
MINIMUM_COVERAGE_FILE = ROOT_PATH.join('.doc-coverage')
|
13
|
+
|
14
|
+
def self.define_task(task_name)
|
15
|
+
YARD::Rake::YardocTask.new(task_name) do |t|
|
16
|
+
t.files = ['lib/**/*.rb', '-', 'README.md']
|
17
|
+
t.options = ['--protected', '--no-private']
|
18
|
+
|
19
|
+
# make sure we doc the things
|
20
|
+
t.after = proc do
|
21
|
+
|
22
|
+
min_coverage = MINIMUM_COVERAGE
|
23
|
+
if MINIMUM_COVERAGE_FILE.exist?
|
24
|
+
min_coverage = [min_coverage, MINIMUM_COVERAGE_FILE.read.strip.to_f].max
|
25
|
+
end
|
26
|
+
|
27
|
+
yard_result = `bundle exec yard stats --list-undoc`
|
28
|
+
match = YARD_COVERAGE_REGEX.match(yard_result)
|
29
|
+
if !match
|
30
|
+
raise "Could not determine doc coverage using RE #{RE} from YARD output\n" \
|
31
|
+
">>> start YARD output\n#{yard_result}\n<<< end YARD output"
|
32
|
+
end
|
33
|
+
|
34
|
+
percent = match[:percent].to_f
|
35
|
+
failure = percent < min_coverage
|
36
|
+
|
37
|
+
if failure
|
38
|
+
raise "FAILURE: doc coverage percent #{percent} < #{min_coverage}\n" \
|
39
|
+
" please write good docs for your methods and attributes!\n" \
|
40
|
+
" run `bundle exec yard stats --list-undoc` for details"
|
41
|
+
else
|
42
|
+
puts "SUCCESS: doc coverage percent #{percent} >= #{min_coverage}"
|
43
|
+
end
|
44
|
+
|
45
|
+
File.write(MINIMUM_COVERAGE_FILE, [percent, min_coverage].max.to_s)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
BasicDocCoverage.define_task(:doc)
|
52
|
+
|
53
|
+
task default: [:spec, :doc]
|
data/appear.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'appear/constants'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "appear"
|
8
|
+
spec.version = Appear::VERSION
|
9
|
+
spec.authors = ["Jake Teton-Landis"]
|
10
|
+
spec.email = ["just.1.jake@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Appear your terminal programs in your gui!}
|
13
|
+
spec.description = <<-EOS
|
14
|
+
Appear is a tool for revealing a given process in your terminal. Given a
|
15
|
+
process ID, `appear` finds the terminal emulator view (be it a window, tab, or
|
16
|
+
pane) containing that process and shows it to you. Appear understands terminal
|
17
|
+
multiplexers like `tmux`, so if your target process is in a multiplexer
|
18
|
+
session, `appear` will reveal a client connected to that session, or start one
|
19
|
+
if needed.
|
20
|
+
|
21
|
+
This project intends to support all POSIX operating systems eventually, but
|
22
|
+
currently only supports macOS.
|
23
|
+
EOS
|
24
|
+
spec.homepage = "https://github.com/airbnb/appear"
|
25
|
+
|
26
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
27
|
+
# delete this section to allow pushing this gem to any host.
|
28
|
+
# if spec.respond_to?(:metadata)
|
29
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
30
|
+
# else
|
31
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
32
|
+
# end
|
33
|
+
|
34
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
35
|
+
spec.bindir = "exe"
|
36
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
37
|
+
spec.require_paths = ["lib"]
|
38
|
+
|
39
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
40
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
41
|
+
spec.add_development_dependency "rspec"
|
42
|
+
spec.add_development_dependency "pry"
|
43
|
+
spec.add_development_dependency "yard", "~> 0.8.0"
|
44
|
+
end
|
data/bin/appear
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "appear"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/pparents
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
$:.unshift(Pathname.new(__FILE__).realpath.dirname.dirname.join('./lib').to_s)
|
5
|
+
|
6
|
+
require 'appear'
|
7
|
+
|
8
|
+
module Appear::PParents
|
9
|
+
def self.main
|
10
|
+
pid = ARGV[0].to_i
|
11
|
+
|
12
|
+
output = Appear::Output.new(nil, true)
|
13
|
+
runner = Appear::Runner.new(:output => output)
|
14
|
+
processes = Appear::Processes.new(:output => output, :runner => runner)
|
15
|
+
|
16
|
+
tree = processes.process_tree(pid)
|
17
|
+
tree.each do |info|
|
18
|
+
puts "#{info.pid} #{info.command.join(' ')}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Appear::PParents.main
|
data/bin/setup
ADDED
data/lib/appear.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Appear
|
2
|
+
# This method is an easy public interface to Appear for ruby consumers.
|
3
|
+
# Appear the given PID in your user interfaces.
|
4
|
+
# @param pid [Number] pid to Appear.
|
5
|
+
# @param config [Appear::Config, nil] a config for adjusting verbosity and logging.
|
6
|
+
def self.appear(pid, config = nil)
|
7
|
+
config ||= Appear::Config.new
|
8
|
+
instance = Appear::Instance.new(config)
|
9
|
+
instance.call(pid)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'appear/config'
|
14
|
+
require 'appear/instance'
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'appear/constants'
|
2
|
+
require 'appear/config'
|
3
|
+
require 'appear/instance'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
module Appear
|
7
|
+
class InvalidPidError < Error; end
|
8
|
+
|
9
|
+
# Entrypoint and manager for the command-line `appear` tool.
|
10
|
+
class Command
|
11
|
+
def initialize
|
12
|
+
@config = Appear::Config.new
|
13
|
+
@config.silent = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def option_parser
|
17
|
+
@option_parser ||= OptionParser.new do |o|
|
18
|
+
o.banner = 'Usage: appear [options] PID - appear PID in your user interface'
|
19
|
+
o.on('-l', '--log-file [PATH]', 'log to a file') do |file|
|
20
|
+
@config.log_file = file
|
21
|
+
end
|
22
|
+
|
23
|
+
o.on('-v', '--verbose', 'tell many tales about how the appear process is going') do |flag|
|
24
|
+
@config.silent = false if flag
|
25
|
+
end
|
26
|
+
|
27
|
+
o.on('--record-runs', 'record every executed command as a JSON file') do |flag|
|
28
|
+
@config.record_runs = flag
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def execute(all_args)
|
34
|
+
argv = option_parser.parse!(all_args)
|
35
|
+
|
36
|
+
pid = argv[0].to_i
|
37
|
+
if pid == 0
|
38
|
+
raise InvalidPidError.new("Invalid PID #{argv[0].inspect} given (parsed to 0).")
|
39
|
+
end
|
40
|
+
|
41
|
+
start = Time.now
|
42
|
+
revealer = Appear::Instance.new(@config)
|
43
|
+
revealer.output("STARTING. pid: #{pid}")
|
44
|
+
result = revealer.call(pid)
|
45
|
+
finish = Time.now
|
46
|
+
revealer.output("DONE. total time: #{finish - start} seconds, success: #{result}")
|
47
|
+
|
48
|
+
if result
|
49
|
+
# success! revealed something!
|
50
|
+
exit 0
|
51
|
+
else
|
52
|
+
# did not appear, but no errors encountered
|
53
|
+
exit 2
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|