├── Main.sublime-menu ├── README.md ├── Smart Title Case.py ├── Smart Title Case.sublime-commands └── titlecase └── __init__.py /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "edit", 4 | "children": 5 | [ 6 | { 7 | "id": "convert_case", 8 | "children": 9 | [ 10 | { 11 | "caption": "Smart Title Case", 12 | "command": "smart_title_case" 13 | } 14 | ] 15 | } 16 | ] 17 | } 18 | ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The title case function that currently ships with Sublime capitalizes the first letter of every word regardless of context or size. This plugin adds a Smart Title Case command that wraps Stuart Colville's [Python implementation](http://muffinresearch.co.uk/archives/2008/05/27/titlecasepy-titlecase-in-python/) of John Gruber's [Title Case](http://daringfireball.net/2008/05/title_case). -------------------------------------------------------------------------------- /Smart Title Case.py: -------------------------------------------------------------------------------- 1 | import sublime, sublime_plugin 2 | 3 | try: 4 | from .titlecase import titlecase 5 | except ValueError: 6 | from titlecase import titlecase 7 | 8 | class SmartTitleCaseCommand(sublime_plugin.TextCommand): 9 | def run(self, edit): 10 | for region in self.view.sel(): 11 | if region.empty(): 12 | region = self.view.line(region) 13 | 14 | s = self.view.substr(region) 15 | s = titlecase(s) 16 | self.view.replace(edit, region, s) 17 | -------------------------------------------------------------------------------- /Smart Title Case.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Convert Case: Smart Title Case", 4 | "command": "smart_title_case" 5 | } 6 | ] -------------------------------------------------------------------------------- /titlecase/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Original Perl version by: John Gruber http://daringfireball.net/ 10 May 2008 6 | Python version by Stuart Colville http://muffinresearch.co.uk 7 | License: http://www.opensource.org/licenses/mit-license.php 8 | """ 9 | 10 | import re 11 | 12 | __all__ = ['titlecase'] 13 | __version__ = '0.5.1' 14 | 15 | SMALL = 'a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v\.?|via|vs\.?' 16 | PUNCT = r"""!"#$%&'‘()*+,\-./:;?@[\\\]_`{|}~""" 17 | 18 | SMALL_WORDS = re.compile(r'^(%s)$' % SMALL, re.I) 19 | INLINE_PERIOD = re.compile(r'[a-z][.][a-z]', re.I) 20 | UC_ELSEWHERE = re.compile(r'[%s]*?[a-zA-Z]+[A-Z]+?' % PUNCT) 21 | CAPFIRST = re.compile(r"^[%s]*?([A-Za-z])" % PUNCT) 22 | SMALL_FIRST = re.compile(r'^([%s]*)(%s)\b' % (PUNCT, SMALL), re.I) 23 | SMALL_LAST = re.compile(r'\b(%s)[%s]?$' % (SMALL, PUNCT), re.I) 24 | SUBPHRASE = re.compile(r'([:.;?!][ ])(%s)' % SMALL) 25 | APOS_SECOND = re.compile(r"^[dol]{1}['‘]{1}[a-z]+$", re.I) 26 | ALL_CAPS = re.compile(r'^[A-Z\s%s]+$' % PUNCT) 27 | UC_INITIALS = re.compile(r"^(?:[A-Z]{1}\.{1}|[A-Z]{1}\.{1}[A-Z]{1})+$") 28 | MAC_MC = re.compile(r"^([Mm]a?c)(\w+)") 29 | 30 | def titlecase(text): 31 | 32 | """ 33 | Titlecases input text 34 | 35 | This filter changes all words to Title Caps, and attempts to be clever 36 | about *un*capitalizing SMALL words like a/an/the in the input. 37 | 38 | The list of "SMALL words" which are not capped comes from 39 | the New York Times Manual of Style, plus 'vs' and 'v'. 40 | 41 | """ 42 | 43 | lines = re.split('[\r\n]+', text) 44 | processed = [] 45 | for line in lines: 46 | all_caps = ALL_CAPS.match(line) 47 | words = re.split('[\t ]', line) 48 | tc_line = [] 49 | for word in words: 50 | if all_caps: 51 | if UC_INITIALS.match(word): 52 | tc_line.append(word) 53 | continue 54 | else: 55 | word = word.lower() 56 | 57 | if APOS_SECOND.match(word): 58 | word = word.replace(word[0], word[0].upper()) 59 | word = word.replace(word[2], word[2].upper()) 60 | tc_line.append(word) 61 | continue 62 | if INLINE_PERIOD.search(word) or UC_ELSEWHERE.match(word): 63 | tc_line.append(word) 64 | continue 65 | if SMALL_WORDS.match(word): 66 | tc_line.append(word.lower()) 67 | continue 68 | 69 | match = MAC_MC.match(word) 70 | if match: 71 | tc_line.append("%s%s" % (match.group(1).capitalize(), 72 | match.group(2).capitalize())) 73 | continue 74 | 75 | hyphenated = [] 76 | for item in word.split('-'): 77 | hyphenated.append(CAPFIRST.sub(lambda m: m.group(0).upper(), item)) 78 | tc_line.append("-".join(hyphenated)) 79 | 80 | 81 | result = " ".join(tc_line) 82 | 83 | result = SMALL_FIRST.sub(lambda m: '%s%s' % ( 84 | m.group(1), 85 | m.group(2).capitalize() 86 | ), result) 87 | 88 | result = SMALL_LAST.sub(lambda m: m.group(0).capitalize(), result) 89 | 90 | result = SUBPHRASE.sub(lambda m: '%s%s' % ( 91 | m.group(1), 92 | m.group(2).capitalize() 93 | ), result) 94 | 95 | processed.append(result) 96 | 97 | return "\n".join(processed) 98 | 99 | --------------------------------------------------------------------------------