puncsig 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.
data/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # puncsig: Punctuation Signatures
2
+
3
+ ## What Is This?
4
+
5
+ Inspired by Ward Cunningham's [Signature Survey: A Method for Browsing
6
+ Unfamiliar Code](http://c2.com/doc/SignatureSurvey/), "puncsig" is
7
+ short for "punctuation signature": it parses ruby code, and shows you
8
+ just the punctuation from the methods. It gives you a rough idea of
9
+ the length of each method, and helps you spot similar methods.
10
+
11
+ ## Install
12
+
13
+ In your Gemfile:
14
+
15
+ ```
16
+ gem 'puncsig'
17
+ ```
18
+
19
+ ...or on your command line:
20
+
21
+ ```
22
+ $ gem install puncsig
23
+ ```
24
+
25
+ You know, the basics.
26
+
27
+ ## Use It
28
+
29
+ In your rails app:
30
+
31
+ ```
32
+ $ bundle exec rake -T puncsig
33
+ rake puncsig:all # Run puncsig on the whole app
34
+ rake puncsig:controllers # Run puncsig on just the controllers
35
+ rake puncsig:helpers # Run puncsig on just the helpers
36
+ rake puncsig:lib # Run puncsig on just the files in lib
37
+ rake puncsig:models # Run puncsig on just the models
38
+ ```
39
+
40
+ TODO In a normal ruby app. It's not quite here yet, I want to separate
41
+ it out a bit more. Coming soon, promise!
42
+
43
+ ## Example: rstat.us
44
+
45
+ Just for fun, let's take a look at the [rstat.us
46
+ source](https://github.com/hotsh/rstat.us). I chose rstat.us strictly
47
+ because a) it was open-source ruby, and b) it cleanly installed, so
48
+ whatever puncsig says about the source, that's a great start - and I
49
+ gave up on several others, because I couldn't get them installed
50
+ easily. We _all_ have code that needs some love, and I have much love
51
+ for the people behind rstat.us.
52
+
53
+ ```
54
+ $ be rake puncsig:models
55
+
56
+ [...]
57
+
58
+ app/models/salmon_author.rb
59
+ author_attributes: {:=>,:=>,:=>,:=>,:=>,:=>,:=>}==().==.==.==.&&==.&&==.&&==.&&==.&&==.
60
+ avatar_url: @..{||..==}..
61
+ email: =@.==
62
+ initialize: ()@=
63
+ bio: @..
64
+ name: @..
65
+ uri: @.
66
+ username: @.
67
+
68
+ [...]
69
+
70
+ app/models/user.rb
71
+ no_malformed_username: (=~/[@!#$\%&()*,^~{}|`=:;\\\/\[\]\?]/).?&&(=~/^[.]/).?&&(=~/[.]$/).?&&(=~/[.]{,}/).?.(:,.,,.)
72
+ send_mention_notification: (,)=.:=>=.:=>=://#{.}/=::.(.())=..=.(..)=::.(.,.)=.(.,,{-=>/-+})
73
+ edit_user_profile: ()[:].?[:].?[:]==[:].=[:]..=.==[:].=[:]..=[:].=[:].=[:].=[:]...
74
+ following_url?: ()=.(:=>).?.?(://#{.}/)=[/\/\/(.+)$/,]=[.(:=>)].?!(&).?!
75
+ send_unfollow_notification: ()=.:=>=::.(.,..)=..=.(..)=::.(.,.)=.(.,,{-=>/-+})
76
+ send_follow_notification: ()=.:=>=::.(.,..)=..=.(..)=::.(.,.)=.(.,,{-=>/-+})
77
+
78
+ [...]
79
+ ```
80
+
81
+ Look at these two signatures from app/models/discussion_list.rb:
82
+
83
+ ```
84
+ send_unfollow_notification: ()=.:=>=::.(.,..)=..=.(..)=::.(.,.)=.(.,,{-=>/-+})
85
+ send_follow_notification: ()=.:=>=::.(.,..)=..=.(..)=::.(.,.)=.(.,,{-=>/-+})
86
+ ```
87
+
88
+ There's clearly something similar about them. Here's the source:
89
+
90
+ ```
91
+ # Send Salmon notification so that the remote user
92
+ # knows this user is following them
93
+ def send_follow_notification(to_feed_id)
94
+ f = Feed.first :id => to_feed_id
95
+
96
+ salmon = OStatus::Salmon.from_follow(author.to_atom, f.author.to_atom)
97
+
98
+ envelope = salmon.to_xml self.to_rsa_keypair
99
+
100
+ # Send envelope to Author's Salmon endpoint
101
+ uri = URI.parse(f.author.salmon_url)
102
+ http = Net::HTTP.new(uri.host, uri.port)
103
+ res = http.post(uri.path, envelope, {"Content-Type" => "application/magic-envelope+xml"})
104
+ end
105
+
106
+ # Send Salmon notification so that the remote user
107
+ # knows this user has stopped following them
108
+ def send_unfollow_notification(to_feed_id)
109
+ f = Feed.first :id => to_feed_id
110
+
111
+ salmon = OStatus::Salmon.from_unfollow(author.to_atom, f.author.to_atom)
112
+
113
+ envelope = salmon.to_xml self.to_rsa_keypair
114
+
115
+ # Send envelope to Author's Salmon endpoint
116
+ uri = URI.parse(f.author.salmon_url)
117
+ http = Net::HTTP.new(uri.host, uri.port)
118
+ res = http.post(uri.path, envelope, {"Content-Type" => "application/magic-envelope+xml"})
119
+ end
120
+ ```
121
+
122
+ Definitely some kind of duplication there, and these methods aren't
123
+ right next to each other in the source.
124
+
125
+ And it helps us find really long methods, like these bad boys:
126
+
127
+ ```
128
+ app/models/update.rb
129
+ generate_html: =.().!(/([]?:\/\/\+[---\/}])/,<=\\>\\</>).!()||$=.(:=>/^#{$}$/,:=>/^#{$}$/)=..?(/)=://#{.}#{}#{$}<=#{}>@#{$}@#{$}</>$=.(:=>/^#{$}$/)=..?(/)=://#{.}#{}#{$}<=#{}>@#{$}</>.!(/(^|\+)#(\+)/)||#{$}<=/?=%#{$}>##{$}</>.=
130
+ ```
131
+
132
+ ## TODOS
133
+
134
+ * break it up & test it a bit.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new
4
+ task :default => :test
data/lib/puncsig.rb ADDED
@@ -0,0 +1,78 @@
1
+ module Puncsig
2
+
3
+ class FileReport
4
+ attr_reader :filename
5
+
6
+ def initialize(filename, method_sigs)
7
+ @filename = filename
8
+ @method_sigs = method_sigs
9
+ end
10
+
11
+ def method_names
12
+ @method_sigs.keys
13
+ end
14
+
15
+ # Not sure this is how it'll end up...
16
+ def method_sigs
17
+ @method_sigs
18
+ end
19
+ end
20
+
21
+ class Parser
22
+ def parse(filename)
23
+ src = src(filename)
24
+ methods = methods(src)
25
+ method_sigs = Hash[*methods.map { |name, src| [name, puncsig(src)] }.flatten]
26
+ FileReport.new(filename, method_sigs)
27
+ end
28
+
29
+ private
30
+
31
+ def src(path)
32
+ File.read(path).gsub(/^\s*#.*$/, '')
33
+ end
34
+
35
+ # Note: for models, this ignores stuff like named_scopes, etc. That's ok for now, and maybe ok for later.
36
+ def methods(src)
37
+
38
+ # TODO This leaves out methods like [], <<, etc...maybe just check for first non-space?
39
+ method_sigs = /def\s+[a-z_!?.]+/
40
+ method_names = src.scan(method_sigs).map { |sig| sig.sub(/^def /, '') }
41
+
42
+ bodies = src.split(method_sigs)[1..-1] # strip off first chunk, the class beginning
43
+
44
+ method_names.zip(bodies)
45
+ end
46
+
47
+ def puncsig(src)
48
+ src.gsub(/[a-z0-9'"_\s]/i, '')
49
+ end
50
+
51
+ end
52
+
53
+ class Report
54
+
55
+ def initialize(*filename_methods)
56
+ @filenames = filename_methods.flatten
57
+ end
58
+
59
+ def run
60
+ parser = Parser.new
61
+
62
+ @filenames.each do |filename|
63
+
64
+ file_report = parser.parse(filename)
65
+ len = file_report.method_names.map(&:size).max
66
+
67
+ puts file_report.filename
68
+ file_report.method_sigs.sort_by { |n, s| -s.size }.each do |name, sig|
69
+ print "#{name}:".ljust(len + 3)
70
+ puts sig
71
+ end
72
+ puts
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ require 'puncsig/railtie' if defined?(Rails)
@@ -0,0 +1,12 @@
1
+ require 'puncsig'
2
+ require 'rails'
3
+
4
+ module Puncsig
5
+ class Railtie < Rails::Railtie
6
+ railtie_name :puncsig
7
+
8
+ rake_tasks do
9
+ load "tasks/puncsig.rake"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Puncsig
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,51 @@
1
+ require 'puncsig'
2
+
3
+ namespace :puncsig do
4
+ desc "Run puncsig on the whole app"
5
+ task :all do
6
+ Puncsig::Report.new(controllers + models + helpers + lib).run
7
+ end
8
+
9
+ desc "Run puncsig on just the models"
10
+ task :models do
11
+ Puncsig::Report.new(models).run
12
+ end
13
+
14
+ desc "Run puncsig on just the controllers"
15
+ task :controllers do
16
+ Puncsig::Report.new(controllers).run
17
+ end
18
+
19
+ desc "Run puncsig on just the helpers"
20
+ task :helpers do
21
+ Puncsig::Report.new(helpers).run
22
+ end
23
+
24
+ desc "Run puncsig on just the files in lib"
25
+ task :lib do
26
+ Puncsig::Report.new(lib).run
27
+ end
28
+
29
+
30
+
31
+ def controllers
32
+ all_under("app/controllers")
33
+ end
34
+
35
+ def models
36
+ all_under("app/models")
37
+ end
38
+
39
+ def helpers
40
+ all_under("app/helpers")
41
+ end
42
+
43
+ def lib
44
+ all_under("lib")
45
+ end
46
+
47
+ def all_under(dir)
48
+ Dir.glob(File.join(dir, '**/*.rb'))
49
+ end
50
+
51
+ end
data/puncsig.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ require './lib/puncsig/version'
2
+
3
+ spec = Gem::Specification.new do |s|
4
+ s.name = 'puncsig'
5
+ s.version = Puncsig::VERSION
6
+
7
+ s.summary = %{
8
+ PuncSig: Punctuation Signatures for your ruby methods
9
+ }.strip.gsub(/\s+/, ' ')
10
+
11
+ s.description = %{
12
+
13
+ A method's punctuation signature is its source, minus all letters,
14
+ numbers, and whitespace. It can help you find similar methods,
15
+ find long methods, and see how your methods are balanced.
16
+
17
+ PuncSig parses your ruby classes and prints a report on your
18
+ classes' punctuation signatures.
19
+
20
+ }.strip.gsub(/\s+/, ' ')
21
+
22
+ s.files = Dir['lib/**/*.rb'] + Dir['test/**/*.rb'] + %w[
23
+ README.md
24
+ Rakefile
25
+ lib/tasks/puncsig.rake
26
+ puncsig.gemspec
27
+ ]
28
+
29
+ s.require_path = 'lib'
30
+ s.required_ruby_version = ">= 1.8.7"
31
+
32
+ s.author = "Dan Bernier"
33
+ s.email = "danbernier@gmail.com"
34
+ s.homepage = "https://github.com/danbernier/puncsig"
35
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: puncsig
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dan Bernier
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-31 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A method's punctuation signature is its source, minus all letters, numbers,
15
+ and whitespace. It can help you find similar methods, find long methods, and see
16
+ how your methods are balanced. PuncSig parses your ruby classes and prints a report
17
+ on your classes' punctuation signatures.
18
+ email: danbernier@gmail.com
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - lib/puncsig/railtie.rb
24
+ - lib/puncsig/version.rb
25
+ - lib/puncsig.rb
26
+ - README.md
27
+ - Rakefile
28
+ - lib/tasks/puncsig.rake
29
+ - puncsig.gemspec
30
+ homepage: https://github.com/danbernier/puncsig
31
+ licenses: []
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: 1.8.7
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 1.8.10
51
+ signing_key:
52
+ specification_version: 3
53
+ summary: ! 'PuncSig: Punctuation Signatures for your ruby methods'
54
+ test_files: []