Capitalizes words according to typical English titling conventions

Hi All,

Another automating and scripting request. Is it possible to embed and run the Perl script below as a script within DEVONthink 3? The Source of this script is from the PopClip Title Case Extension here which uses U.K. titling conventions.

What I’d like to achieve, is to select a number of records I wish to convert to Title Case (using this perl script) and have DT3 rename all those files via a script action.

Any help with this would be greatly appreciated! Thank you for your help in advance. :grinning:

p.s. I’m still a total noob at scripting so am pretty hopeless when knowing exactly what I need to do to make this work. I know Keyboard Maestro might also be an option… But working out how to execute this script is still beyond me.

Perl Script:

#!/usr/bin/perl

# 	This filter changes all words to Title Caps, and attempts to be clever
#	about *un*capitalizing 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'. 
#
#	10 May 2008
#	Original version by John Gruber:
#	http://daringfireball.net/2008/05/title_case
#
#	28 July 2008
#	Re-written and much improved by Aristotle Pagaltzis:
#	http://plasmasturm.org/code/titlecase/
#
#   Full change log at __END__.
#
#	License: http://www.opensource.org/licenses/mit-license.php
#


use strict;
use warnings;
use utf8;
use open qw( :encoding(UTF-8) :std );


my @small_words = qw( (?<!q&)a an and as at(?!&t) but by en for if in of on or the to v[.]? via vs[.]? );
my $small_re = join '|', @small_words;

my $apos = qr/ (?: ['’] [[:lower:]]* )? /x;

while ( <> ) {
	#s{\A\s+}{}, s{\s+\z}{};

	$_ = lc $_ if not /[[:lower:]]/;

	s{
		\b (_*) (?:
			( (?<=[ ][/\\]) [[:alpha:]]+ [-_[:alpha:]/\\]+ |   # file path or
			  [-_[:alpha:]]+ [@.:] [-_[:alpha:]@.:/]+ $apos )  # URL, domain, or email
			|
			( (?i: $small_re ) $apos )                         # or small word (case-insensitive)
			|
			( [[:alpha:]] [[:lower:]'’()\[\]{}]* $apos )       # or word w/o internal caps
			|
			( [[:alpha:]] [[:alpha:]'’()\[\]{}]* $apos )       # or some other word
		) (_*) \b
	}{
		$1 . (
		  defined $2 ? $2         # preserve URL, domain, or email
		: defined $3 ? "\L$3"     # lowercase small word
		: defined $4 ? "\u\L$4"   # capitalize word w/o internal caps
		: $5                      # preserve other kinds of word
		) . $6
	}xeg;


	# Exceptions for small words: capitalize at start and end of title
	s{
		(  \A [[:punct:]]*         # start of title...
		|  [:.;?!][ ]+             # or of subsentence...
		|  [ ]['"“‘(\[][ ]*     )  # or of inserted subphrase...
		( $small_re ) \b           # ... followed by small word
	}{$1\u\L$2}xig;

	s{
		\b ( $small_re )      # small word...
		(?= [[:punct:]]* \Z   # ... at the end of the title...
		|   ['"’”)\]] [ ] )   # ... or of an inserted subphrase?
	}{\u\L$1}xig;

	# Exceptions for small words in hyphenated compound words
	## e.g. "in-flight" -> In-Flight
	s{
		\b
		(?<! -)					# Negative lookbehind for a hyphen; we don't want to match man-in-the-middle but do want (in-flight)
		( $small_re )
		(?= -[[:alpha:]]+)		# lookahead for "-someword"
	}{\u\L$1}xig;

	## # e.g. "Stand-in" -> "Stand-In" (Stand is already capped at this point)
	s{
		\b
		(?<!…)					# Negative lookbehind for a hyphen; we don't want to match man-in-the-middle but do want (stand-in)
		( [[:alpha:]]+- )		# $1 = first word and hyphen, should already be properly capped
		( $small_re )           # ... followed by small word
		(?!	- )					# Negative lookahead for another '-'
	}{$1\u$2}xig;

	print "$_";
}

__END__

Changes:

Thu, 06 Nov 2014

- Removed /o switch from substitutions; it's out-dated and described now as only "pretending" to optimize
- Special cases for small words in two-word compounds, like "stand-in" and "in-flight" (but not "man-in-the-middle")

Shell:

result=`echo $POPCLIP_TEXT | perl titlecase.pl`

/bin/echo -n $result

@BLUEFROG I’d be grateful for any suggestions this one :blush:

This doesn’t do exactly what Gruber’s script does, but this will titlecase a record’s name…

use framework "Foundation"
use scripting additions

tell application id "DNtp"
	repeat with thisRecord in (selection as list)
		set ns to (current application's NSString's stringWithString:(name of thisRecord as string))
		set (name of thisRecord) to ((ns's capitalizedString) as string)
	end repeat
end tell

Much appreciated :blush:

No problem.
It’s definitely not a teaching edition script (as AppleScript Objective-C is not beginner material), but it was a quick way to appraoch this.

You should be able to use “do shell script …” in an AppleScript (much like what you posted as your command line). Also, there’s the “Execute” submenu in DT3’s “Script” menu, where I have a “run perl script” script.

However, as far as I know, Perl is now longer automatically installed on Mac OS. So you might want to make sure that your Perl script runs on the command line.

However, as far as I know, Perl is now longer automatically installed on Mac OS.

Perl is still included in the base installation of macOS.

You’re right obviiously. I had read about Apple not including Perl, Python et al any more last year, but apparently they are still there. But not for very much longer: https://developer.apple.com/documentation/macos_release_notes/macos_catalina_10_15_release_notes

@BLUEFROG and @chrillek I’m so jealous of your wealth of knowledge you guys have accumulated over the years through much hard work and graft… I have so much I’m trying to achieve within DEVONthink and so little usable knowledge :woman_facepalming: Learning Applescript is slow going! (So far I’ve managed to make my mac pop-up “Hello World”, beep a few times and create an icon I can open a new document in my Screenwriting app, Highland 2… Wouldn’t even know where or how to start applying perl, figuring how to extract the perl script and shell from a PopClip extension package was a challenge in itself :sweat_smile:

At this early stage of learning… definitely relying on shoulders of giants to stand on :wink:

Thank you both for your help and advice.

You’re very welcome :slight_smile: