prettyp 0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6f5a14081112b48776bdb009a7b509ca08548d94
4
+ data.tar.gz: 6506aa55657f050cda05b958b377a15b92556024
5
+ SHA512:
6
+ metadata.gz: c28301c9b78b7a2d51809163b018a8a7922105883a2ff3e1588dd64e9cec6c3a3ae784da3a3894a31e1c222e6f9e1399cdc330eb18634337c2a713c7703d5a08
7
+ data.tar.gz: 4999d3c6478c700ff330af063863506a2f1d1c7c0960b2a87c42ca3656bacc5ef572713bb7a4a123c5090d12fd2037842a9fb5087f172b5d1e6403771d8d6a84
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ tags
16
+ /.vendor/
17
+ cscope.out
18
+ .starscope.db
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development do
4
+ gem 'pry', require: true
5
+ gem 'fakefs'
6
+ end
7
+
8
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Jacob Evans
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # Prettyp
2
+
3
+ One language formatter tool to rule them all.
4
+
5
+ ## Why?
6
+ I didn't like having to remember:
7
+
8
+ ```
9
+ pbpaste | xmllint --format -
10
+ cat log.json | python -m json.tool
11
+ ```
12
+
13
+ Why not just have a tool to do them all.
14
+
15
+ ## Installation
16
+
17
+ Install it yourself as:
18
+
19
+ $ gem install prettyp
20
+
21
+ ## Usage
22
+
23
+ ```
24
+ pbpaste | prettyp format
25
+ cat test.json | prettyp format
26
+ prettyp format --file test.json
27
+ ```
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it ( https://github.com/dekz/prettyp/fork )
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create a new Pull Request
36
+
37
+ ## TODO support ignoring the language classifier
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/prettyp ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+
4
+ require 'prettyp'
5
+ require 'thor'
6
+
7
+ class CLI < Thor
8
+ Prettyp::Logger.logger.level = ::Logger::WARN
9
+ desc "format", "formats input from either stdin or file (--file) and prints to stdout"
10
+ option :file
11
+ def format
12
+ service = Prettyp::FormatterService.new
13
+ text = if options[:file]
14
+ service.format_from_file(File.open(options[:file], 'r'))
15
+ else
16
+ service.format_from_stdin
17
+ end
18
+ puts text
19
+ end
20
+ end
21
+
22
+ CLI.start(ARGV)
data/lib/prettyp.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "prettyp/version"
2
+ require "prettyp/logger"
3
+ require 'prettyp/formatters'
4
+ require 'prettyp/formatter_service'
5
+
6
+ module Prettyp
7
+ end
@@ -0,0 +1,73 @@
1
+ require 'tempfile'
2
+
3
+ module Prettyp
4
+ module Formatter
5
+ class FormatError < StandardError; end
6
+ class Unimplemented < StandardError; end
7
+
8
+ class BaseFormatter
9
+ include Logger
10
+
11
+ def self.inherited clazz
12
+ @inherited_classes ||= []
13
+ @inherited_classes << clazz
14
+ end
15
+
16
+ def self.inherited_classes
17
+ @inherited_classes
18
+ end
19
+
20
+ def self.check_requirement
21
+ raise Unimplemented 'requirement'
22
+ end
23
+
24
+ def self.languages
25
+ []
26
+ end
27
+
28
+ def check_requirement
29
+ self.class.check_requirement
30
+ end
31
+
32
+ def format input, language
33
+ raise Unimplemented 'format'
34
+ end
35
+
36
+ protected
37
+ def execute_command command, on_error: nil, on_success: nil
38
+ logger.debug command
39
+
40
+ output = `#{command} 2>&1 `
41
+ success = !execute_error?
42
+
43
+ on_error.call(output) if !success && on_error
44
+ on_success.call(output) if success and on_success
45
+
46
+ output
47
+ end
48
+
49
+ def execute_error?
50
+ $? != 0
51
+ end
52
+
53
+ def with_file input, &block
54
+ return block.call(input) if input.is_a?(File) || input.is_a?(Tempfile)
55
+ with_tempfile(input, &block)
56
+ end
57
+
58
+ def with_tempfile input, &block
59
+ file = Tempfile.new('prettyp')
60
+ file.write(input)
61
+ begin
62
+ file.rewind
63
+ block.call(file)
64
+ ensure
65
+ file.close
66
+ file.unlink
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+
@@ -0,0 +1 @@
1
+ Dir.glob(File.dirname(__FILE__) + '/html/*') { |f| load f }
@@ -0,0 +1,32 @@
1
+ module Prettyp
2
+ module Formatter
3
+ module HTML
4
+ class Tidy < ::Prettyp::Formatter::BaseFormatter
5
+
6
+ def self.languages
7
+ ['HTML']
8
+ end
9
+
10
+ def self.executeable; 'tidy'; end
11
+
12
+ def self.check_requirement
13
+ !%x|which #{executeable}|.empty?
14
+ end
15
+
16
+ def format input, language
17
+ with_file(input) do |file|
18
+ with_tempfile '' do |tmp|
19
+ out = execute_command("#{self.class.executeable} -im #{file.path} -f #{tmp.path} -q",
20
+ #on_error: Proc.new { |output| raise FormatError, output })
21
+ on_error: Proc.new { })
22
+ out = File.read(file.path)
23
+ out
24
+ end
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1 @@
1
+ Dir.glob(File.dirname(__FILE__) + '/json/*') { |f| load f }
@@ -0,0 +1,24 @@
1
+ module Prettyp
2
+ module Formatter
3
+ module JSON
4
+ class Python < ::Prettyp::Formatter::BaseFormatter
5
+ def self.languages
6
+ ['JSON']
7
+ end
8
+
9
+ def self.executeable; 'python'; end
10
+ def self.check_requirement
11
+ !%x|which #{executeable}|.empty?
12
+ end
13
+
14
+ def format input, language
15
+ with_file(input) do |file|
16
+ out = execute_command("cat #{file.path} | #{self.class.executeable} -m json.tool",
17
+ on_error: Proc.new { |output| raise FormatError, output })
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
File without changes
@@ -0,0 +1 @@
1
+ Dir.glob(File.dirname(__FILE__) + '/xml/*') { |f| load f }
@@ -0,0 +1,27 @@
1
+ module Prettyp
2
+ module Formatter
3
+ module XML
4
+ class Xmllint < ::Prettyp::Formatter::BaseFormatter
5
+
6
+ def self.languages
7
+ [:xml, :html]
8
+ end
9
+
10
+ def self.executeable; 'xmllint'; end
11
+ def self.check_requirement
12
+ !%x|which #{executeable}|.empty?
13
+ end
14
+
15
+ def format input, language
16
+ extra_opts = '--html' if language.eql? :html
17
+ with_file(input) do |file|
18
+ out = execute_command("cat #{file.path} | #{self.class.executeable} --format #{extra_opts} -",
19
+ on_error: Proc.new { |output| raise FormatError, output })
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,30 @@
1
+ module Prettyp
2
+ class FormatterRegistry
3
+
4
+ attr_reader :formatters
5
+
6
+ def initialize formatters = Formatter::BaseFormatter.inherited_classes
7
+ determine_formatters formatters
8
+ end
9
+
10
+ def formatter_for language
11
+ formatters[format_language_key(language)].first
12
+ end
13
+
14
+ private
15
+ def determine_formatters formatters
16
+ our_formatters = Hash.new {|h,k| h[k]=[]}
17
+
18
+ formatters.each do |clazz|
19
+ clazz.languages.each { |l| our_formatters[format_language_key(l)] << clazz } if clazz.check_requirement
20
+ end
21
+
22
+ @formatters = our_formatters
23
+ end
24
+
25
+ def format_language_key l
26
+ l.downcase.to_sym
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,62 @@
1
+ require 'prettyp/language_detection_service'
2
+ require 'prettyp/formatter_registry'
3
+
4
+ module Prettyp
5
+ class FormatError < StandardError; end
6
+ class FormatterService
7
+ include Logger
8
+
9
+ def initialize(formatter_registry: FormatterRegistry.new, language_detection: LanguageDetectionService.new)
10
+ @formatter_registry = formatter_registry
11
+ @language_detection = language_detection
12
+ end
13
+
14
+ def format_from_file file
15
+ language = language_detection.detect_from_file(file)
16
+ format file, language
17
+ end
18
+
19
+ def format_from_stdin
20
+ input = $stdin.read
21
+
22
+ language = language_detection.detect_from_input(input)
23
+ with_tempfile input do |f|
24
+ format f, language
25
+ end
26
+ end
27
+
28
+ def format_as_language_from_file language, file
29
+ format file, language
30
+ end
31
+
32
+ def format_as_language_from_stdin language
33
+ input = $stdin.read
34
+
35
+ with_tempfile input do |f|
36
+ format f, language
37
+ end
38
+ end
39
+
40
+ private
41
+ attr_reader :formatter_registry, :language_detection
42
+
43
+ def format file, language
44
+ formatter = formatter_registry.formatter_for(language)
45
+ raise FormatError, "Cannot determine formatter for #{language} from #{formatter_registry.formatters}" unless formatter
46
+ formatter.new.format(file, language)
47
+ end
48
+
49
+ def with_tempfile input, &block
50
+ file = Tempfile.new('prettyp')
51
+ file.write(input)
52
+ begin
53
+ file.rewind
54
+ block.call(file)
55
+ ensure
56
+ file.close
57
+ file.unlink
58
+ end
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,4 @@
1
+ require 'prettyp/formatter/base_formatter'
2
+ require 'prettyp/formatter/xml'
3
+ require 'prettyp/formatter/json'
4
+ require 'prettyp/formatter/html'
@@ -0,0 +1,31 @@
1
+ require 'linguist'
2
+
3
+ module Prettyp
4
+ class LanguageDetectionService
5
+ # Our supported languages
6
+ POSSIBLE_LANGUAGE_NAMES = ['XML', 'Ruby', 'JSON', 'JavaScript', 'HTML']
7
+
8
+ def detect_from_file file
9
+ file_blob = Linguist::FileBlob.new(file.path)
10
+ language = file_blob.language
11
+ return format_language_key(language.name) if language
12
+
13
+ detect_from_input(file_blob.data)
14
+ end
15
+
16
+ def detect_from_input input
17
+ classified = Linguist::Classifier.classify(Linguist::Samples::DATA, input, possible).first
18
+ format_language_key(Linguist::Language[classified[0]].name)
19
+ end
20
+
21
+ private
22
+ def possible
23
+ @possible_languaes_list ||= POSSIBLE_LANGUAGE_NAMES.map { |n| Linguist::Language.find_by_name(n) }.map(&:name)
24
+ end
25
+
26
+ def format_language_key l
27
+ l.downcase.to_sym
28
+ end
29
+ end
30
+ end
31
+