appear 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
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
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in appear.gemspec
4
+ gemspec
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
+ [![Build Status](https://secure.travis-ci.org/airbnb/appear.svg?branch=master)](http://travis-ci.org/airbnb/appear)
6
+
7
+ ![screenshot demo thing](./screenshot.gif)
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
@@ -0,0 +1,7 @@
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/command'
7
+ command = Appear::Command.new.execute(ARGV)
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
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
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