Kadner - 2014-09-22

Updated 2022/03/31
Moved python-code in separate downloadable file. Precious code indentation and lines were missing on earlier version of post due to errors in formatting ...

Updated 2015/04/21
Made code cleaner.
Expanded to include all possible matching bracket pairs.
Included 2-selections concept from Davey https://sourceforge.net/p/npppythonscript/discussion/1199074/thread/4691495a/#d4a9 .

I thought I would share this code as a token of appreciation after having learned from reading code examples from so many other programmers.
filename : Swap_Items.py
Thank you all 'pythoners'. Comments are welcome!

~~~~~~
PURPOSE
There is often a need to switch the position of 2 items in a text, especially
when writing code.
An item here refers to a word, a function and it's parameter, an array and it's
indices or only the contents between matching braces (including the braces).
The cumbersome, error-prone process involves 8 steps: Select item#1, Cut,
move cursor to item#2, Copy, Select item#2, Cut, move cursor back, Copy
This scripts provides 2 complementary solutions.

One-Selection Case
The script works by analysing the characters near where the selection starts and
ends to determine the size of the 2 items to swap.
It looks for word-characters and special word-delimiters, namely the
brace-pairs "()", "{}", "[]" and "<>".
Specifically, when the selection begins or ends
on any brace character, the contents of the 2 matching braces is itemized,
on a word followed by a non-brace character, a simple word is itemized,
on a word followed by any left-brace, the word and the contents of the
2 matching braces is itemized
e.g. an array-name and it's indices or a function-name and it's parameters
As a side-bonus, when selection is within a word, the first and last letters
of selection will be swapped.

2-Selections Case
The "1-selection" mode will not work for some 'unusual' swaps,
e.g.
trying to swap function- or array-names alone.
trying to swap 123 and 456 in +0.123 & -0.456
An alternate, specific swap code can be used in these cases.
It requires making 2 Selections and will result in the 2 items being swapped.
NB If one Selection is left "empty", if will be expanded to a whole word.

How to use:
Set a KB short-cut for swap script, i.e. Ctrl-Shift-X
Make the appropriate Selection(s). (Use Ctrl-LeftClick for a 2nd Selection).
(Depending on the number of selections, the corresponding code will run.)
Press the KB short-cut.
NB an unwanted swap result can allways be undone with Ctrl-Z

The default character set used for selecting whole word is modified to include -+.'"#.
This results in slightly different whole word compared to the default character set:
Numeric expressions such as 3, +4, #123, -6.5, \076, are considered as a whole word.
Single and double quotes will also be included in words.

There are 2 symmetrical sets of 3 rules when making a single Selection:
When selection STARTS on a word, the LeftItem will include the whole word.
When word is followed by a LeftBracket, the LeftItem will be expanded to the matching RightBracket.
When selection STARTS on a LeftBracket, the LeftItem will extend to the matching RightBracket
When selection STARTS on a RightBracket, the LeftItem will extend to the matching LeftBracket

When selection ENDS on a word, the RightItem will include the whole word.
When word is preceded by a RightBracket, the RightItem will be expanded to the matching LeftBracket.
When selection ENDS on a LeftBracket, the RightItem will extend to the matching RightBracket
When selection ENDS on a RightBracket, the RightItem will extend to the matching LeftBracket

Example:
Line1: word1 = word2 ; word3 = fn1(arg1) / (within_braces1) ; {comment1}
Line2: word4 = fn2(arg2, arr1[arg3], (within_braces2)) ;
Line3: a = "WZYX" ; b = 'abcd' ;
Line4: word5 = fn3(arr2[word6, 7], arg3, <within_braces3>) ; {comment2}
Line5: word6 = -0.123 ; word 7 = \076 ; word 7 = x0FF ; {x0F}
An almost infinite variety of 1-selection swaps are possible:
word1 & word2
word1 & word4
arg1 & word3
arr1[...] & arr2[...]
word1 & (within_braces1)
(within_braces1) & (within_braces2)
{comment1} & {comment2}
fn1(arg1) & fn2(arg2, arr1[arg3]
fn2(arg2, arr1[arg3], (within_braces2)) & <within_braces3>
"WZYX" & 'abcd'
char "Z" & char "X"
-0.123 & \076
x0FF & x0F
etc.
But 2 selections are necessary to swap:
fn1 & fn2
arr1 & arr2
etc.</within_braces3></within_braces3>

 

Last edit: Kadner 2022-03-31