Studly Previous

Summary: Jump to the previous intra-word. Works like a finer-grained Option-Leftarrow.
Requires: BBEdit 8 (similar functionality built-into BBEdit 8.5)
Suggested Key Binding: Control-Leftarrow
Last Modified: 2019-10-02

Description

This script brings CodeWarrior’s Control-Leftarrow functionality to BBEdit. It lets you jump between the parts of words with inner caps (a.k.a. studly caps or camel case). This is very useful for programmers who follow the Apple or Java naming conventions.

This script works like a finer-grained Option-Leftarrow. Instead of moving to the previous word, it moves to the previous capitalized part of a word. For instance, the underscored positions in: _set_Script_Error_Number_.

Installation Instructions · Download in Compiled Format · Download in Text Format

Script

property wordCharacters : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"

-- FIXME: asymmetry compared to Studly Next in that it jumps over runs of spaces

on run
    
tell application "BBEdit"
        
try
            
tell window 1
                
set oldOffset to characterOffset of selection
                
if oldOffset is 1 then return
                
set firstChar to character (oldOffset - 1) as string
                
set inWordNow to my isWordCharacter(firstChar)
                
repeat with newOffset from (oldOffset - 1) to 1 by -1
                    
if newOffset is 2 then
                        
select insertion point before character 1
                        
return
                    
end if
                    
set c to character newOffset as string
                    
-- FIXME: is there a way to run the loop so this can be clean, like in Studly Next?
                    
if inWordNow and not my isWordCharacter(c) then
                        
select insertion point after character newOffset
                        
return
                    
else if not inWordNow and my isWordCharacter(c) then
                        
select insertion point after character newOffset
                        
return
                    
else if my stopHere(c, inWordNow) or newOffset is 1 then
                        
select insertion point before character newOffset
                        
return
                    
end if
                
end repeat
            
end tell
        
end try
    
end tell
end run

on stopHere(c, inWordNow)
    
if isCapitalLetter(c) then
        
return true
    
else if inWordNow and not isWordCharacter(c) then
        
return true
    
else if not inWordNow and isWordCharacter(c) then
        
return true
    
else
        
return false
    
end if
end stopHere

on isCapitalLetter(c)
    
if (ASCII number of c) is greater than or equal to 65 ¬
        
and (ASCII number of c) is less than 97 then
        
return true
    
else
        
return false
    
end if
end isCapitalLetter

on isWordCharacter(c)
    
return wordCharacters contains c
end isWordCharacter