├── .gitignore
├── .project
├── .settings
└── org.eclipse.core.resources.prefs
├── .travis.yml
├── LICENSE
├── README.md
├── RELEASING
├── com.asparck.eclipse.multicursor.feature
├── .project
├── .settings
│ └── org.eclipse.core.resources.prefs
├── build.properties
├── feature.xml
└── pom.xml
├── com.asparck.eclipse.multicursor.p2updatesite
├── .project
├── .settings
│ └── org.eclipse.core.resources.prefs
├── category.xml
└── pom.xml
├── com.asparck.eclipse.multicursor.plugin
├── .classpath
├── .project
├── .settings
│ ├── org.eclipse.core.resources.prefs
│ ├── org.eclipse.jdt.core.prefs
│ └── org.eclipse.jdt.ui.prefs
├── META-INF
│ └── MANIFEST.MF
├── build.properties
├── plugin.xml
├── pom.xml
└── src
│ └── com
│ └── asparck
│ └── eclipse
│ └── multicursor
│ ├── Logger.java
│ ├── MultiCursorPlugin.java
│ ├── copied
│ └── DeleteBlockingExitPolicy.java
│ ├── hacks
│ └── ISourceViewerFinder.java
│ ├── handlers
│ ├── SelectAllOccurrencesHandler.java
│ └── SelectNextOccurrenceHandler.java
│ └── util
│ ├── CoordinatesUtil.java
│ └── TextUtil.java
├── com.asparck.eclipse.multicursor.target
├── .project
├── com.asparck.eclipse.multicursor.target.target
└── pom.xml
├── com.asparck.eclipse.multicursor.tests
├── .classpath
├── .project
├── .settings
│ ├── org.eclipse.core.resources.prefs
│ └── org.eclipse.jdt.core.prefs
├── META-INF
│ └── MANIFEST.MF
├── build.properties
├── pom.xml
└── src
│ └── com
│ └── asparck
│ └── eclipse
│ └── multicursor
│ ├── tests
│ └── Activator.java
│ └── util
│ └── TextUtilTest.java
├── pom.xml
├── redownload-p2-plugin-jars.sh
└── release.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | */bin
2 | */target
3 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.asparck.eclipse.multicursor.parent
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 1395452751685
14 |
15 | 10
16 |
17 | org.eclipse.ui.ide.multiFilter
18 | 1.0-name-matches-false-false-com.asparck.eclipse.multicursor.*
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding/=UTF-8
3 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk:
3 | - oraclejdk7
4 | # set the install script to 'true' succeed in installing without doing anything
5 | install: true
6 | script: mvn verify
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Eclipse Public License - v 1.0
2 |
3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
4 |
5 | 1. DEFINITIONS
6 |
7 | "Contribution" means:
8 |
9 | a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
10 | b) in the case of each subsequent Contributor:
11 | i) changes to the Program, and
12 | ii) additions to the Program;
13 | where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
14 | "Contributor" means any person or entity that distributes the Program.
15 |
16 | "Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
17 |
18 | "Program" means the Contributions distributed in accordance with this Agreement.
19 |
20 | "Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
21 |
22 | 2. GRANT OF RIGHTS
23 |
24 | a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
25 | b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
26 | c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
27 | d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
28 | 3. REQUIREMENTS
29 |
30 | A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
31 |
32 | a) it complies with the terms and conditions of this Agreement; and
33 | b) its license agreement:
34 | i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
35 | ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
36 | iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
37 | iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
38 | When the Program is made available in source code form:
39 |
40 | a) it must be made available under this Agreement; and
41 | b) a copy of this Agreement must be included with each copy of the Program.
42 | Contributors may not remove or alter any copyright notices contained within the Program.
43 |
44 | Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
45 |
46 | 4. COMMERCIAL DISTRIBUTION
47 |
48 | Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
49 |
50 | For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
51 |
52 | 5. NO WARRANTY
53 |
54 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
55 |
56 | 6. DISCLAIMER OF LIABILITY
57 |
58 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
59 |
60 | 7. GENERAL
61 |
62 | If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
63 |
64 | If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
65 |
66 | All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
67 |
68 | Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
69 |
70 | This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | What is this?
2 | =============
3 |
4 | An *aborted* attempt to provide Sublime-Text-like multi cursor support for text editors in the Eclipse IDE (3.7 and later).
5 |
6 | [](https://travis-ci.org/caspark/eclipse-multicursor)
7 |
8 | What works?
9 | -----------
10 |
11 | I intended to implement full multi cursor behaviour in this plugin, but stopped using Eclipse before I got more than bits and pieces of that working. So at the moment this plugin is implemented under the covers by using Eclipse linked mode editing (similar to existing "rename in file" functionality), so **you can't move the cursors outside the initial selection areas, and all multiple-cursor-edited-text must be the same string.**
12 |
13 | Usage
14 | -----
15 |
16 | * `Alt+J` (OSX: `Ctrl+G`): "Select Next Occurrence" of the selected text & start editing it. Repeat to select remaining occurrences.
17 | * `Alt+F3` (OSX: `Ctrl+Cmd+G`): "Select All Occurrences" of the selected text & start editing all of them at once.
18 |
19 | (If you haven't got anything selected, it'll expand your selection to the word under the cursor, or to the whole line if the cursor is in whitespace.)
20 |
21 | What's next?
22 | ------------
23 |
24 | Nothing from me. I'm not using Eclipse any more and don't have much interest in continuing this project as a result.
25 |
26 | Ideally, I'd like to hand this project over to someone else, as I still believe it's very doable to create a real implementation (i.e. not using Eclipse linked mode). Open an issue if you're interested.
27 |
28 | Getting and installing it
29 | -------------------------
30 |
31 | Get the latest release from the [releases page] and follow the install instructions below.
32 |
33 | You have 2 options for installing (pick one):
34 |
35 | *Option 1:* [Download](https://github.com/caspark/eclipse-multicursor/releases) the P2 update site (i.e. `com.asparck.eclipse.multicursor.p2updatesite-X.Y.Z.zip`), then in Eclipse choose Help >> Install New Software >> Add >> Archive >> choose the downloaded P2 update site >> tick the box to select Eclipse Multicursor >> go through the rest of the wizard >> ignore any warnings about unsigned content (just click OK) >> restart Eclipse when prompted. You can uninstall it later by going to Help >> About Eclipse >> Installation Details >> select "Eclipse Multicursor" >> Uninstall >> restart Eclipse when prompted.
36 |
37 | *Option 2:* [Download](https://github.com/caspark/eclipse-multicursor/releases) `com.asparck.eclipse.multicursor.plugin_X.Y.Z.jar` and put it in `eclipse/plugins/dropins`, then restart Eclipse. You can uninstall it by shutting down Eclipse and deleting the jar from the dropins directory.
38 |
39 | The former is the official recommended way of installing plugins & the latter is the quick and dirty way.
40 |
41 | After installing, look at the *what works?* section above to use it.
42 |
43 | Building from source
44 | --------------------
45 |
46 | Uses [Tycho](https://eclipse.org/tycho/) for building via Maven 3:
47 |
48 | mvn verify
49 |
50 | This:
51 |
52 | * looks at `c.a.e.m.target/c.a.e.m.target.target` to find the repo to get Eclipse OSGi dependency bundles from
53 | * builds the plugin, feature, and update site in the target directories of `c.a.e.m.plugin`, `c.a.e.m.feature`, and `c.a.e.m.p2updatesite`
54 | * runs the tests in `c.a.e.m.tests`
55 |
56 | Installing after building
57 | -------------------------
58 |
59 | After building, point your Eclipse at the update site in `c.a.e.m.p2updatesite\target` and install the feature contained therein.
60 |
61 | Developing
62 | ----------
63 |
64 | Using Eclipse, with the Plugin Development Environment (PDE) plugins installed:
65 |
66 | 1. Import the projects from the repo as Existing Eclipse projects
67 | 2. Open `c.a.e.m.target/c.a.e.m.target.target` and click the "activate this target platform" link on the top right of the editor that opens
68 | 3. Right click on `c.a.e.m.plugin` and choose `Debug As` >> `Eclipse Application`
69 | 4. You can also right click on tests in `c.a.e.m.tests` to run them as either plugin tests or normal JUnit tests.
70 |
71 | Note that the target platform you activate this way is more restricted than the target platform that Tycho will build with when you `mvn verify`. Tycho only uses the `.target` file to find which P2 repo it should search, and it ignores any restrictions in the enabled features of the target platform.
72 |
--------------------------------------------------------------------------------
/RELEASING:
--------------------------------------------------------------------------------
1 | Release Process
2 | ===============
3 |
4 | You do not need to follow these steps if you only want to build a version for personal use (see the README).
5 |
6 | Please do not release this project if you are not the current maintainer.
7 |
8 | Scripted
9 | --------
10 |
11 | Use the release script and specify: the release version, the next development version, and the directory to copy the built artifacts to. For example, to release v0.1.1 and have the next version being developed be 0.1.2(-SNAPSHOT):
12 |
13 | mkdir -p ~/tmp/release && ./release.sh 0.1.1 0.1.2 ~/tmp/release && ls ~/tmp/release
14 |
15 | Manually
16 | --------
17 |
18 | # Update the version in the pom files to the release version (e.g. 0.1.0):
19 | com.asparck.eclipse.multicursor.feature/pom.xml
20 | com.asparck.eclipse.multicursor.p2updatesite/pom.xml
21 | com.asparck.eclipse.multicursor.plugin/pom.xml
22 | com.asparck.eclipse.multicursor.target/pom.xml
23 | com.asparck.eclipse.multicursor.tests/pom.xml
24 | pom.xml
25 |
26 | # Update the OSGi manifest versions to the release version (e.g. 0.1.0):
27 | com.asparck.eclipse.multicursor.plugin/META-INF/MANIFEST.MF
28 | com.asparck.eclipse.multicursor.tests/META-INF/MANIFEST.MF
29 |
30 | # Update the feature version and the plugin version in the P2 feature definition to the release version (e.g. 0.1.0):
31 | com.asparck.eclipse.multicursor.feature/feature.xml
32 |
33 | # Update the feature version and filename in the P2 update site category definition to the release version and release filename (e.g. 0.1.0 and features/com.asparck.eclipse.multicursor.feature_0.1.0.jar)
34 | com.asparck.eclipse.multicursor.p2updatesite/category.xml
35 |
36 | # Build the release:
37 | mvn clean verify
38 |
39 | # Commit and tag the release:
40 | git commit -a -m "Release: prepare for v$RELEASE_VERSION release"
41 | git tag v$RELEASE_VERSION
42 |
43 | # Update the version in the pom files to the new Maven development version (e.g. 0.1.1-SNAPSHOT):
44 | com.asparck.eclipse.multicursor.feature/pom.xml
45 | com.asparck.eclipse.multicursor.p2updatesite/pom.xml
46 | com.asparck.eclipse.multicursor.plugin/pom.xml
47 | com.asparck.eclipse.multicursor.target/pom.xml
48 | com.asparck.eclipse.multicursor.tests/pom.xml
49 | pom.xml
50 |
51 | # Update the OSGi manifest versions to the new OSGi development version (e.g. 0.1.1.qualifier):
52 | com.asparck.eclipse.multicursor.plugin/META-INF/MANIFEST.MF
53 | com.asparck.eclipse.multicursor.tests/META-INF/MANIFEST.MF
54 |
55 | # Update the feature version and the plugin version in the P2 feature definition to the new OSGi development version (e.g. 0.1.1.qualifier):
56 | com.asparck.eclipse.multicursor.feature/feature.xml
57 |
58 | # Update the feature version and filename in the P2 update site category definition to the new OSGI development version and development filename (e.g. 0.1.1.qualifier and features/com.asparck.eclipse.multicursor.feature_0.1.1.qualifier.jar)
59 | com.asparck.eclipse.multicursor.p2updatesite/category.xml
60 |
61 | # Verify the development version works:
62 | mvn clean verify
63 |
64 | # Commit and push changes:
65 | git commit -a -m "Release: prepare for next development cycle"
66 | git push
67 |
68 | # Publish a release on github and upload the P2 update site + plugin jar as binaries.
69 | https://github.com/caspark/eclipse-multicursor/releases/new
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.feature/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.asparck.eclipse.multicursor.feature
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.pde.FeatureBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.pde.FeatureNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.feature/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding/=UTF-8
3 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.feature/build.properties:
--------------------------------------------------------------------------------
1 | bin.includes = feature.xml
2 | src.includes = feature.xml,\
3 | build.properties,\
4 | pom.xml
5 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.feature/feature.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | Provides multiple cursor support for Eclipse.
10 |
11 |
12 |
13 | Copyright Caspar Krieger 2013-2014
14 |
15 |
16 |
17 | Eclipse Public License - v 1.0
18 |
19 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
20 |
21 | 1. DEFINITIONS
22 |
23 | "Contribution" means:
24 |
25 | a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
26 | b) in the case of each subsequent Contributor:
27 | i) changes to the Program, and
28 | ii) additions to the Program;
29 | where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
30 | "Contributor" means any person or entity that distributes the Program.
31 |
32 | "Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
33 |
34 | "Program" means the Contributions distributed in accordance with this Agreement.
35 |
36 | "Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
37 |
38 | 2. GRANT OF RIGHTS
39 |
40 | a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
41 | b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
42 | c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
43 | d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
44 | 3. REQUIREMENTS
45 |
46 | A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
47 |
48 | a) it complies with the terms and conditions of this Agreement; and
49 | b) its license agreement:
50 | i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
51 | ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
52 | iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
53 | iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
54 | When the Program is made available in source code form:
55 |
56 | a) it must be made available under this Agreement; and
57 | b) a copy of this Agreement must be included with each copy of the Program.
58 | Contributors may not remove or alter any copyright notices contained within the Program.
59 |
60 | Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
61 |
62 | 4. COMMERCIAL DISTRIBUTION
63 |
64 | Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
65 |
66 | For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
67 |
68 | 5. NO WARRANTY
69 |
70 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
71 |
72 | 6. DISCLAIMER OF LIABILITY
73 |
74 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
75 |
76 | 7. GENERAL
77 |
78 | If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
79 |
80 | If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
81 |
82 | All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
83 |
84 | Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
85 |
86 | This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
87 |
88 |
89 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.feature/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | com.asparck.eclipse.multicursor
8 | parent
9 | 0.1.5-SNAPSHOT
10 |
11 |
12 | com.asparck.eclipse.multicursor.feature
13 | eclipse-feature
14 |
15 |
16 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.p2updatesite/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.asparck.eclipse.multicursor.p2updatesite
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.p2updatesite/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding/=UTF-8
3 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.p2updatesite/category.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Multiple Cursor support for Eclipse
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.p2updatesite/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | com.asparck.eclipse.multicursor
8 | parent
9 | 0.1.5-SNAPSHOT
10 |
11 |
12 | com.asparck.eclipse.multicursor.p2updatesite
13 | eclipse-repository
14 |
15 |
16 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.asparck.eclipse.multicursor.plugin
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.pde.ManifestBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.pde.SchemaBuilder
20 |
21 |
22 |
23 |
24 |
25 | org.eclipse.pde.PluginNature
26 | org.eclipse.jdt.core.javanature
27 |
28 |
29 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding/=UTF-8
3 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
4 | org.eclipse.jdt.core.compiler.compliance=1.6
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7 | org.eclipse.jdt.core.compiler.source=1.6
8 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/.settings/org.eclipse.jdt.ui.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
3 | sp_cleanup.add_default_serial_version_id=true
4 | sp_cleanup.add_generated_serial_version_id=false
5 | sp_cleanup.add_missing_annotations=true
6 | sp_cleanup.add_missing_deprecated_annotations=true
7 | sp_cleanup.add_missing_methods=false
8 | sp_cleanup.add_missing_nls_tags=false
9 | sp_cleanup.add_missing_override_annotations=true
10 | sp_cleanup.add_missing_override_annotations_interface_methods=true
11 | sp_cleanup.add_serial_version_id=false
12 | sp_cleanup.always_use_blocks=true
13 | sp_cleanup.always_use_parentheses_in_expressions=false
14 | sp_cleanup.always_use_this_for_non_static_field_access=false
15 | sp_cleanup.always_use_this_for_non_static_method_access=false
16 | sp_cleanup.convert_to_enhanced_for_loop=false
17 | sp_cleanup.correct_indentation=true
18 | sp_cleanup.format_source_code=false
19 | sp_cleanup.format_source_code_changes_only=false
20 | sp_cleanup.make_local_variable_final=false
21 | sp_cleanup.make_parameters_final=false
22 | sp_cleanup.make_private_fields_final=true
23 | sp_cleanup.make_type_abstract_if_missing_method=false
24 | sp_cleanup.make_variable_declarations_final=true
25 | sp_cleanup.never_use_blocks=false
26 | sp_cleanup.never_use_parentheses_in_expressions=true
27 | sp_cleanup.on_save_use_additional_actions=true
28 | sp_cleanup.organize_imports=false
29 | sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
30 | sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
31 | sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
32 | sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
33 | sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
34 | sp_cleanup.remove_private_constructors=true
35 | sp_cleanup.remove_trailing_whitespaces=true
36 | sp_cleanup.remove_trailing_whitespaces_all=true
37 | sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
38 | sp_cleanup.remove_unnecessary_casts=true
39 | sp_cleanup.remove_unnecessary_nls_tags=false
40 | sp_cleanup.remove_unused_imports=true
41 | sp_cleanup.remove_unused_local_variables=false
42 | sp_cleanup.remove_unused_private_fields=true
43 | sp_cleanup.remove_unused_private_members=false
44 | sp_cleanup.remove_unused_private_methods=true
45 | sp_cleanup.remove_unused_private_types=true
46 | sp_cleanup.sort_members=false
47 | sp_cleanup.sort_members_all=false
48 | sp_cleanup.use_blocks=false
49 | sp_cleanup.use_blocks_only_for_return_and_throw=false
50 | sp_cleanup.use_parentheses_in_expressions=false
51 | sp_cleanup.use_this_for_non_static_field_access=false
52 | sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
53 | sp_cleanup.use_this_for_non_static_method_access=false
54 | sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
55 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Bundle-ManifestVersion: 2
3 | Bundle-Name: Eclipse Multiple Cursor Support
4 | Bundle-SymbolicName: com.asparck.eclipse.multicursor.plugin;singleton:=true
5 | Bundle-Version: 0.1.5.qualifier
6 | Bundle-Activator: com.asparck.eclipse.multicursor.MultiCursorPlugin
7 | Bundle-Vendor: Caspar Krieger
8 | Require-Bundle: org.eclipse.ui;bundle-version="3.7.0",
9 | org.eclipse.core.runtime;bundle-version="3.7.0",
10 | org.eclipse.jface.text;bundle-version="3.7.0",
11 | org.eclipse.ui.workbench.texteditor;bundle-version="3.7.0"
12 | Bundle-RequiredExecutionEnvironment: JavaSE-1.6
13 | Bundle-ActivationPolicy: lazy
14 | Export-Package: com.asparck.eclipse.multicursor.util
15 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/build.properties:
--------------------------------------------------------------------------------
1 | source.. = src/
2 | output.. = bin/
3 | bin.includes = plugin.xml,\
4 | META-INF/,\
5 | .
6 | src.includes = pom.xml
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
22 |
23 |
25 |
26 |
27 |
28 |
29 |
34 |
35 |
40 |
41 |
46 |
47 |
52 |
53 |
58 |
59 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | com.asparck.eclipse.multicursor
8 | parent
9 | 0.1.5-SNAPSHOT
10 |
11 |
12 | com.asparck.eclipse.multicursor.plugin
13 | eclipse-plugin
14 |
15 |
16 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/src/com/asparck/eclipse/multicursor/Logger.java:
--------------------------------------------------------------------------------
1 | package com.asparck.eclipse.multicursor;
2 |
3 | import org.eclipse.core.runtime.ILog;
4 | import org.eclipse.core.runtime.IStatus;
5 | import org.eclipse.core.runtime.Status;
6 |
7 | public class Logger {
8 | public static Logger create(Class> clazz) {
9 | return new Logger(clazz.getCanonicalName());
10 | }
11 |
12 | private final ILog pluginLog = MultiCursorPlugin.getDefault().getLog();
13 |
14 | private final String name;
15 |
16 | public Logger(String name) {
17 | this.name = name;
18 | }
19 |
20 | public void debug(String text) {
21 | System.out.println("DEBUG: " + formatMessage(text));
22 | }
23 |
24 | public void info(String text) {
25 | logToEclipseLog(IStatus.INFO, text, null);
26 | }
27 |
28 | public void warning(String text) {
29 | logToEclipseLog(IStatus.WARNING, text, null);
30 | }
31 |
32 | public void error(String text, Throwable error) {
33 | logToEclipseLog(IStatus.ERROR, text, error);
34 | }
35 |
36 | private String formatMessage(String message) {
37 | return name + " " + message;
38 | }
39 |
40 | private void logToEclipseLog(int iStatusLogLevel, String message, Throwable error) {
41 | pluginLog.log(new Status(iStatusLogLevel, MultiCursorPlugin.PLUGIN_ID, formatMessage(message), error));
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/src/com/asparck/eclipse/multicursor/MultiCursorPlugin.java:
--------------------------------------------------------------------------------
1 | package com.asparck.eclipse.multicursor;
2 |
3 | import org.eclipse.jface.resource.ImageDescriptor;
4 | import org.eclipse.ui.plugin.AbstractUIPlugin;
5 | import org.osgi.framework.BundleContext;
6 |
7 | /**
8 | * The activator class controls the plug-in life cycle
9 | */
10 | public class MultiCursorPlugin extends AbstractUIPlugin {
11 |
12 | // The plug-in ID
13 | public static final String PLUGIN_ID = "com.asparck.eclipse.multicursor.plugin"; //$NON-NLS-1$
14 |
15 | // The shared instance
16 | private static MultiCursorPlugin plugin;
17 |
18 | /**
19 | * The constructor
20 | */
21 | public MultiCursorPlugin() {
22 | }
23 |
24 | /*
25 | * (non-Javadoc)
26 | * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
27 | */
28 | @Override
29 | public void start(BundleContext context) throws Exception {
30 | super.start(context);
31 | plugin = this;
32 | }
33 |
34 | /*
35 | * (non-Javadoc)
36 | * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
37 | */
38 | @Override
39 | public void stop(BundleContext context) throws Exception {
40 | plugin = null;
41 | super.stop(context);
42 | }
43 |
44 | /**
45 | * Returns the shared instance
46 | *
47 | * @return the shared instance
48 | */
49 | public static MultiCursorPlugin getDefault() {
50 | return plugin;
51 | }
52 |
53 | /**
54 | * Returns an image descriptor for the image file at the given
55 | * plug-in relative path
56 | *
57 | * @param path the path
58 | * @return the image descriptor
59 | */
60 | public static ImageDescriptor getImageDescriptor(String path) {
61 | return imageDescriptorFromPlugin(PLUGIN_ID, path);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/src/com/asparck/eclipse/multicursor/copied/DeleteBlockingExitPolicy.java:
--------------------------------------------------------------------------------
1 | package com.asparck.eclipse.multicursor.copied;
2 |
3 | import org.eclipse.jface.text.IDocument;
4 | import org.eclipse.jface.text.link.LinkedModeModel;
5 | import org.eclipse.jface.text.link.LinkedPosition;
6 | import org.eclipse.jface.text.link.LinkedPositionGroup;
7 | import org.eclipse.jface.text.link.LinkedModeUI.ExitFlags;
8 | import org.eclipse.jface.text.link.LinkedModeUI.IExitPolicy;
9 | import org.eclipse.swt.SWT;
10 | import org.eclipse.swt.events.VerifyEvent;
11 |
12 | /**
13 | * An exit policy that skips Backspace and Delete at the beginning and at the end
14 | * of a linked position, respectively.
15 | *
16 | * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=183925 .
17 | */
18 | // Copied from org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedNamesAssistProposal.DeleteBlockingExitPolicy
19 | public class DeleteBlockingExitPolicy implements IExitPolicy {
20 | private final IDocument fDocument;
21 |
22 | public DeleteBlockingExitPolicy(IDocument document) {
23 | fDocument= document;
24 | }
25 |
26 | @Override
27 | public ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length) {
28 | if (length == 0 && (event.character == SWT.BS || event.character == SWT.DEL)) {
29 | LinkedPosition position= model.findPosition(new LinkedPosition(fDocument, offset, 0, LinkedPositionGroup.NO_STOP));
30 | if (position != null) {
31 | if (event.character == SWT.BS) {
32 | if (offset - 1 < position.getOffset()) {
33 | //skip backspace at beginning of linked position
34 | event.doit= false;
35 | }
36 | } else /* event.character == SWT.DEL */ {
37 | if (offset + 1 > position.getOffset() + position.getLength()) {
38 | //skip delete at end of linked position
39 | event.doit= false;
40 | }
41 | }
42 | }
43 | }
44 |
45 | return null; // don't change behavior
46 | }
47 | }
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/src/com/asparck/eclipse/multicursor/hacks/ISourceViewerFinder.java:
--------------------------------------------------------------------------------
1 | package com.asparck.eclipse.multicursor.hacks;
2 |
3 | import java.lang.reflect.Method;
4 |
5 | import org.eclipse.jface.text.source.ISourceViewer;
6 | import org.eclipse.ui.IEditorPart;
7 | import org.eclipse.ui.part.MultiPageEditorPart;
8 | import org.eclipse.ui.texteditor.AbstractTextEditor;
9 |
10 | import com.asparck.eclipse.multicursor.Logger;
11 |
12 | /**
13 | * Uses hacky reflection techniques to find the source viewer for a given thing.
14 | */
15 | public class ISourceViewerFinder {
16 | private static final Logger logger = Logger.create(ISourceViewerFinder.class);
17 |
18 | public static ISourceViewer fromEditorPart(IEditorPart editorPart) {
19 | Object activeEditor = editorPart;
20 | if (editorPart instanceof MultiPageEditorPart) {
21 | MultiPageEditorPart multiPageEditorPart = (MultiPageEditorPart) editorPart;
22 | activeEditor = multiPageEditorPart.getSelectedPage();
23 | }
24 | if (activeEditor instanceof AbstractTextEditor) {
25 | return fromAbstractTextEditor((AbstractTextEditor) activeEditor);
26 | } else {
27 | logger.info("Unable to get ISourceViewer from " + editorPart
28 | + " of type " + editorPart.getClass().getCanonicalName());
29 | return null;
30 | }
31 | }
32 |
33 | /**
34 | * Relies on protected final method {@link AbstractTextEditor#getSourceViewer()}.
35 | */
36 | private static ISourceViewer fromAbstractTextEditor(AbstractTextEditor editor) {
37 | try {
38 | Method getSourceViewerMethod = null;
39 | Class> clazz = editor.getClass();
40 | while (clazz != null && getSourceViewerMethod == null) {
41 | if (clazz.equals(AbstractTextEditor.class)) {
42 | getSourceViewerMethod = clazz.getDeclaredMethod("getSourceViewer");
43 | } else {
44 | clazz = clazz.getSuperclass();
45 | }
46 | }
47 | if (getSourceViewerMethod == null) {
48 | throw new RuntimeException();
49 | }
50 | getSourceViewerMethod.setAccessible(true);
51 | ISourceViewer result = (ISourceViewer) getSourceViewerMethod.invoke(editor);
52 | return result;
53 | } catch (Exception e) {
54 | logger.error("Failed to acquire ISourceViewer via reflection", e);
55 | return null;
56 | }
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/src/com/asparck/eclipse/multicursor/handlers/SelectAllOccurrencesHandler.java:
--------------------------------------------------------------------------------
1 | package com.asparck.eclipse.multicursor.handlers;
2 |
3 | import org.eclipse.core.commands.AbstractHandler;
4 | import org.eclipse.core.commands.ExecutionEvent;
5 | import org.eclipse.core.commands.ExecutionException;
6 | import org.eclipse.jface.text.BadLocationException;
7 | import org.eclipse.jface.text.FindReplaceDocumentAdapter;
8 | import org.eclipse.jface.text.IDocument;
9 | import org.eclipse.jface.text.IRegion;
10 | import org.eclipse.jface.text.link.LinkedModeModel;
11 | import org.eclipse.jface.text.link.LinkedModeUI;
12 | import org.eclipse.jface.text.link.LinkedPosition;
13 | import org.eclipse.jface.text.link.LinkedPositionGroup;
14 | import org.eclipse.jface.text.source.ISourceViewer;
15 | import org.eclipse.swt.graphics.Point;
16 | import org.eclipse.ui.IEditorPart;
17 | import org.eclipse.ui.handlers.HandlerUtil;
18 | import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
19 |
20 | import com.asparck.eclipse.multicursor.copied.DeleteBlockingExitPolicy;
21 | import com.asparck.eclipse.multicursor.hacks.ISourceViewerFinder;
22 | import com.asparck.eclipse.multicursor.util.CoordinatesUtil;
23 | import com.asparck.eclipse.multicursor.util.TextUtil;
24 |
25 | /** When triggered, any lines which are identical to the current line will start being edited. */
26 | public class SelectAllOccurrencesHandler extends AbstractHandler {
27 |
28 | @Override
29 | public Object execute(ExecutionEvent event) throws ExecutionException {
30 | IEditorPart editor = HandlerUtil.getActiveEditorChecked(event);
31 |
32 | ISourceViewer viewer = ISourceViewerFinder.fromEditorPart(editor);
33 | if (viewer != null) {
34 | startEditing(viewer);
35 | }
36 |
37 | return null;
38 | }
39 |
40 | /**
41 | * Mostly based on code from {@link org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedNamesAssistProposal}
42 | */
43 | private void startEditing(ISourceViewer viewer) throws ExecutionException {
44 | Point selOffsetAndLen = viewer.getSelectedRange();
45 | int selStart = CoordinatesUtil.fromOffsetAndLengthToStartAndEnd(selOffsetAndLen).x;
46 |
47 | IDocument document = viewer.getDocument();
48 | try {
49 | String selectedText;
50 | if (selOffsetAndLen.y == 0) { // no characters selected
51 | String documentText = document.get();
52 | Point wordOffsetAndLen = TextUtil.findWordSurrounding(documentText, selStart);
53 | if (wordOffsetAndLen != null) {
54 | selectedText = document.get(wordOffsetAndLen.x, wordOffsetAndLen.y);
55 | } else {
56 | IRegion selectedLine = document.getLineInformationOfOffset(selStart);
57 | selectedText = document.get(selectedLine.getOffset(), selectedLine.getLength());
58 | }
59 | } else {
60 | selectedText = document.get(selOffsetAndLen.x, selOffsetAndLen.y);
61 | }
62 |
63 | LinkedPositionGroup linkedPositionGroup = new LinkedPositionGroup();
64 |
65 | FindReplaceDocumentAdapter findReplaceAdaptor = new FindReplaceDocumentAdapter(document);
66 | IRegion matchingRegion = findReplaceAdaptor.find(0, selectedText, true, true, false, false);
67 | while (matchingRegion != null) {
68 | linkedPositionGroup.addPosition(new LinkedPosition(document, matchingRegion.getOffset(), matchingRegion
69 | .getLength()));
70 |
71 | matchingRegion = findReplaceAdaptor.find(matchingRegion.getOffset() + matchingRegion.getLength(),
72 | selectedText, true, true, false, false);
73 | }
74 |
75 | LinkedModeModel model = new LinkedModeModel();
76 | model.addGroup(linkedPositionGroup);
77 | model.forceInstall();
78 |
79 | LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
80 | ui.setExitPolicy(new DeleteBlockingExitPolicy(document));
81 | ui.enter();
82 |
83 | // by default the text being edited is selected so restore original selection
84 | viewer.setSelectedRange(selOffsetAndLen.x, selOffsetAndLen.y);
85 | } catch (BadLocationException e) {
86 | throw new ExecutionException("Editing failed", e);
87 | }
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/src/com/asparck/eclipse/multicursor/handlers/SelectNextOccurrenceHandler.java:
--------------------------------------------------------------------------------
1 | package com.asparck.eclipse.multicursor.handlers;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 | import java.util.List;
6 |
7 | import org.eclipse.core.commands.AbstractHandlerWithState;
8 | import org.eclipse.core.commands.ExecutionEvent;
9 | import org.eclipse.core.commands.ExecutionException;
10 | import org.eclipse.core.commands.State;
11 | import org.eclipse.jface.text.BadLocationException;
12 | import org.eclipse.jface.text.FindReplaceDocumentAdapter;
13 | import org.eclipse.jface.text.IDocument;
14 | import org.eclipse.jface.text.IRegion;
15 | import org.eclipse.jface.text.ITextViewer;
16 | import org.eclipse.jface.text.link.LinkedModeModel;
17 | import org.eclipse.jface.text.link.LinkedModeUI;
18 | import org.eclipse.jface.text.link.LinkedPosition;
19 | import org.eclipse.jface.text.link.LinkedPositionGroup;
20 | import org.eclipse.jface.text.source.ISourceViewer;
21 | import org.eclipse.swt.graphics.Point;
22 | import org.eclipse.ui.IEditorPart;
23 | import org.eclipse.ui.handlers.HandlerUtil;
24 | import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
25 |
26 | import com.asparck.eclipse.multicursor.copied.DeleteBlockingExitPolicy;
27 | import com.asparck.eclipse.multicursor.hacks.ISourceViewerFinder;
28 | import com.asparck.eclipse.multicursor.util.CoordinatesUtil;
29 | import com.asparck.eclipse.multicursor.util.TextUtil;
30 |
31 | public class SelectNextOccurrenceHandler extends AbstractHandlerWithState {
32 | private static final String ID_SELECTS_IN_PROGRESS = "SELECTS_IN_PROGRESS";
33 |
34 | private static final class SelectInProgress {
35 | public final String searchText;
36 | public final List existingSelections;
37 | public final int nextOffset;
38 | private final Point startingSelection;
39 |
40 | public SelectInProgress(Point startingSelection, String selectedText, List existingSelections, int nextOffset) {
41 | this.startingSelection = startingSelection;
42 | this.searchText = selectedText;
43 | this.existingSelections = Collections.unmodifiableList(new ArrayList(existingSelections));
44 | this.nextOffset = nextOffset;
45 | }
46 |
47 | @Override
48 | public String toString() {
49 | return "[Find " + searchText + " at " + nextOffset + "; original=" + startingSelection + "]";
50 | }
51 | }
52 |
53 | @Override
54 | public Object execute(ExecutionEvent event) throws ExecutionException {
55 | IEditorPart editor = HandlerUtil.getActiveEditorChecked(event);
56 |
57 | ISourceViewer viewer = ISourceViewerFinder.fromEditorPart(editor);
58 | if (viewer != null) {
59 | startEditing(viewer);
60 | }
61 |
62 | return null;
63 | }
64 |
65 | private void startEditing(ISourceViewer viewer) throws ExecutionException {
66 | final Point selOffsetAndLen = viewer.getSelectedRange();
67 | final IDocument document = viewer.getDocument();
68 |
69 | try {
70 | final String searchText;
71 | final int candidateSearchOffset;
72 | final int selStart = CoordinatesUtil.fromOffsetAndLengthToStartAndEnd(selOffsetAndLen).x;
73 | if (selOffsetAndLen.y == 0) { // no characters selected
74 | final String documentText = document.get();
75 | final Point wordOffsetAndLen = TextUtil.findWordSurrounding(documentText, selStart);
76 | if (wordOffsetAndLen != null) {
77 | searchText = document.get(wordOffsetAndLen.x, wordOffsetAndLen.y);
78 | candidateSearchOffset = wordOffsetAndLen.x;
79 | } else {
80 | final IRegion selectedLine = document.getLineInformationOfOffset(selStart);
81 | searchText = document.get(selectedLine.getOffset(), selectedLine.getLength());
82 | candidateSearchOffset = selectedLine.getOffset();
83 | }
84 | } else {
85 | searchText = document.get(selOffsetAndLen.x, selOffsetAndLen.y);
86 | candidateSearchOffset = selOffsetAndLen.x;
87 | }
88 |
89 | final int searchOffset;
90 | final List selections;
91 | final Point startingSelection;
92 |
93 | final SelectInProgress currentState = getCurrentState();
94 | if (LinkedModeModel.getModel(document, 0) != null &&
95 | currentState != null
96 | && selOffsetAndLen.equals(currentState.startingSelection)
97 | && searchText.equals(currentState.searchText)) {
98 | startingSelection = currentState.startingSelection;
99 | selections = new ArrayList(currentState.existingSelections);
100 | searchOffset = currentState.nextOffset;
101 | } else {
102 | startingSelection = selOffsetAndLen;
103 | selections = new ArrayList();
104 | searchOffset = candidateSearchOffset;
105 | }
106 |
107 | final IRegion matchingRegion = new FindReplaceDocumentAdapter(document).find(searchOffset,
108 | searchText, true, true, false, false);
109 | if (matchingRegion != null) {
110 | selections.add(matchingRegion);
111 |
112 | if (selections.size() == 1) {
113 | // select the next occurrence too; only selecting the current cursor pos isn't useful
114 | final IRegion secondMatchingRegion = new FindReplaceDocumentAdapter(document).find(
115 | matchingRegion.getOffset() + matchingRegion.getLength(), searchText, true, true, false, false);
116 | if (secondMatchingRegion != null) {
117 | selections.add(secondMatchingRegion);
118 | }
119 | }
120 |
121 | if (selections.size() > 1) {
122 | final IRegion lastSelection = selections.get(selections.size() - 1);
123 | saveCurrentState(new SelectInProgress(startingSelection, searchText, selections,
124 | lastSelection.getOffset() + lastSelection.getLength()));
125 |
126 | startLinkedEdit(selections, viewer, selOffsetAndLen);
127 | }
128 | }
129 | } catch (BadLocationException e) {
130 | throw new ExecutionException("Editing failed", e);
131 | }
132 | }
133 |
134 |
135 | // Reference: RenameLinkedMode class shows how linked mode is meant to be used
136 | private void startLinkedEdit(List selections, ITextViewer viewer, Point originalSelection)
137 | throws BadLocationException {
138 | final LinkedPositionGroup linkedPositionGroup = new LinkedPositionGroup();
139 | for (IRegion selection : selections) {
140 | linkedPositionGroup.addPosition(new LinkedPosition(viewer.getDocument(), selection.getOffset(), selection
141 | .getLength()));
142 | }
143 |
144 | LinkedModeModel model = new LinkedModeModel();
145 | model.addGroup(linkedPositionGroup);
146 | model.forceInstall();
147 | //FIXME can add a listener here to listen for the end of linked mode
148 | //model.addLinkingListener(null);
149 |
150 | LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
151 | ui.setExitPolicy(new DeleteBlockingExitPolicy(viewer.getDocument()));
152 | ui.enter();
153 |
154 | // by default the text being edited is selected so restore original selection
155 | viewer.setSelectedRange(originalSelection.x, originalSelection.y);
156 | }
157 |
158 | private SelectInProgress getCurrentState() {
159 | State state = getState(ID_SELECTS_IN_PROGRESS);
160 | if (state == null) {
161 | return null;
162 | } else {
163 | return (SelectInProgress) state.getValue();
164 | }
165 | }
166 |
167 | private void saveCurrentState(SelectInProgress selectInProgress) {
168 | State state = new State();
169 | state.setValue(selectInProgress);
170 | state.setId(ID_SELECTS_IN_PROGRESS);
171 | addState(ID_SELECTS_IN_PROGRESS, state);
172 | }
173 |
174 | @Override
175 | public void handleStateChange(State state, Object oldValue) {
176 | // logger.debug("State changed; new value=" + state.getId() + ":" + state.getValue() + " and old value="
177 | // + oldValue);
178 | }
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/src/com/asparck/eclipse/multicursor/util/CoordinatesUtil.java:
--------------------------------------------------------------------------------
1 | package com.asparck.eclipse.multicursor.util;
2 |
3 | import org.eclipse.swt.graphics.Point;
4 |
5 | public class CoordinatesUtil {
6 | /**
7 | * Converts offset and (possibly negative) length to absolute start and end positions.
8 | */
9 | public static Point fromOffsetAndLengthToStartAndEnd(Point startAndOffset) {
10 | int selStart = Math.min(startAndOffset.x, startAndOffset.x + startAndOffset.y);
11 | int selEnd = Math.max(startAndOffset.x, startAndOffset.x + startAndOffset.y);
12 | return new Point(selStart, selEnd);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.plugin/src/com/asparck/eclipse/multicursor/util/TextUtil.java:
--------------------------------------------------------------------------------
1 | package com.asparck.eclipse.multicursor.util;
2 |
3 | import java.util.regex.Matcher;
4 | import java.util.regex.Pattern;
5 |
6 | import org.eclipse.swt.graphics.Point;
7 |
8 | public class TextUtil {
9 | private static final Pattern WORD_RE = Pattern.compile("\\w+");
10 |
11 | /**
12 | * Scans backward from the given offset to identify a word which contains {@code offset}.
13 | *
14 | * @return position (x) and length (y) of the last word in {@code text} which contains {@code offset}, or null if no
15 | * word containing {@code offset} could be identified (i.e. offset is in whitespace)
16 | */
17 | public static Point findWordSurrounding(String text, int offset) {
18 | int wordOffset = offset == 0 ? 0 : offset - 1;
19 | Point lastWordFound = null;
20 | Matcher matcher = WORD_RE.matcher(text);
21 | while (wordOffset >= 0) {
22 | boolean found = matcher.find(wordOffset);
23 | if (found && matcher.start() <= offset && matcher.end() >= offset) {
24 | lastWordFound = new Point(matcher.start(), matcher.end() - matcher.start());
25 | wordOffset--; // see if there's another match behind
26 | } else {
27 | break;
28 | }
29 | }
30 |
31 | return lastWordFound;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.target/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.asparck.eclipse.multicursor.target
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.target/com.asparck.eclipse.multicursor.target.target:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.target/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | com.asparck.eclipse.multicursor
8 | parent
9 | 0.1.5-SNAPSHOT
10 |
11 |
12 | com.asparck.eclipse.multicursor.target
13 | eclipse-target-definition
14 |
15 |
16 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.tests/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.tests/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.asparck.eclipse.multicursor.tests
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.pde.ManifestBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.pde.SchemaBuilder
20 |
21 |
22 |
23 |
24 |
25 | org.eclipse.pde.PluginNature
26 | org.eclipse.jdt.core.javanature
27 |
28 |
29 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.tests/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding/=UTF-8
3 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.tests/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
4 | org.eclipse.jdt.core.compiler.compliance=1.6
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7 | org.eclipse.jdt.core.compiler.source=1.6
8 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.tests/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Bundle-ManifestVersion: 2
3 | Bundle-Name: Tests
4 | Bundle-SymbolicName: com.asparck.eclipse.multicursor.tests
5 | Bundle-Version: 0.1.5.qualifier
6 | Bundle-Activator: com.asparck.eclipse.multicursor.tests.Activator
7 | Bundle-Vendor: Caspar Krieger
8 | Require-Bundle: org.eclipse.core.runtime,
9 | org.junit;bundle-version="4.8.1",
10 | com.asparck.eclipse.multicursor.plugin,
11 | org.eclipse.swt
12 | Bundle-RequiredExecutionEnvironment: JavaSE-1.6
13 | Bundle-ActivationPolicy: lazy
14 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.tests/build.properties:
--------------------------------------------------------------------------------
1 | source.. = src/
2 | output.. = bin/
3 | bin.includes = META-INF/,\
4 | .
5 | src.includes = pom.xml
6 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.tests/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | com.asparck.eclipse.multicursor
8 | parent
9 | 0.1.5-SNAPSHOT
10 |
11 |
12 | com.asparck.eclipse.multicursor.tests
13 | eclipse-test-plugin
14 |
15 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.tests/src/com/asparck/eclipse/multicursor/tests/Activator.java:
--------------------------------------------------------------------------------
1 | package com.asparck.eclipse.multicursor.tests;
2 |
3 | import org.osgi.framework.BundleActivator;
4 | import org.osgi.framework.BundleContext;
5 |
6 | public class Activator implements BundleActivator {
7 |
8 | private static BundleContext context;
9 |
10 | static BundleContext getContext() {
11 | return context;
12 | }
13 |
14 | /*
15 | * (non-Javadoc)
16 | * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
17 | */
18 | public void start(BundleContext bundleContext) throws Exception {
19 | Activator.context = bundleContext;
20 | }
21 |
22 | /*
23 | * (non-Javadoc)
24 | * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
25 | */
26 | public void stop(BundleContext bundleContext) throws Exception {
27 | Activator.context = null;
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/com.asparck.eclipse.multicursor.tests/src/com/asparck/eclipse/multicursor/util/TextUtilTest.java:
--------------------------------------------------------------------------------
1 | package com.asparck.eclipse.multicursor.util;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.eclipse.swt.graphics.Point;
6 | import org.junit.Test;
7 |
8 | public class TextUtilTest {
9 |
10 | @Test
11 | public void findWordSurroundingShouldFindWordSurroundingGivenOffset() {
12 | String str = "my name is bob";
13 | Point word = TextUtil.findWordSurrounding(str, 5);
14 |
15 | assertEquals("name", str.substring(word.x, word.x + word.y));
16 | }
17 |
18 | @Test
19 | public void findWordSurroundingShouldFindWordWhenOffsetIsAtStartOfWord() {
20 | String str = "my name is bob";
21 | Point word = TextUtil.findWordSurrounding(str, 3);
22 |
23 | assertEquals("name", str.substring(word.x, word.x + word.y));
24 | }
25 |
26 | @Test
27 | public void findWordSurroundingShouldFindWordWhenOffsetIsAtEndOfWord() {
28 | String str = "my name is bob";
29 | Point word = TextUtil.findWordSurrounding(str, 7);
30 |
31 | assertEquals("name", str.substring(word.x, word.x + word.y));
32 | }
33 |
34 | @Test
35 | public void findWordSurroundingShouldFindWordWhenOffsetIsAtStartOfString() {
36 | String str = "my name is bob";
37 | Point word = TextUtil.findWordSurrounding(str, 0);
38 |
39 | assertEquals("my", str.substring(word.x, word.x + word.y));
40 | }
41 |
42 | @Test
43 | public void findWordSurroundingShouldFindWordWhenOffsetIsAtEndOfString() {
44 | String str = "my name is bob";
45 | Point word = TextUtil.findWordSurrounding(str, str.length());
46 |
47 | assertEquals("bob", str.substring(word.x, word.x + word.y));
48 | }
49 |
50 | @Test
51 | public void findWordSurroundingShouldReturnNullIfOffsetIsInEmptyString() {
52 | Point word = TextUtil.findWordSurrounding("", 0);
53 |
54 | assertNull(word);
55 | }
56 |
57 | @Test
58 | public void findWordSurroundingShouldReturnNullIfOffsetIsInWhitespace() {
59 | Point word = TextUtil.findWordSurrounding("hello world", 6);
60 |
61 | assertNull(word);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.asparck.eclipse.multicursor
7 | parent
8 | 0.1.5-SNAPSHOT
9 | pom
10 |
11 |
12 | com.asparck.eclipse.multicursor.target
13 | com.asparck.eclipse.multicursor.plugin
14 | com.asparck.eclipse.multicursor.feature
15 | com.asparck.eclipse.multicursor.p2updatesite
16 | com.asparck.eclipse.multicursor.tests
17 |
18 |
19 |
20 | 0.20.0
21 |
22 | UTF-8
23 |
24 |
25 |
26 |
27 |
28 | org.eclipse.tycho
29 | tycho-maven-plugin
30 | ${tycho.version}
31 | true
32 |
33 |
34 |
35 | org.eclipse.tycho
36 | tycho-compiler-plugin
37 | ${tycho.version}
38 |
39 | 1.6
40 | 1.6
41 |
42 |
43 |
44 |
45 | org.eclipse.tycho
46 | target-platform-configuration
47 | ${tycho.version}
48 |
49 |
50 |
51 | ${project.groupId}
52 | com.asparck.eclipse.multicursor.target
53 | ${project.version}
54 |
55 |
56 |
57 |
58 | linux
59 | gtk
60 | x86
61 |
62 |
63 | linux
64 | gtk
65 | x86_64
66 |
67 |
68 | win32
69 | win32
70 | x86
71 |
72 |
73 | win32
74 | win32
75 | x86_64
76 |
77 |
78 | macosx
79 | cocoa
80 | x86_64
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/redownload-p2-plugin-jars.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # If, when setting the target platform, Eclipse gets a bunch of errors about being unable to parse
4 | # manifests and it turns out that each of the jars it complains about is not a valid zip file, you
5 | # can use this to download the correct jars in the pack.gz forms (and then unpacking them; the
6 | # .pack.gz versions of the jars aren't corrupted, in my experience).
7 | #
8 | # This script will download the jars from the 3.7.2 update site; you can plug in another update
9 | # site by editing the script below (we're defaulting to 3.7.2 because at time of writing, that's
10 | # the lowest version of Eclipse that we support).
11 | #
12 | # Usage: cd to your Eclipse workspace (containing the .metadata directory), and then run this
13 | # script from there.
14 |
15 | set -e
16 |
17 | #UPDATE_SITE_BASE_URL=http://download.eclipse.org/eclipse/updates/3.8/R-3.8.2-201301310800/plugins/
18 | #UPDATE_SITE_BASE_URL=http://download.eclipse.org/eclipse/updates/3.7/R-3.7.2-201202080800/plugins/
19 | UPDATE_SITE_BASE_URL=http://download.eclipse.org/releases/indigo/201202240900/aggregate/plugins/
20 |
21 | # PDE downloads its plugins to here
22 | cd .metadata/.plugins/org.eclipse.pde.core/.bundle_pool/plugins
23 |
24 | for f in *.jar; do
25 | # echo "Processing ${f}"
26 | echo -n .
27 | if ! unzip -t ${f} 2>&1 > /dev/null ; then
28 | echo "*** ${f} appears corrupt, redownloading"
29 | curl -Ov "${UPDATE_SITE_BASE_URL}${f}.pack.gz"
30 | unpack200 -r "${f}.pack.gz" "${f}"
31 | fi
32 | done
33 |
--------------------------------------------------------------------------------
/release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # See RELEASING
4 |
5 | if [ "$#" -ne 3 ]; then
6 | echo "Expected: 3 parameters:"
7 | echo "- release version"
8 | echo "- development version"
9 | echo "- release artifact destination directory"
10 | exit 1
11 | fi
12 |
13 | function fail_with_msg {
14 | echo $1
15 | exit 1
16 | }
17 |
18 | function set_maven_version {
19 | NEW_MAVEN_VERSION=$1
20 |
21 | echo "Using maven to update pom.xml versions to ${NEW_MAVEN_VERSION}"
22 | mvn org.codehaus.mojo:versions-maven-plugin:2.1:set -DnewVersion=${NEW_MAVEN_VERSION} > /dev/null || fail_with_msg "Setting versions failed; aborting"
23 | find . -name 'pom.xml.versionsBackup' -delete || fail_with_msg "Deleting temp files failed; aborting"
24 | }
25 |
26 | function set_osgi_version {
27 | OLD_OSGI_VERSION=$1
28 | NEW_OSGI_VERSION=$2
29 |
30 | echo "Updating OSGI manifest versions from ${OLD_OSGI_VERSION} to ${NEW_OSGI_VERSION}"
31 | find . -name "MANIFEST.MF" -exec sed -i "s/Bundle-Version: ${OLD_OSGI_VERSION}/Bundle-Version: ${NEW_OSGI_VERSION}/g" '{}' \; || fail_with_msg "Error; aborting"
32 |
33 | echo "Updating Eclipse feature version and referenced plugin version in the P2 feature definition from ${OLD_OSGI_VERSION} to ${NEW_OSGI_VERSION}"
34 | # using /g to make update both occurrences as per message above
35 | sed -i "s/version=\"${OLD_OSGI_VERSION}\"/version=\"${NEW_OSGI_VERSION}\"/g" com.asparck.eclipse.multicursor.feature/feature.xml || fail_with_msg "Error; aborting"
36 |
37 | echo "Updating Eclipse feature version and filename in the P2 update site category definition from ${OLD_OSGI_VERSION} to ${NEW_OSGI_VERSION}"
38 | sed -i "s/com.asparck.eclipse.multicursor.feature_${OLD_OSGI_VERSION}.jar/com.asparck.eclipse.multicursor.feature_${NEW_OSGI_VERSION}.jar/" com.asparck.eclipse.multicursor.p2updatesite/category.xml || fail_with_msg "Error; aborting"
39 | sed -i "s/version=\"${OLD_OSGI_VERSION}\">/version=\"${NEW_OSGI_VERSION}\">/" com.asparck.eclipse.multicursor.p2updatesite/category.xml || fail_with_msg "Error; aborting"
40 | }
41 |
42 | function verify_only_expected_files_are_dirty {
43 | UNEXPECTED_DIRTY=$(git status --porcelain | grep -v pom.xml | grep -v category.xml | grep -v MANIFEST.MF | grep -v feature.xml)
44 | if [[ ! -z ${UNEXPECTED_DIRTY} ]]; then
45 | echo "Unexpected files are dirty:"
46 | echo ${UNEXPECTED_DIRTY}
47 | exit 1
48 | fi
49 | }
50 |
51 | function git_commit_all_with_msg {
52 | echo "*** Committing with message '${1}'"
53 | git commit -a -m "${1}" || fail_with_msg "Error committing; aborting"
54 | }
55 |
56 |
57 | echo "Determining project development version from maven"
58 | CURRENT_DEVELOPMENT_VERSION_MAVEN=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -Ev '(^\[|Download\w+:)')
59 | #CURRENT_DEVELOPMENT_VERSION_MAVEN="0.1.1-SNAPSHOT"
60 | EXPECTED_CURRENT_DEVELOPMENT_VERSION_MAVEN_RE="([0-9]+\.[0-9]+\.[0-9]+)-SNAPSHOT"
61 |
62 | if [[ ${CURRENT_DEVELOPMENT_VERSION_MAVEN} =~ ${EXPECTED_CURRENT_DEVELOPMENT_VERSION_MAVEN_RE} ]]; then
63 | CURRENT_DEVELOPMENT_VERSION=${BASH_REMATCH[1]}
64 | else
65 | fail_with_msg "Maven development version of ${CURRENT_DEVELOPMENT_VERSION_MAVEN} does not match expected format of ${EXPECTED_CURRENT_DEVELOPMENT_VERSION_MAVEN_RE}"
66 | fi
67 |
68 | CURRENT_DEVELOPMENT_VERSION_OSGI=${CURRENT_DEVELOPMENT_VERSION}.qualifier
69 | RELEASE_VERSION=$1
70 | RELEASE_GIT_COMMIT_MSG="Release: v${RELEASE_VERSION}"
71 | RELEASE_GIT_TAG="v${RELEASE_VERSION}"
72 | NEXT_DEVELOPMENT_VERSION=${2}
73 | NEXT_DEVELOPMENT_VERSION_MAVEN=${NEXT_DEVELOPMENT_VERSION}-SNAPSHOT
74 | NEXT_DEVELOPMENT_VERSION_OSGI=${NEXT_DEVELOPMENT_VERSION}.qualifier
75 | NEXT_DEVELOPMENT_GIT_COMMIT_MSG="Release: prepare for next development cycle"
76 | RELEASE_ARTIFACT_DIR=$(readlink -m $3)
77 |
78 | echo "CURRENT_DEVELOPMENT_VERSION_MAVEN=${CURRENT_DEVELOPMENT_VERSION_MAVEN}"
79 | echo "CURRENT_DEVELOPMENT_VERSION_OSGI=${CURRENT_DEVELOPMENT_VERSION_OSGI} (assumed from Maven version)"
80 | echo "RELEASE_VERSION=${RELEASE_VERSION}"
81 | echo "RELEASE_GIT_COMMIT_MSG=${RELEASE_GIT_COMMIT_MSG}"
82 | echo "RELEASE_GIT_TAG=${RELEASE_GIT_TAG}"
83 | echo "NEXT_DEVELOPMENT_VERSION_MAVEN=${NEXT_DEVELOPMENT_VERSION_MAVEN}"
84 | echo "NEXT_DEVELOPMENT_VERSION_OSGI=${NEXT_DEVELOPMENT_VERSION_OSGI}"
85 | echo "NEXT_DEVELOPMENT_GIT_COMMIT_MSG=${NEXT_DEVELOPMENT_GIT_COMMIT_MSG}"
86 | echo "RELEASE_ARTIFACT_DIR=${RELEASE_ARTIFACT_DIR}"
87 |
88 | read -p "Continue with release? [y/n] " -n 1 -r
89 | echo # move to a new line
90 | if [[ ! ${REPLY} =~ ^[Yy]$ ]]
91 | then
92 | echo "Release cancelled; aborting."
93 | exit 1
94 | fi
95 |
96 | echo "*** Preparing for release by setting versions to ${RELEASE_VERSION}"
97 | set_maven_version ${RELEASE_VERSION}
98 | set_osgi_version ${CURRENT_DEVELOPMENT_VERSION_OSGI} ${RELEASE_VERSION}
99 |
100 | echo "*** Building release"
101 | mvn clean verify || fail_with_msg "Error building release; aborting"
102 |
103 | echo "*** Copying release artifacts to ${RELEASE_ARTIFACT_DIR}"
104 | cp com.asparck.eclipse.multicursor.plugin/target/com.asparck.eclipse.multicursor.plugin-${RELEASE_VERSION}.jar \
105 | com.asparck.eclipse.multicursor.p2updatesite/target/com.asparck.eclipse.multicursor.p2updatesite-${RELEASE_VERSION}.zip \
106 | "${RELEASE_ARTIFACT_DIR}"
107 |
108 | verify_only_expected_files_are_dirty
109 | git_commit_all_with_msg "${RELEASE_GIT_COMMIT_MSG}"
110 |
111 | echo "*** Tagging release with tag '${RELEASE_GIT_TAG}'"
112 | git tag "${RELEASE_GIT_TAG}" || fail_with_msg "Error tagging; aborting"
113 |
114 | echo "*** Preparing for next development version by setting versions to ${NEXT_DEVELOPMENT_VERSION}"
115 | set_maven_version ${NEXT_DEVELOPMENT_VERSION_MAVEN}
116 | set_osgi_version ${RELEASE_VERSION} ${NEXT_DEVELOPMENT_VERSION_OSGI}
117 |
118 | echo "*** Building next development version to make sure it isn't broken"
119 | mvn clean verify || fail_with_msg "Error building next development version; aborting"
120 |
121 | verify_only_expected_files_are_dirty
122 | git_commit_all_with_msg "${NEXT_DEVELOPMENT_GIT_COMMIT_MSG}"
123 |
124 | echo "*** Release completed; next steps:"
125 | echo "- Check the git commit history and then 'git push --tags'"
126 | echo "- Upload artifacts from ${RELEASE_ARTIFACT_DIR} to a new github release: https://github.com/caspark/eclipse-multicursor/releases/new"
127 |
--------------------------------------------------------------------------------