Vico home blog download feedback

1
votes

Automatically hard-wrap text (:set textwidth=72)

Is there a way to make Vico automatically insert a new line (the behavior of VIM when you :set textwidth to something other than 0)?

Comments

The textwidth option is not implemented in Vico.

But can I script it?

I'm thinking of a adding a listener to didModifyDocument and manually inserting return after line goes over predefined width.

Will this work or this having a listener hooked on every change may prove taxing?

Sure you can! Well, to be able to give you a positive answer, I had to try it myself:

(global NSMaxRange (do (range) (+ (range first) (range second))))
(global NSBackwardsSearch 4)
(set $textwidth 72) ; set to zero to disable
(if (defined $autoTextWrapEventId)
  (eventManager remove:$autoTextWrapEventId))
(set $autoTextWrapEventId (eventManager on:"didModifyDocument" do:(do (doc range delta)
  ; Only wrap lines when inserting, and only in text documents, not in source code.
  (if (and (gt $textwidth 0) (gt delta 0) (((doc language) name) hasPrefix:"text."))
    ; The range parameter is wrapped in an NSValue object.
    (set range (range rangeValue))
    (set location (range first))
    (set textStorage (doc textStorage))
    (set lineRange (textStorage rangeOfLineAtLocation:location))
    ; Insert a newline if inserting at column > $textwidth.
    (set column (- location (lineRange first)))
    (if (gt column $textwidth)
      ; Find first space before the wrapping column.
      (set preRange `(,(lineRange first) ,$textwidth))
      (set wrapRange ((textStorage string) rangeOfCharacterFromSet:(NSCharacterSet whitespaceCharacterSet)
                                                           options:NSBackwardsSearch
                                                             range:preRange))
      (if (eq (wrapRange first) NSNotFound)
        ; If no space found before, look after.
        (set postRange `(,$textwidth ,(- (NSMaxRange lineRange) $textwidth)))
        (set wrapRange ((textStorage string) rangeOfCharacterFromSet:(NSCharacterSet whitespaceCharacterSet)
                                                             options:0
                                                               range:postRange)))
      ; Replace the whitespace with a newline, if found.
      (unless (eq (wrapRange first) NSNotFound)
        ((doc text) replaceRange:wrapRange withString:"\n")) )))))

Add a new comment »