Code covered by the BSD License  

Highlights from
TextTools

from TextTools by Perttu Ranta-aho
Collection of small macros for text manipulation

fHandle=TextTools(MacroName)
function fHandle=TextTools(MacroName)
% TextTools - Collection of small macros for text manipulation
%
% Syntax:
%    tt = TextTools;
%    ttMacro = TextTools(MacroName)
%
% Description:
%    TextTools provides a small collection of macros for text manipulation. It
%    is intended to be used together with EditorMacro
%    http://www.mathworks.com/matlabcentral/fileexchange/24615.
%
%    Optional input argument MACRONAME selects one of the macros. Without
%    input arguments ?funtion returns a struct containing function handles to
%    all available macros.
% 
%    Included macros are:
%      transpose_chars - Swap characters around the caret
%      transpose_words - Swap words around the caret
%      capitalize      - Capitalize word starting from caret location
%      fill_comment    - Wrap current comment paragraph. Opposite to Matlab
%                        Editors wrap menu action no selection is needed. 
% 
%
% Examples:
%    tt = TextTools;
%    EditorMacro('Alt-Q',tt.fill_comment,'run')
% 
% 
% Warning:
%    This code heavily relies on undocumented and unsupported Matlab
%    functionality. Use at your own risk!
%
%
% Known issues (TODO):
%  - There are some edge cases where fill_comment doesn't work properly.
%  - fill_document produces two undo-steps.
%
%
% Bugs and suggestions:
%    Please send to Perttu Ranta-aho (rantaaho at gmail dot com)

% Perttu Ranta-aho, <rantaaho (at) gmail dot com>
% $Revision: 1.1 $ $Date: 2009/08/24 21:36:06 $


error(nargchk(0, 1, nargin, 'struct'))

fHandles = struct(...
    'transpose_chars',@transpose_chars,...
    'transpose_words',@transpose_words,... 
    'fill_comment',@fill_comment, ...
    'capitalize',@capitalize ...
    );
if nargin
    try
        fHandle=fHandles(MacroName);
    catch %#ok<CTCH>
        error('PRa:TextTools:InvalidArg','Invalid MacroName.')
    end
else
    fHandle = fHandles;
end


    function capitalize(hDocument,eventData) %#ok<INUSD>
        % Capitalize from current position
        caret = hDocument.getCaretPosition;
        wordEnd = hDocument.getWordEndFromPos(caret);
        hDocument.select(caret,wordEnd)
        txt = char(hDocument.getSelectedText);
        newTxt = [upper(txt(1)),lower(txt(2:end))];
        hDocument.replaceSelection(newTxt);
    end % capitalize 


    function fill_comment(hDocument,eventData) %#ok<INUSD>
        % Wrap current comment paragraph.
        commentWidth = com.mathworks.services.Prefs.getIntegerPref('EditorMaxCommentWidth');
        if commentWidth == 0,
            commentWidth = 75;
        end
        caretLine = hDocument.getLineStart(l_getCaretLine(hDocument));
        txt = char(hDocument.getTextStartEnd(0,caretLine));
        paraPat = {'^\s*([^% ]|%%|%\s*$)','lineanchors','dotexceptnewline'};
        m = regexp(txt,paraPat{:});
        startInd = hDocument.getLineEndFromPos(m(end)+1)+1;
        txt = char(hDocument.getTextStartEnd(caretLine,hDocument.getLength));
        m = regexp(txt,paraPat{:});
        endInd = caretLine+m(1)-1;
        para = char(hDocument.getTextStartEnd(startInd,endInd));
        outerIndent = find(para=='%',1)-1;
        innerIndent = max(find(para(outerIndent+2:end)~= ' ',1)-1,1);
        para = regexprep(para,'^\s*\%\s?','','lineanchors');
        para = strtrim(regexprep(para,'\s+',' ','lineanchors'));
        newTxt = textwrap({para},commentWidth-outerIndent-innerIndent);        
        newTxt = strcat(...
            repmat({['%',repmat(' ',1,innerIndent)]},size(newTxt,1),1), ...
            newTxt,...
            repmat({sprintf('\n')},size(newTxt,1),1));
        newTxt = cat(2,newTxt{:});
        try
            hDocument.select(startInd,endInd);
            awtinvoke(hDocument.java, 'replaceSelection', newTxt);
            hDocument.select(startInd,startInd+numel(newTxt));
            % hDocument.startBlockEdit; % Store only one undo-able action, doesn't work :(
            % l_builtinAction(hDocument,'comment')            
            l_builtinAction(hDocument,'format') % Proper indent
            % hDocument.endBlockEdit,
        catch ME %#ok<NASGU>
            %disp(ME.message)
        end
    end % fill_comment


    function l_builtinAction(jHandle,actionID)
        % Call built-in action 
        import java.awt.event.ActionEvent;
        action = jHandle.getActionMap.get(actionID);
        actionEvent = ActionEvent(jHandle, ActionEvent.ACTION_PERFORMED, actionID);
        awtinvoke(action,'actionPerformed(Ljava.awt.event.ActionEvent;)',actionEvent,'');
    end % l_builtinAction


    function line = l_getCaretLine(hDocument)
        % Return current line number
        pos = hDocument.getCaretPosition;
        line = hDocument.getLineFromPos(pos);
    end % l_getCaretLine


    function transpose_chars(hDocument,eventData) %#ok<INUSD>
        % Transpose characters, similar to Emacs transpose-chars
        caret = hDocument.getCaretPosition;
        lngth = hDocument.getLength;
        if caret == 0 || caret == lngth,
            % caret is before the first character in the first line
            % or after the last character in the document
           return
        end
        pair = char(hDocument.getTextStartEnd(caret - 1, caret+1));
        hDocument.select(caret-1, caret+1);
        awtinvoke(hDocument.java, 'replaceSelection',fliplr(pair))
    end % transpose_chars


    function transpose_words(hDocument,eventData) %#ok<INUSD>
        % Transpose words, similar to Emacs transpose-words
        % Multiline version
        chunkSize = 100; 
		offset = hDocument.getCaretPosition;
        chunkStart = max(0,offset-chunkSize);
		textChunk = char(hDocument.getTextStartEnd(chunkStart,...
            min(offset+chunkSize,hDocument.getLength)));
        [words, wordStart, wordEnd] = regexp(textChunk,'\w+',...
            'match','start','end');
        % Find the word on the left side
        lWordInd = find((wordStart-(offset-chunkStart)-1)<0,1,'last');
        if isempty(lWordInd),
            lWordInd = 1;
        elseif lWordInd == numel(words)
            % Last word, do nothing.
            return
        end
        % next word is the right side one
        rWordInd = lWordInd + 1;
        % Characters between two words
        sep = textChunk(wordEnd(lWordInd)+1:wordStart(rWordInd)-1);
        % Convert local indeces to global
        wordStart = wordStart + chunkStart - 1;
        wordEnd = wordEnd + chunkStart;
        % Do replacing in one operation to have only one "undo" step.
        hDocument.select(wordStart(lWordInd),wordEnd(rWordInd));
        awtinvoke(hDocument.java, 'replaceSelection',...
            [words{rWordInd},sep,words{lWordInd}]);
    end % transpose_words

end % TextTools

Contact us at files@mathworks.com