public
Description: A Ruby port of John Gruber's TitleCase Perl script
Homepage:
Clone URL: git://github.com/samaaron/titlecase-rb.git
titlecase-rb / title_case.rb
100755 63 lines (53 sloc) 2.448 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!/usr/bin/env ruby
 
# This filter changes all words to Title Caps, and attempts to be clever
# about *un*capitalising small words like a/an/the in the input.
#
# The list of "small words" which are not capped comes from
# the New York Times Manual of Style, plus 'vs' and 'v'.
#
# Sam Aaron
# http://sam.aaron.name
# 21st of May, 2008
#
# This is a Ruby port of the original Perl script written by John Gruber
# http://daringfireball.net/2008/05/title_case
#
# License: http://www.opensource.org/licenses/mit-license.php
#
 
small_words = %w(a an and as at but by en for if in of on or the to v[.]? via vs[.]?)
 
#define regexps
SMALL_WORDS = /\b#{small_words.join('\b|\b')}\b/i
LAST_WORD_IS_A_SMALL_WORD = /\b(#{small_words.join('|')})([[:punct:]]*)\Z/
FIRST_WORD_IS_A_SMALL_WORD = /\A([[:punct:]]*)(#{small_words.join('|')})\b/
ENDING_PUNCTUATION_OR_STARTING_QUOTES = /( [:.;?!][ ] | (?:[ ]|^)["] )/x
WORDS_WHERE_THE_SECOND_CHAR_IS_LOWERCASE = /\b([[:alpha:]][[:lower:].']*)\b/
WORDS_CONTAINING_A_PERIOD = /[[:alpha:]][.][[:alpha:]]/
 
while(input_line = gets) do
 
    capitalised_line = input_line.split(ENDING_PUNCTUATION_OR_STARTING_QUOTES).map do |part|
      part.gsub!(WORDS_WHERE_THE_SECOND_CHAR_IS_LOWERCASE) do
        match = $1
        if (match !~ WORDS_CONTAINING_A_PERIOD and match =~ WORDS_WHERE_THE_SECOND_CHAR_IS_LOWERCASE)
          match = match.downcase.capitalize
        end
        
        if match =~ SMALL_WORDS
          match = match.downcase
        end
        match
      end
      
      # If the first word in the title is a small word, then capitalise it:
      part.gsub!(FIRST_WORD_IS_A_SMALL_WORD) do
        $1 + $2.capitalize
      end
             
      # If the last word in the title is a small word, then capitalise it:
      part.gsub!(LAST_WORD_IS_A_SMALL_WORD) do
        $1.capitalize + $2
      end
      part
    end.join
    
    #Special Cases:
    capitalised_line.gsub!(/V(s?)\. /) {'v' + $1 + '. '} # "v." and "vs."
    capitalised_line.gsub!(/(['])S\b/) {$1 + 's'} # 'S (otherwise you get "the SEC'S decision")
    capitalised_line.gsub!(/\b(AT&T|Q&A)\b/i){$1.upcase} # "AT&T" and "Q&A", which get tripped up by
                                                                # self-contained small words "at" and "a"
    puts capitalised_line
    
end