Created
March 12, 2012 00:06
-
-
Save aokj4ck/2018777 to your computer and use it in GitHub Desktop.
Comment Spell Check with incomplete support for ignored words file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'raspell' | |
class CommentSpellCheck | |
SP = Aspell.new("en") #initialize our spell checker | |
SP.suggestion_mode = Aspell::NORMAL | |
SP.set_option("ignore-case", "false") #case sensitivity is important to us | |
# Regex to find text within documentation code comments, not plain // comments or regular block comments /* */. Only /** */ comments | |
@@comment_regex = /\/\*([\w\d\W\D]+?)\*\// | |
# List of words we can safely ignore as language constructs, language keywords, jargon, or documentation keywords | |
@@ignored_words = ['struct', 'iOS', 'rect', 'param'] | |
# Find all the misspellings and potential errors in a file | |
def self.misspelledWords(string, path) | |
# Store all the wrong words and potential errors | |
wrongWords = Array.new | |
probablySpeltRight = Array.new | |
# Determine what file we are in by getting the last element of the path when split by forward slashes | |
filename = path.split('/')[-1] | |
# Split the file by the comment finding regex | |
string.scan(@@comment_regex) {|comment| | |
for line in comment #find each line of a comment | |
for word in line.split(' ') #find each word of a line of a comment | |
word.gsub!(/([\W\d]+)/, '') #cut out non-word and numeric characters | |
# I sure hope you don't use numbers in your variable names | |
word.strip! #strip out any whitespace, just in case | |
# Iterate through the list of ignoreable words and ignore any ones we meet | |
@@ignored_words.each { |ignoreMe| | |
if word == ignoreMe | |
word = '' | |
break | |
end | |
} | |
first_suggestion = SP.suggest(word)[0] | |
second_suggestion = SP.suggest(word)[1] | |
# A camel case word is probably okay to ignore | |
# being a variable or other programming construct | |
if hasInnerCapital(word) | |
# Add to list of probably safely ignored | |
# Add the filename to the warned word indenting it first | |
item = "\e[33m" + word + "\e[0m" + "\t in #{filename}" | |
if first_suggestion != nil | |
item += "\n did you mean \e[32m#{first_suggestion}\e[0m or \e[32m#{second_suggestion}\e[0m?" | |
end | |
probablySpeltRight << item | |
next | |
end | |
# Check if this word is: spelled wrong, ascii characters only, | |
# not a word with >2 capitals in a row signifying an Objective-C | |
# namespace prefixed construct, and not equal to the empty string | |
if isValidWord(word) # Switch this to `word.isValidWord?` | |
# Add the filename to the misspelled word indenting it first | |
item = "\e[31m" + word + "\e[0m" + "\t in #{filename}" | |
if first_suggestion != nil | |
item += "\n did you mean \e[35m#{first_suggestion}\e[0m or \e[35m#{second_suggestion}\e[0m?" | |
end | |
wrongWords << item | |
end | |
end | |
end | |
} | |
# Make sure that each element only occurs once and return the errors and warnings | |
return wrongWords.uniq, probablySpeltRight.uniq | |
end | |
# Check if this word is: spelled wrong, ascii characters only, | |
# not a word with >2 capitals in a row signifying an Objective-C | |
# namespace prefixed construct, and not equal to the empty string | |
def self.isValidWord string | |
return (!SP.check(string) and string.ascii_only? and !hasObjective_CNamePrefix(string) and string != '') | |
end | |
# Check if this string begins with two or more capitals | |
# which signifies that it is a string with an Objective-C | |
# namespace prefix, we ignore these | |
def self.hasObjective_CNamePrefix string | |
capsCount = 0 | |
for letter in string.each_char | |
if letter.upcase == letter | |
capsCount += 1 | |
if capsCount > 2 | |
return true | |
end | |
else | |
return false | |
end | |
end | |
return false | |
end | |
# Check if there is an inner capitalization: exampleString | |
# which are often used in variables | |
# used to put matches in potential errors list | |
def self.hasInnerCapital string | |
result = string.scan(/([a-z]+[A-Z]+[a-z]+)/) | |
if result.count == 1 | |
return true | |
else | |
return false | |
end | |
end | |
# Given a directory, it will scan it for all .h files and spell check comments | |
def self.spellCheck(path = nil, ignoreFile = nil) | |
# Load a text file of other words to ignore and append it to class list of ignored words | |
if ignoreFile | |
importedIgnoreFile = File.open(ignoreFile, 'r') | |
userIgnore = importedIgnoreFile.read.split('\n') | |
@@ignored_words << userIgnore | |
@@ignored_words.flatten! | |
importedIgnoreFile.close | |
end | |
puts @@ignored_words | |
if path | |
path = File.expand_path(path) | |
allObjCFiles = Dir.glob(path + '/**/*.h') # Recursively search path and subdirectories | |
else | |
allObjCFiles = Dir.glob('**/*.h') # Recursively search present directory | |
end | |
# Store the results of each file's spell check split into errors and warnings | |
errors = Array.new | |
potentialErrors = Array.new | |
# Iterate through each file | |
allObjCFiles.each { |path| | |
# Read the file | |
input = File.open(path, 'r') | |
text = input.read | |
# Calculate misspellings and potential misspellings | |
# don't worry about duplicates or empty strings | |
# as `misspelledWords() takes care of them | |
misspellings, probablyRight = self.misspelledWords(text, path) | |
errors << misspellings | |
potentialErrors << probablyRight | |
input.close | |
} | |
if errors.count > 0 | |
# Color Errors red, print each error | |
puts "\e[1mSpelling Errors:\e[0m" | |
errors.each {|error| | |
puts error | |
} | |
else | |
puts "\e[1mNo errors! :D\e[0m" | |
end | |
if potentialErrors.count > 0 | |
# Color Warnings yellow, print each warning | |
puts "\e[1m\nSpelling Warnings:\e[0m" | |
potentialErrors.each {|perror| | |
puts perror | |
} | |
else | |
puts "\e[1m\nNo warnings! :D\e[0m" | |
end | |
end | |
end | |
# Go! | |
path = ARGV[0] | |
ignoredWordFile = ARGV[1] | |
if path | |
CommentSpellCheck.spellCheck(path, ignoredWordFile) | |
else | |
CommentSpellCheck.spellCheck('.', nil) | |
end | |
# |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
parseError | |
systemVersion | |
px | |
currentDevice | |
textSize | |
xib | |
iAd | |
LinkShare | |
iPad | |
Bombr | |
iPads | |
iAds | |
iMessage |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment