The proposal is that the trim functions (trim, triml, and trimr) would get a second arity with a function {{trim?}}:
[trim? ^CharSequence s]
{{trim?}} comes first to support partial.
New doc string would be: 
"Removes characters from both ends of string. 
 If trim? is omitted white space is removed. When supplied it accepts 
 a character and returns true if the character should be removed." 
Example test: 
(deftest t-trim 
  (is (= "foo" (s/trim "  foo  \r\n"))) 
  (is (= "bar" (s/trim "\u2000bar\t \u2002"))) 
  ;; Additional test 
  (is (= "bar" (s/trim "$%#\u2000bar\t \u2002%$#" 
                       #(or (Character/isWhitespace %) ((set "$#%") %)))))) 
Similar to Python's strip - 
https://docs.python.org/2/library/stdtypes.html#str.strip
*Approach:* The proposed solution isn't very DRY but it follows the design guidelines at the top of the file, more exactly point 3:
"3. Functions take advantage of String implementation details to
   write high-performing loop/recurs instead of using higher-order
   functions. (This is not idiomatic in general-purpose application
   code.)"
First I had a solution in which I replaced Character/isWhitespace from the current implementation by calling pred. pred was defaulted to an is-whitespace? function.
That code is of course nicer, even trim-newline could just call into trimr, removing a lot of duplication, but it adds the overhead of always calling a function, instead of calling Character/isWhitespace directly.
The only way I can see to have optimised and DRYer code is to use macros, but I don't think that it will necessary lead to nicer code.
Given the existing design style of the other functions in string.clj I felt that the best solution would be to just simply duplicate in favour of optimised code.