Bug 8519 - keystroke macros recording and playing capability

Change-Id: Iaad9fa7a3e6c54b15cf814a38f83aea131368731
Signed-off-by: Fabio Zadrozny <fabiofz@gmail.com>
diff --git a/build/org.eclipse.e4.ui.update/category.xml b/build/org.eclipse.e4.ui.update/category.xml
index 0503a14..10737ae 100644
--- a/build/org.eclipse.e4.ui.update/category.xml
+++ b/build/org.eclipse.e4.ui.update/category.xml
@@ -12,12 +12,9 @@
    <feature id="org.eclipse.ui.glance.feature" version="0.0.1.qualifier">
       <category name="Incrementation Text Search with Eclipse Glance"/>
    </feature>
-   <bundle id="org.eclipse.e4.ui.macros" version="0.1.0.qualifier">
+   <feature id="org.eclipse.e4.ui.macros.feature" version="0.1.0.qualifier">
       <category name="Macros"/>
-   </bundle>
-   <bundle id="org.eclipse.e4.ui.macros.jdt" version="0.1.0.qualifier">
-      <category name="Macros"/>
-   </bundle>
+   </feature>
    <bundle id="org.eclipse.e4.jdt.scope" version="0.0.1.qualifier">
       <category name="JDT"/>
    </bundle>
@@ -25,7 +22,11 @@
       <category name="Misc"/>
    </bundle>
    <category-def name="org.eclipse.e4.ui.keys" label="Eclipse e4 Key Schemes"/>
-   <category-def name="Macros" label="Keyboard macros"/>
+   <category-def name="Macros" label="Keyboard macros">
+      <description>
+         Record/playback 
+      </description>
+   </category-def>
    <category-def name="JDT" label="JDT/PDE Extensions"/>
    <category-def name="Misc" label="Misc"/>
    <category-def name="Incrementation Text Search with Eclipse Glance" label="Incrementation Text Search with Eclipse Glance">
diff --git a/bundles/.project b/bundles/.project
new file mode 100644
index 0000000..38d4784
--- /dev/null
+++ b/bundles/.project
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>bundles</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+	</buildSpec>
+	<natures>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.e4.core.macros/.classpath b/bundles/org.eclipse.e4.core.macros/.classpath
new file mode 100644
index 0000000..eca7bdb
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.e4.ui.macros.jdt/.project b/bundles/org.eclipse.e4.core.macros/.project
similarity index 64%
copy from bundles/org.eclipse.e4.ui.macros.jdt/.project
copy to bundles/org.eclipse.e4.core.macros/.project
index 4babb46..a8f2e12 100644
--- a/bundles/org.eclipse.e4.ui.macros.jdt/.project
+++ b/bundles/org.eclipse.e4.core.macros/.project
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-	<name>org.eclipse.e4.ui.macros.jdt</name>
+	<name>org.eclipse.e4.core.macros</name>
 	<comment></comment>
 	<projects>
 	</projects>
@@ -20,9 +20,20 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ds.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.pde.PluginNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
 	</natures>
 </projectDescription>
diff --git a/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..5a0ad22
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..fdfba91
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,421 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=error
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=error
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..2ecc6a3
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,73 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
+internal.default.compliance=user
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return Returns the ${bare_field_name}.\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} The ${bare_field_name} to set.\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment"/><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * @since 3.5\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
diff --git a/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..a09ec9c
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,97 @@
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Warning
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..be3cfc2
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,35 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=2
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=0
+compilers.p.discouraged-class=1
+compilers.p.illegal-att-value=0
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=2
+compilers.p.missing-version-import-package=2
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=0
+compilers.p.unknown-attribute=0
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.p.unused-element-or-attribute=1
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.e4.core.macros/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.core.macros/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5306d02
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/META-INF/MANIFEST.MF
@@ -0,0 +1,22 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.e4.core.macros;singleton:=true
+Bundle-Version: 0.1.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
+Require-Bundle: org.eclipse.osgi;bundle-version="3.11",
+ org.eclipse.e4.core.contexts;bundle-version="1.5",
+ org.eclipse.osgi.services;bundle-version="3.5",
+ org.eclipse.equinox.util;bundle-version="1.0",
+ org.eclipse.equinox.ds;bundle-version="1.4",
+ org.eclipse.e4.core.di;bundle-version="1.6",
+ org.eclipse.equinox.registry;bundle-version="3.6",
+ javax.inject;bundle-version="1.0",
+ org.eclipse.core.runtime;bundle-version="3.12",
+ org.eclipse.e4.ui.bindings;bundle-version="0.11"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.e4.core.macros.Activator
+Export-Package: org.eclipse.e4.core.macros,
+ org.eclipse.e4.core.macros.internal;x-friends:="org.eclipse.e4.ui.macros.tests,org.eclipse.e4.ui.macros,org.eclipse.ui.workbench.texteditor.macros"
+Service-Component: OSGI-INF/macroService.xml
diff --git a/bundles/org.eclipse.e4.core.macros/OSGI-INF/l10n/bundle.properties b/bundles/org.eclipse.e4.core.macros/OSGI-INF/l10n/bundle.properties
new file mode 100644
index 0000000..b53b6c4
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/OSGI-INF/l10n/bundle.properties
@@ -0,0 +1,6 @@
+#Properties file for org.eclipse.e4.core.macros
+Bundle-Name = Core Macro Recording and Playback
+Bundle-Vendor = Eclipse.org
+extension-point.macroInstructionsFactory.name = Register class to recreate a macro instruction which has been previously recorded through the macro record/playback engine.
+extension-point.macroStateListeners.name = Listeners for changes in the macro service (i.e.: record/playback mode).
+extension-point.macroCommandCustomization.name = Describe command ids which should have some customization in macro handling (by default commands have their activation automatically record an IMacroInstruction and this extension allows a different handling).
diff --git a/bundles/org.eclipse.e4.core.macros/OSGI-INF/macroService.xml b/bundles/org.eclipse.e4.core.macros/OSGI-INF/macroService.xml
new file mode 100644
index 0000000..634ccfa
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/OSGI-INF/macroService.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.e4.core.macros.macroService">
+   <implementation class="org.eclipse.e4.core.macros.internal.MacroServiceCreationFunction"/>
+   <service>
+      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
+   </service>
+   <property name="service.context.key" type="String" value="org.eclipse.e4.core.macros.EMacroService"/>
+</scr:component>
diff --git a/bundles/org.eclipse.e4.core.macros/build.properties b/bundles/org.eclipse.e4.core.macros/build.properties
new file mode 100644
index 0000000..63c8f29
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/build.properties
@@ -0,0 +1,17 @@
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml,\
+               schema/,\
+               OSGI-INF/
+source.. = src/
+src.includes = schema/,\
+               src/,\
+               plugin.xml,\
+               pom.xml,\
+               build.properties,\
+               OSGI-INF/,\
+               META-INF/,\
+               .project,\
+               .classpath,\
+               .settings/
diff --git a/bundles/org.eclipse.e4.core.macros/plugin.xml b/bundles/org.eclipse.e4.core.macros/plugin.xml
new file mode 100644
index 0000000..8a78a5f
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/plugin.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension-point id="macroInstructionsFactory" name="%extension-point.macroInstructionsFactory.name" schema="schema/macroInstructionsFactory.exsd"/>
+   <extension-point id="macroStateListeners" name="%extension-point.macroStateListeners.name" schema="schema/macroStateListeners.exsd"/>
+   <extension-point id="macroCommandCustomization" name="%extension-point.macroCommandCustomization.name" schema="schema/macroCommandCustomization.exsd"/>
+</plugin>
diff --git a/bundles/org.eclipse.e4.core.macros/pom.xml b/bundles/org.eclipse.e4.core.macros/pom.xml
new file mode 100644
index 0000000..761f23f
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2017 Fabio Zadrozny and others.
+  All rights reserved. This program and the accompanying materials
+  are made available under the terms of the Eclipse Distribution License v1.0
+  which accompanies this distribution, and is available at
+  http://www.eclipse.org/org/documents/edl-v10.php
+
+  Contributors:
+     Fabio Zadrozny - initial implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.e4.ui</groupId>
+    <artifactId>e4-ui-aggregator</artifactId>
+    <version>0.17.0-SNAPSHOT</version>
+    <relativePath>../../</relativePath>
+  </parent>
+
+  <artifactId>org.eclipse.e4.core.macros</artifactId>
+  <version>0.1.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+
+ </project>
diff --git a/bundles/org.eclipse.e4.core.macros/schema/macroCommandCustomization.exsd b/bundles/org.eclipse.e4.core.macros/schema/macroCommandCustomization.exsd
new file mode 100644
index 0000000..b5df3f1
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/schema/macroCommandCustomization.exsd
@@ -0,0 +1,111 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.e4.ui.macros" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appinfo>
+         <meta.schema plugin="org.eclipse.e4.ui.macros" id="macroCommandCustomization" name=""/>
+      </appinfo>
+      <documentation>
+         Defines commands that will be customized during a macro record/playback operation -- by default,
+a macro instruction should be automatically added when in macro record mode to execute Eclipse commands
+during playback and this extension allows customization over that (i.e.: to skip recording a command).
+
+It&apos;s also possible to programatically customize how Eclipse commands are handled through the org.eclipse.e4.core.macros.EMacroService.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appinfo>
+            <meta.element />
+         </appinfo>
+      </annotation>
+      <complexType>
+         <choice minOccurs="1" maxOccurs="unbounded">
+            <element ref="whitelistedCommand"/>
+         </choice>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appinfo>
+                  <meta.attribute translatable="true"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="whitelistedCommand">
+      <annotation>
+         <documentation>
+            A command which is allowed during macro record/playback.
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  A command identifier
+               </documentation>
+               <appinfo>
+                  <meta.attribute kind="identifier" basedOn="org.eclipse.ui.commands/command/@id"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+         <attribute name="recordMacroInstruction" type="boolean" use="required">
+            <annotation>
+               <documentation>
+                  If true, the activation of the command will be recorded in the macro (i.e.: an IMacroInstruction will be automatically created and added to the macro when in record mode) and if false it won&apos;t.
+
+Examples of actions whose activation should be recorded include copy, paste, delete line and anything whose playback is simply re-executing that action.
+
+Examples of actions whose activation should not be recorded (in which case, they&apos;re allowed to execute, but only its side-effect should be recorded) include open find dialog (it should not open the dialog, just record the find text or replace text later on) and code-completion (code-completion may be allowed, but only the actual apply of a given code-completion should be recorded -- although the editor itself may decide to disable code-completion at its level so that the action does nothing until its code-completions aren&apos;t actually recorded in the macro).
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="since"/>
+      </appinfo>
+      <documentation>
+         0.1.0
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="examples"/>
+      </appinfo>
+      <documentation>
+         
+&lt;extension point=&quot;org.eclipse.e4.core.macros.macroCommandCustomization&quot;&gt;
+    &lt;customizedCommand id=&quot;org.eclipse.ui.edit.text.contentAssist.proposals&quot; recordMacroInstruction=&quot;false&quot;/&gt;
+&lt;/extension&gt;
+
+Will let the command &quot;org.eclipse.ui.edit.text.contentAssist.proposals&quot; be executed but will not record it to be re-executed on macro playback (in which case the command is responsible for recording its side-effects in the macro later on).
+      </documentation>
+   </annotation>
+
+
+
+
+</schema>
diff --git a/bundles/org.eclipse.e4.core.macros/schema/macroInstructionsFactory.exsd b/bundles/org.eclipse.e4.core.macros/schema/macroInstructionsFactory.exsd
new file mode 100644
index 0000000..b97365e
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/schema/macroInstructionsFactory.exsd
@@ -0,0 +1,108 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.e4.core.macros" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appinfo>
+         <meta.schema plugin="org.eclipse.e4.core.macros" id="macroInstructionsFactory" name="Factory for macro instructions"/>
+      </appinfo>
+      <documentation>
+         Register a factory for macro instructions (which is able to recreate an IMacroInstruction from the contents of its toMap() function).
+
+Any macro instruction which is added to the macro engine during the record phase must have a factory registered through this extension point (an error will be thrown if that&apos;s not the case).
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appinfo>
+            <meta.element />
+         </appinfo>
+      </annotation>
+      <complexType>
+         <choice minOccurs="1" maxOccurs="unbounded">
+            <element ref="macroInstructionsFactory"/>
+         </choice>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appinfo>
+                  <meta.attribute translatable="true"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="macroInstructionsFactory">
+      <annotation>
+         <documentation>
+            A macro instruction factory, which is used to recreate a macro previously persisted during a macro record session (in order to properly play it back later on).
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="macroInstructionId" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The id of the macro instruction which this factory can be used to create (i.e.: the method org.eclipse.e4.core.macros.IMacroInstruction.getId(), of the macro instructions created by this factory must return the same id).
+               </documentation>
+               <appinfo>
+                  <meta.attribute kind="identifier"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  The class which is the factory to recreate macro instructions.
+               </documentation>
+               <appinfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.e4.core.macros.IMacroInstructionFactory"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="since"/>
+      </appinfo>
+      <documentation>
+         0.1.0
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="examples"/>
+      </appinfo>
+      <documentation>
+         &lt;extension point=&quot;org.eclipse.e4.core.macros.macroInstructionsFactory&quot;&gt;
+    &lt;macroInstructionsFactory
+        class=&quot;org.eclipse.my.IMacroInstructionFactoryImplementation&quot;
+        macroInstructionId=&quot;org.eclipse.my.macro.instructionId&quot;&gt;
+    &lt;/macroInstructionsFactory&gt;
+&lt;/extension&gt;
+      </documentation>
+   </annotation>
+
+
+
+
+</schema>
diff --git a/bundles/org.eclipse.e4.core.macros/schema/macroStateListeners.exsd b/bundles/org.eclipse.e4.core.macros/schema/macroStateListeners.exsd
new file mode 100644
index 0000000..644404d
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/schema/macroStateListeners.exsd
@@ -0,0 +1,100 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.e4.core.macros" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appinfo>
+         <meta.schema plugin="org.eclipse.e4.core.macros" id="macroStateListeners" name="Listeners for changes on the macro state"/>
+      </appinfo>
+      <documentation>
+         Allows for other plugins to register listeners which must be notified of changes in the macro service (i.e.: when a record or playback is started or stopped).
+
+It&apos;s possible, for instance, to add listeners which will do the recording of keystrokes for playing back later when that happens, disable commands/actions which are not allowed during macro record/playback, add a listener to record changes to preferences, etc.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appinfo>
+            <meta.element />
+         </appinfo>
+      </annotation>
+      <complexType>
+         <choice minOccurs="1" maxOccurs="unbounded">
+            <element ref="macroStateListener"/>
+         </choice>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appinfo>
+                  <meta.attribute translatable="true"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="macroStateListener">
+      <complexType>
+         <attribute name="class" type="string">
+            <annotation>
+               <documentation>
+                  A listener for changes in the macro state (i.e.: macro record or playback started or stopped).
+
+Listeners should be added to listen the macro state when in order to properly record or playback a macro, some pre/post work must be done.
+
+For instance, an interceptor is added to the keybindings dispatcher in order to blacklist/whitelist commands being triggered by the user when in record mode.
+
+Note: it&apos;s lazily created the first time the macro service changes and the same instance is kept alive afterwards.
+
+Note: it&apos;s also possible to programatically add an IMacroStateListener to the EMacroService (so, existing instances, such as the text editor can act upon starting a macro record session and start recording keystrokes or disable code-completion if it can&apos;t deal with playing it back).
+               </documentation>
+               <appinfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.e4.core.macros.IMacroStateListener"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="since"/>
+      </appinfo>
+      <documentation>
+         0.1.0
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="examples"/>
+      </appinfo>
+      <documentation>
+         &lt;extension point=&quot;org.eclipse.e4.core.macros.macroStateListeners&quot;&gt;
+    &lt;macroStateListener
+        class=&quot;org.eclipse.impl.MyIMacroStateListenerImpl&quot;&gt;
+    &lt;/macroStateListener&gt;
+&lt;/extension&gt;
+      </documentation>
+   </annotation>
+
+
+
+
+</schema>
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/Activator.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/Activator.java
new file mode 100644
index 0000000..ca98f0f
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/Activator.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Plugin activator.
+ */
+public class Activator extends Plugin {
+
+	private static Activator plugin;
+
+	public Activator() {
+		super();
+		plugin = this;
+	}
+
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+	public static void log(Throwable exception) {
+		try {
+			if (plugin != null) {
+				plugin.getLog().log(new Status(IStatus.ERROR, plugin.getBundle().getSymbolicName(),
+						exception.getMessage(), exception));
+			} else {
+				// The plugin is not available. Just print to stderr.
+				exception.printStackTrace();
+			}
+		} catch (Exception e) {
+			// Print the original error if something happened, not the one
+			// related to the log not working.
+			exception.printStackTrace();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/CancelMacroException.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/CancelMacroException.java
new file mode 100644
index 0000000..f5afff7
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/CancelMacroException.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+public class CancelMacroException extends Exception {
+
+	private static final long serialVersionUID = -7828623675170028608L;
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/CancelMacroPlaybackException.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/CancelMacroPlaybackException.java
new file mode 100644
index 0000000..0cd7512
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/CancelMacroPlaybackException.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+/**
+ * An exception to be thrown when the macro playback should be stopped.
+ */
+public class CancelMacroPlaybackException extends CancelMacroException {
+
+	private static final long serialVersionUID = -953668757199552819L;
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/CancelMacroRecordingException.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/CancelMacroRecordingException.java
new file mode 100644
index 0000000..6ad6cd6
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/CancelMacroRecordingException.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+/**
+ * An exception to be thrown when the macro recording should be stopped.
+ */
+public class CancelMacroRecordingException extends CancelMacroException {
+
+	/**
+	 * Generated serial version UID.
+	 */
+	private static final long serialVersionUID = -5295116910722117940L;
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/EMacroService.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/EMacroService.java
new file mode 100644
index 0000000..3097995
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/EMacroService.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+/**
+ * Extension with the public API for dealing with macros.
+ *
+ * Can be accessed by getting it as a service:
+ * <p>
+ * &nbsp;&nbsp;&nbsp;site.getService(EMacroService.class)
+ * </p>
+ * or by having it injected:
+ * <p>
+ * &nbsp;&nbsp;&nbsp;@Inject<br/>
+ * &nbsp;&nbsp;&nbsp;EMacroService fMacroService;
+ * </p>
+ * <p>
+ * The idea is that clients will become aware that a macro record is taking
+ * place (through {@link #isRecording()} and will add their related macro
+ * instructions through {@link #addMacroInstruction(IMacroInstruction)}.
+ * </p>
+ * <p>
+ * It's also important to note that any macro instruction added through
+ * addMacroInstruction also needs to have an {@link IMacroInstructionFactory}
+ * registered through the org.eclipse.e4.core.macros.macroInstructionsFactory
+ * extension point (with a match through
+ * {@link org.eclipse.e4.core.macros.IMacroInstruction#getId()}).
+ * </p>
+ */
+public interface EMacroService {
+
+	/**
+	 * @return whether a macro is currently being recorded (note that it's possible
+	 *         for the user to start recording and then playback a macro
+	 *         simultaneously -- although the inverse is not true).
+	 */
+	boolean isRecording();
+
+	/**
+	 * @return whether a macro is currently being played back.
+	 */
+	boolean isPlayingBack();
+
+	/**
+	 * Adds a macro instruction to be added to the current macro being recorded. Any
+	 * macro instruction added also needs to have an
+	 * {@link IMacroInstructionFactory} registered through the
+	 * org.eclipse.e4.core.macros.macroInstructionsFactory extension point (with a
+	 * match through {@link org.eclipse.e4.core.macros.IMacroInstruction#getId()})
+	 *
+	 * Does nothing if there's no macro being currently recorded.
+	 *
+	 * @param macroInstruction
+	 *            the macro instruction to be added to the macro currently being
+	 *            recorded.
+	 */
+	void addMacroInstruction(IMacroInstruction macroInstruction);
+
+	int PRIORITY_LOW = 0;
+
+	int PRIORITY_HIGH = 10;
+
+	/**
+	 * Adds a macro instruction to be added to the current macro being recorded. The
+	 * difference between this method and
+	 * {@link #addMacroInstruction(IMacroInstruction)} is that it's meant to be used
+	 * when an event may trigger the creation of multiple macro instructions and
+	 * only one of those should be recorded.
+	 *
+	 * For instance, if a given KeyDown event is recorded in a StyledText and later
+	 * an action is triggered by this event, the recorded action should overwrite
+	 * the KeyDown event.
+	 *
+	 * @param macroInstruction
+	 *            the macro instruction to be added to the macro currently being
+	 *            recorded.
+	 * @param event
+	 *            the event that triggered the creation of the macro instruction to
+	 *            be added. If there are multiple macro instructions added for the
+	 *            same event, only the one with the highest priority will be kept
+	 *            (if 2 events have the same priority, the last one will replace the
+	 *            previous one).
+	 * @param priority
+	 *            the priority of the macro instruction being added (to be compared
+	 *            against the priority of other added macro instructions for the
+	 *            same event).
+	 * @see #addMacroInstruction(IMacroInstruction)
+	 */
+	void addMacroInstruction(IMacroInstruction macroInstruction, Object event, int priority);
+
+	/**
+	 * Toggles the macro record mode (i.e.: if it's currently not recording, starts
+	 * recording a macro, otherwise, stops the current record -- at which point a
+	 * macro should be saved with what was recorded so far).
+	 *
+	 * Note that when playing back, calling toggleMacroRecord() should do nothing
+	 * (while it's Ok to start recording and then playback a previous macro to add
+	 * previously recorded macro instructions to the current macro, the opposite is
+	 * not true).
+	 */
+	void toggleMacroRecord();
+
+	/**
+	 * Plays back the last recorded macro.
+	 *
+	 * Note: it's Ok to call it while a macro is being recorded (which should
+	 * playback the given macro and add its contents to the new macro being
+	 * recorded).
+	 *
+	 * @throws MacroPlaybackException
+	 */
+	void playbackLastMacro() throws MacroPlaybackException;
+
+	/**
+	 * Adds a macro state listener to be notified on changes in the macro
+	 * record/playback state.
+	 *
+	 * @param listener
+	 *            the listener to be added.
+	 */
+	void addMacroStateListener(IMacroStateListener listener);
+
+	/**
+	 * @param listener
+	 *            the macro listener which should no longer be notified of changes.
+	 */
+	void removeMacroStateListener(IMacroStateListener listener);
+
+	/**
+	 * @return the macro record context created when macro record started or null if
+	 *         it's not currently recording.
+	 */
+	IMacroRecordContext getMacroRecordContext();
+
+	/**
+	 * @return the macro playback context created when the macro playback started or
+	 *         null if it's not currently playing back.
+	 */
+	IMacroPlaybackContext getMacroPlaybackContext();
+
+	// Deal with managing accepted commands during macro record/playback.
+	// (by default should load the command behavior
+	// through the org.eclipse.e4.core.macros.macroCommandCustomization extension
+	// point,
+	// but it's possible to programmatically change it as needed later on).
+
+	/**
+	 * @param commandId
+	 *            the id of the command.
+	 *
+	 * @return whether the command should be recorded for playback when recording a
+	 *         macro (i.e.: an {@link org.eclipse.e4.core.macros.IMacroInstruction}
+	 *         will be automatically created to play it back when in record mode).
+	 *
+	 * @see org.eclipse.e4.core.macros.macroCommandCustomization extension point
+	 */
+	@SuppressWarnings("javadoc")
+	boolean getRecordCommandInMacro(String commandId);
+
+	/**
+	 * @param commandId
+	 *            the command id to be customized during macro record/playback.
+	 *
+	 * @param recordInMacro
+	 *            if true, the command activation will be automatically recorded in
+	 *            the macro -- which means that an
+	 *            {@link org.eclipse.e4.core.macros.IMacroInstruction} will be
+	 *            automatically created to play it back when in record mode. If
+	 *            false, the activation of the command will not be recorded.
+	 *
+	 * @see org.eclipse.e4.core.macros.macroCommandCustomization extension point
+	 */
+	@SuppressWarnings("javadoc")
+	void setRecordCommandInMacro(String commandId, boolean recordInMacro);
+
+	/**
+	 * Adds a macro instructions listener (it may be added to validate the current
+	 * state of the macro recording).
+	 *
+	 * @param macroInstructionsListener
+	 *            the listener for macro instructions.
+	 */
+	void addMacroInstructionsListener(IMacroInstructionsListener macroInstructionsListener);
+
+	/**
+	 * Removes a macro instructions listener.
+	 *
+	 * @param macroInstructionsListener
+	 *            the listener for macro instructions.
+	 */
+	void removeMacroInstructionsListener(IMacroInstructionsListener macroInstructionsListener);
+
+	/**
+	 * @return the number of macro instructions in the macro currently recorded or
+	 *         -1 if no macro is being recorded.
+	 */
+	int getLenOfMacroBeingRecorded();
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroContext.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroContext.java
new file mode 100644
index 0000000..4569588
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroContext.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+/**
+ * The context bound to the macro record or playback.
+ */
+public interface IMacroContext {
+
+	/**
+	 * @param key
+	 *            the key of the variable to be retrieved.
+	 * @return the object related to that variable.
+	 */
+	public Object get(String key);
+
+	/**
+	 * @param key
+	 *            the key of the variable to store.
+	 * @param value
+	 *            the value to be stored for that key.
+	 */
+	public void set(String key, Object value);
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroInstruction.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroInstruction.java
new file mode 100644
index 0000000..4a5b13f
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroInstruction.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+import java.util.Map;
+
+/**
+ * The basic abstraction of a macro instruction (i.e.: a macro may be composed
+ * of multiple macro instructions). The macro instruction also can be stored in
+ * disk to be reconstructed later on.
+ */
+public interface IMacroInstruction {
+
+	/**
+	 * @return the id for the macro instruction.
+	 * @note this id may be visible to the user, so, it should ideally be something
+	 *       short and readable (such as KeyDown, or Command), not a dotted name as
+	 *       is usual for Eclipse ids (and it can't be changed afterwards).
+	 */
+	String getId();
+
+	/**
+	 * Executes the macro instruction in the given context.
+	 *
+	 * @param macroPlaybackContext
+	 *            the context used to playback the macro.
+	 * @throws MacroPlaybackException
+	 *             if something didn't work when executing the macro.
+	 */
+	void execute(IMacroPlaybackContext macroPlaybackContext) throws MacroPlaybackException;
+
+	/**
+	 * Convert the macro instruction into a map (which may be later dumped to the
+	 * disk) and recreated with an
+	 * {@link org.eclipse.e4.core.macros.IMacroInstructionFactory} registered
+	 * through the org.eclipse.e4.core.macros.macroInstructionsFactory extension
+	 * point.
+	 *
+	 * @return a map which may be dumped to the disk and can be used to recreate the
+	 *         macro instruction later on.
+	 */
+	Map<String, String> toMap();
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroInstructionFactory.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroInstructionFactory.java
new file mode 100644
index 0000000..330c869
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroInstructionFactory.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+import java.util.Map;
+
+/**
+ * Factory for macro instructions which had the contents of
+ * {@link IMacroInstruction#toMap()} persisted.
+ *
+ * Should be registered through the
+ * org.eclipse.e4.core.macros.macroInstructionsFactory extension point (with a
+ * match through {@link org.eclipse.e4.core.macros.IMacroInstruction#getId()}).
+ */
+public interface IMacroInstructionFactory {
+
+	/**
+	 * @param stringMap
+	 *            a map which was created from {@link IMacroInstruction#toMap()}
+	 * @return the {@link IMacroInstruction} created from the given stringMap.
+	 * @throws Exception
+	 *             if some error happened recreating the macro instruction.
+	 */
+	IMacroInstruction create(Map<String, String> stringMap) throws Exception;
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroInstructionsListener.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroInstructionsListener.java
new file mode 100644
index 0000000..3d83d15
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroInstructionsListener.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+/**
+ * A listener for the macro instructions being added.
+ */
+public interface IMacroInstructionsListener {
+
+	/**
+	 * The macro instruction to be added to the macro.
+	 *
+	 * @param macroInstruction
+	 *            the macro instruction to be added.
+	 * @throws CancelMacroRecordingException
+	 *             if the recording of the macro should stop before actually adding
+	 *             the given macro instruction.
+	 */
+	void beforeMacroInstructionAdded(IMacroInstruction macroInstruction) throws CancelMacroRecordingException;
+
+	/**
+	 * Called after a given macro instruction is added to the macro. Note that it's
+	 * possible that beforeMacroInstructionAdded is called and
+	 * afterMacroInstructionAdded isn't if the macro instruction doesn't have enough
+	 * priority.
+	 *
+	 * @param macroInstruction
+	 *            the macro instruction just added to the current macro.
+	 */
+	void afterMacroInstructionAdded(IMacroInstruction macroInstruction);
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroPlaybackContext.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroPlaybackContext.java
new file mode 100644
index 0000000..de1d14e
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroPlaybackContext.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+import java.util.Map;
+
+/**
+ * Context passed when playing back a macro.
+ */
+public interface IMacroPlaybackContext extends IMacroContext {
+
+	/**
+	 * Creates a macro instruction (for execution) given its id and the
+	 * {@link IMacroInstruction#toMap()} contents gotten from a previously recorded
+	 * instruction.
+	 *
+	 * @param macroInstructionId
+	 *            the id of the macro instruction to be created.
+	 * @param stringMap
+	 *            the contents previously gotten from
+	 *            {@link IMacroInstruction#toMap()}.
+	 * @return a macro instruction created from the given id and parameters.
+	 * @throws Exception
+	 *             if some error was thrown when creating the macro instruction.
+	 */
+	IMacroInstruction createMacroInstruction(String macroInstructionId, Map<String, String> stringMap) throws Exception;
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroRecordContext.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroRecordContext.java
new file mode 100644
index 0000000..b6a837e
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroRecordContext.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+/**
+ * A context created when macro record starts.
+ */
+public interface IMacroRecordContext extends IMacroContext {
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroStateListener.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroStateListener.java
new file mode 100644
index 0000000..5a7eb8f
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroStateListener.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+/**
+ * Listener for changes in the EMacroService.
+ */
+public interface IMacroStateListener {
+
+	public enum StateChange {
+		RECORD_STARTED, PLAYBACK_STARTED, RECORD_FINISHED, PLAYBACK_FINISHED,
+	}
+
+	/**
+	 * Called when a record started/stopped or a playback started/stopped. Note that
+	 * a macro may be played back under a record session (although the opposite is
+	 * not true).
+	 *
+	 * @param macroService
+	 *            the macro service where the change happened.
+	 * @param stateChange
+	 *            the state change which just took place.
+	 * @throws CancelMacroException
+	 *             to stop the record or playback from happening.
+	 */
+	public void macroStateChanged(EMacroService macroService, StateChange stateChange)
+			throws CancelMacroException;
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroStateListener1.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroStateListener1.java
new file mode 100644
index 0000000..31b4b7a
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/IMacroStateListener1.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+/**
+ * Provides a way for clients to be notified of the creation of macro contexts
+ * to fill it as needed.
+ */
+public interface IMacroStateListener1 extends IMacroStateListener {
+
+	/**
+	 * Called after the creation of the macro playback context (before notifying
+	 * about changes to the macro state or actual playback).
+	 *
+	 * @param context
+	 *            the context for the macro playback.
+	 */
+	public void onMacroPlaybackContextCreated(IMacroPlaybackContext context);
+
+	/**
+	 * Called after the creation of the macro record context (before notifying about
+	 * changes to the macro state or actual record).
+	 *
+	 * @param context
+	 *            the context for the macro record.
+	 */
+	public void onMacroRecordContextCreated(IMacroRecordContext context);
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/MacroPlaybackException.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/MacroPlaybackException.java
new file mode 100644
index 0000000..9911e09
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/MacroPlaybackException.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros;
+
+/**
+ * An exception to be raised if there's some issue when playing back macros.
+ */
+public class MacroPlaybackException extends Exception {
+
+	/**
+	 * @param msg
+	 *            message for exception.
+	 */
+	public MacroPlaybackException(String msg) {
+		super(msg);
+	}
+
+	/**
+	 * @param msg
+	 *            message for exception.
+	 * @param e
+	 *            cause of exception.
+	 */
+	public MacroPlaybackException(String msg, Exception e) {
+		super(msg, e);
+	}
+
+	/**
+	 * Generated serial version UID.
+	 */
+	private static final long serialVersionUID = -2589166244366784288L;
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/ComposableMacro.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/ComposableMacro.java
new file mode 100644
index 0000000..806af4f
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/ComposableMacro.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros.internal;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.e4.core.macros.Activator;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.e4.core.macros.IMacroInstructionFactory;
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+import org.eclipse.e4.core.macros.MacroPlaybackException;
+
+/**
+ * This is a macro which is created from a sequence of instructions which are
+ * stored in-memory (and may be persisted later on).
+ */
+/* default */ class ComposableMacro implements IMacro {
+
+	/**
+	 * Provides the macro instruction id to an implementation which is able to
+	 * recreate it.
+	 */
+	private Map<String, IMacroInstructionFactory> fMacroInstructionIdToFactory;
+
+	/**
+	 * The macro instructions which compose this macro.
+	 */
+	private List<IMacroInstruction> fMacroInstructions = new ArrayList<>();
+
+	private static class IndexAndPriority {
+
+		private final int fIndex;
+		private final int fPriority;
+
+		private IndexAndPriority(int index, int priority) {
+			this.fIndex = index;
+			this.fPriority = priority;
+		}
+
+	}
+
+	/**
+	 * Map of an event to the current index of the macro instruction in
+	 * fMacroInstructions and the priority for the given macro instruction.
+	 */
+	private final Map<Object, IndexAndPriority> fEventToPlacement = new HashMap<>();
+
+	/**
+	 * @param macroInstructionIdToFactory
+	 *            Only macros instructions which have ids available as keys in the
+	 *            macroInstructionIdToFactory will be accepted.
+	 */
+	public ComposableMacro(Map<String, IMacroInstructionFactory> macroInstructionIdToFactory) {
+		fMacroInstructionIdToFactory = macroInstructionIdToFactory;
+	}
+
+	/**
+	 * Checks whether the added macro instruction is suitable to be added to this
+	 * macro.
+	 *
+	 * @param macroInstruction
+	 *            the macro instruction to be checked.
+	 */
+	private void checkMacroInstruction(IMacroInstruction macroInstruction) {
+		if (fMacroInstructionIdToFactory != null
+				&& !fMacroInstructionIdToFactory.containsKey(macroInstruction.getId())) {
+			throw new RuntimeException(String.format(
+					"Macro instruction: %s not properly registered through a %s extension point.", //$NON-NLS-1$
+					macroInstruction.getId(), MacroServiceImplementation.MACRO_INSTRUCTION_FACTORY_EXTENSION_POINT));
+		}
+	}
+
+	/**
+	 * Adds a new macro instruction to this macro.
+	 *
+	 * @param macroInstruction
+	 *            the macro instruction to be appended to this macro.
+	 */
+	public void addMacroInstruction(IMacroInstruction macroInstruction) {
+		checkMacroInstruction(macroInstruction);
+		fMacroInstructions.add(macroInstruction);
+	}
+
+	/**
+	 * Adds a macro instruction to be added to the current macro being recorded. The
+	 * difference between this method and
+	 * {@link #addMacroInstruction(IMacroInstruction)} is that it's meant to be used
+	 * when an event may trigger the creation of multiple macro instructions and
+	 * only one of those should be recorded.
+	 *
+	 * @param macroInstruction
+	 *            the macro instruction to be added to the macro currently being
+	 *            recorded.
+	 * @param event
+	 *            the event that triggered the creation of the macro instruction to
+	 *            be added. If there are multiple macro instructions added for the
+	 *            same event, only the one with the highest priority will be kept
+	 *            (if 2 events have the same priority, the last one will replace the
+	 *            previous one).
+	 * @param priority
+	 *            the priority of the macro instruction being added (to be compared
+	 *            against the priority of other added macro instructions for the
+	 *            same event).
+	 * @return true if the macro instruction was actually added and false otherwise.
+	 * @see #addMacroInstruction(IMacroInstruction)
+	 */
+	public boolean addMacroInstruction(IMacroInstruction macroInstruction, Object event, int priority) {
+		Assert.isNotNull(event);
+		IndexAndPriority currentIndexAndPriority = this.fEventToPlacement.get(event);
+		if (currentIndexAndPriority == null) {
+			this.addMacroInstruction(macroInstruction);
+			this.fEventToPlacement.put(event, new IndexAndPriority(this.fMacroInstructions.size() - 1, priority));
+			return true;
+		}
+		if (priority >= currentIndexAndPriority.fPriority) {
+			checkMacroInstruction(macroInstruction);
+			fMacroInstructions.set(currentIndexAndPriority.fIndex, macroInstruction);
+			this.fEventToPlacement.put(event, new IndexAndPriority(currentIndexAndPriority.fIndex, priority));
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Clears information obtained during recording which should be no longer needed
+	 * after the macro is properly composed.
+	 */
+	public void clearCachedInfo() {
+		this.fEventToPlacement.clear();
+	}
+
+	@Override
+	public void playback(IMacroPlaybackContext macroPlaybackContext) throws MacroPlaybackException {
+		for (IMacroInstruction macroInstruction : fMacroInstructions) {
+			macroInstruction.execute(macroPlaybackContext);
+		}
+	}
+
+	/**
+	 * Actually returns the bytes to be written to the disk to be loaded back later
+	 * on (the actual load and playback is later done by {@link SavedJSMacro}.
+	 *
+	 * @return an UTF-8 encoded array of bytes which can be used to rerun the macro
+	 *         later on.
+	 */
+	/* default */ byte[] toJSBytes() {
+		final StringBuilder buf = new StringBuilder(this.fMacroInstructions.size() * 60);
+
+		buf.append("// Macro generated by the Eclipse macro record engine.\n"); //$NON-NLS-1$
+		buf.append("// The runMacro() function will be later run by the macro engine.\n"); //$NON-NLS-1$
+		buf.append("function runMacro(){\n"); //$NON-NLS-1$
+
+		for (IMacroInstruction macroInstruction : this.fMacroInstructions) {
+			Map<String, String> map = macroInstruction.toMap();
+			Assert.isNotNull(map);
+
+			buf.append("    runMacroInstruction("); //$NON-NLS-1$
+			buf.append(JSONHelper.quote(macroInstruction.getId()));
+			buf.append(", "); //$NON-NLS-1$
+			buf.append(JSONHelper.toJSon(map));
+			buf.append(");\n"); //$NON-NLS-1$
+		}
+		buf.append("}\n"); //$NON-NLS-1$
+
+		try {
+			return buf.toString().getBytes("UTF-8"); //$NON-NLS-1$
+		} catch (UnsupportedEncodingException e) {
+			// Make this a RuntimeException (UTF-8 should definitely be
+			// supported).
+			Activator.log(e);
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * @return the number of macro instructions in this macro.
+	 */
+	public int getLength() {
+		return this.fMacroInstructions.size();
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/IMacro.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/IMacro.java
new file mode 100644
index 0000000..22059ad
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/IMacro.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros.internal;
+
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+import org.eclipse.e4.core.macros.MacroPlaybackException;
+
+/**
+ * Basic interface for a macro (private API, only meant to be used inside the
+ * org.eclipse.e4.core.macros plugin).
+ *
+ * Note that the actual macro implementation could be created from a list of
+ * macro instructions in memory, a javascript file to be run, a json/xml
+ * describing macro commands, etc.
+ */
+/* default */ interface IMacro {
+
+	/**
+	 * Used to playback a macro in the given context.
+	 *
+	 * @param macroPlaybackContext
+	 *            the context to playback the macro.
+	 * @throws MacroPlaybackException
+	 *             if there was some error running the macro.
+	 */
+	void playback(IMacroPlaybackContext macroPlaybackContext) throws MacroPlaybackException;
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/JSONHelper.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/JSONHelper.java
new file mode 100644
index 0000000..aad7125
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/JSONHelper.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros.internal;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Helper to convert a map to a JSON without adding new dependencies.
+ */
+public class JSONHelper {
+
+	public static String quote(String string) {
+		int len = string.length();
+		if (len == 0) {
+			return "\"\""; //$NON-NLS-1$
+		}
+
+		StringBuilder sb = new StringBuilder(len + 4);
+		sb.append('"');
+
+		for (int i = 0; i < len; i += 1) {
+			char c = string.charAt(i);
+			switch (c) {
+			case '"':
+			case '\\':
+			case '/':
+				sb.append('\\');
+				sb.append(c);
+				break;
+
+			case '\b':
+				sb.append("\\b"); //$NON-NLS-1$
+				break;
+
+			case '\f':
+				sb.append("\\f"); //$NON-NLS-1$
+				break;
+
+			case '\n':
+				sb.append("\\n"); //$NON-NLS-1$
+				break;
+
+			case '\r':
+				sb.append("\\r"); //$NON-NLS-1$
+				break;
+
+			case '\t':
+				sb.append("\\t"); //$NON-NLS-1$
+				break;
+
+			default:
+				if (c < ' ') {
+					String t = "000" + Integer.toHexString(c); //$NON-NLS-1$
+					sb.append("\\u" + t.substring(t.length() - 4)); //$NON-NLS-1$
+				} else {
+					sb.append(c);
+				}
+			}
+		}
+		sb.append('"');
+		return sb.toString();
+	}
+
+	/**
+	 * @param map
+	 *            a map to be converted to a json string.
+	 * @return a json string with the contents of the passed map.
+	 */
+	public static String toJSon(Map<String, String> map) {
+		Iterator<Entry<String, String>> iterator = map.entrySet().iterator();
+		final StringBuilder buf = new StringBuilder("{"); //$NON-NLS-1$
+
+		while (iterator.hasNext()) {
+			if (buf.length() > 1) {
+				buf.append(", "); //$NON-NLS-1$
+			}
+			Entry<String, String> entry = iterator.next();
+			buf.append(quote(entry.getKey()));
+			buf.append(": "); //$NON-NLS-1$
+			buf.append(quote(entry.getValue()));
+		}
+		buf.append('}');
+		return buf.toString();
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroManager.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroManager.java
new file mode 100644
index 0000000..728660c
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroManager.java
@@ -0,0 +1,542 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.e4.core.macros.Activator;
+import org.eclipse.e4.core.macros.CancelMacroException;
+import org.eclipse.e4.core.macros.CancelMacroRecordingException;
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.e4.core.macros.IMacroInstructionFactory;
+import org.eclipse.e4.core.macros.IMacroInstructionsListener;
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+import org.eclipse.e4.core.macros.IMacroRecordContext;
+import org.eclipse.e4.core.macros.IMacroStateListener;
+import org.eclipse.e4.core.macros.IMacroStateListener.StateChange;
+import org.eclipse.e4.core.macros.IMacroStateListener1;
+import org.eclipse.e4.core.macros.MacroPlaybackException;
+
+/**
+ * Macro manager (pure java, without any OSGI requirements).
+ */
+public class MacroManager {
+
+	private static final String JS_EXT = ".js"; //$NON-NLS-1$
+
+	private static final String TEMP_MACRO_PREFIX = "temp_macro_"; //$NON-NLS-1$
+
+	/**
+	 * The max number of temporary macros to be kept (can't be lower than 1).
+	 */
+	private int fMaxNumberOfTemporaryMacros = 5;
+
+	/**
+	 * @param maxNumberOfTemporaryMacros
+	 *            The max number of temporary macros to be kept.
+	 */
+	public void setMaxNumberOfTemporaryMacros(int maxNumberOfTemporaryMacros) {
+		Assert.isTrue(maxNumberOfTemporaryMacros >= 1);
+		this.fMaxNumberOfTemporaryMacros = maxNumberOfTemporaryMacros;
+	}
+
+	/**
+	 * @return Returns the max number of temporary macros to be kept.
+	 */
+	public int getMaxNumberOfTemporaryMacros() {
+		return fMaxNumberOfTemporaryMacros;
+	}
+
+	/**
+	 * The directories where macros should be looked up. The first directory is the
+	 * one where macros are persisted.
+	 */
+	private File[] fMacrosDirectories;
+
+	/**
+	 * Holds the macro currently being recorded (if we're in record mode). If not in
+	 * record mode, should be null.
+	 */
+	private ComposableMacro fMacroBeingRecorded;
+
+	/**
+	 * Holds the last recorded or played back macro.
+	 */
+	private IMacro fLastMacro;
+
+	/**
+	 * Flag indicating whether we're playing back a macro.
+	 */
+	private boolean fIsPlayingBack = false;
+
+	/**
+	 * State to be used when recording macro.
+	 */
+	private IMacroRecordContext fMacroRecordContext;
+
+	/**
+	 * State to be used when playing back macro.
+	 */
+	private IMacroPlaybackContext fMacroPlaybackContext;
+
+	/**
+	 * Creates a manager for macros which will read macros from the given
+	 * directories.
+	 *
+	 * @param macrosDirectories
+	 *            the directories where macros should be looked up. The first
+	 *            directory is the one where macros are persisted. If there are 2
+	 *            macros which would end up having the same name, the one in the
+	 *            directory that appears last is the one which is used.
+	 */
+	public MacroManager(File... macrosDirectories) {
+		setMacrosDirectories(macrosDirectories);
+	}
+
+	/**
+	 * @param macrosDirectories
+	 *            the directories where macros should be looked up. The first
+	 *            directory is the one where macros are persisted. If there are 2
+	 *            macros which would end up having the same name, the one in the
+	 *            directory that appears last is the one which is used.
+	 */
+	public void setMacrosDirectories(File... macrosDirectories) {
+		Assert.isNotNull(macrosDirectories);
+		for (File file : macrosDirectories) {
+			Assert.isNotNull(file);
+		}
+		this.fMacrosDirectories = macrosDirectories;
+		reloadMacros();
+	}
+
+	/**
+	 * @return whether a macro is currently being recorded.
+	 */
+	public boolean isRecording() {
+		return fMacroBeingRecorded != null;
+	}
+
+	/**
+	 * @return whether a macro is currently being played back.
+	 */
+	public boolean isPlayingBack() {
+		return fIsPlayingBack;
+	}
+
+	/**
+	 * Adds a macro instruction to the macro currently being recorded. Does nothing
+	 * if no macro is being recorded.
+	 *
+	 * @param macroInstruction
+	 *            the macro instruction to be recorded.
+	 * @throws CancelMacroRecordingException
+	 */
+	public void addMacroInstruction(IMacroInstruction macroInstruction) throws CancelMacroRecordingException {
+		ComposableMacro macroBeingRecorded = fMacroBeingRecorded;
+		if (macroBeingRecorded != null) {
+			for (IMacroInstructionsListener listener : fMacroInstructionsListeners) {
+				listener.beforeMacroInstructionAdded(macroInstruction);
+			}
+			macroBeingRecorded.addMacroInstruction(macroInstruction);
+			for (IMacroInstructionsListener listener : fMacroInstructionsListeners) {
+				listener.afterMacroInstructionAdded(macroInstruction);
+			}
+		}
+	}
+
+	/**
+	 * Adds a macro instruction to be added to the current macro being recorded. The
+	 * difference between this method and
+	 * {@link #addMacroInstruction(IMacroInstruction)} is that it's meant to be used
+	 * when an event may trigger the creation of multiple macro instructions and
+	 * only one of those should be recorded.
+	 *
+	 * For instance, if a given KeyDown event is recorded in a StyledText and later
+	 * an action is triggered by this event, the recorded action should overwrite
+	 * the KeyDown event.
+	 *
+	 * @param macroInstruction
+	 *            the macro instruction to be added to the macro currently being
+	 *            recorded.
+	 * @param event
+	 *            the event that triggered the creation of the macro instruction to
+	 *            be added. If there are multiple macro instructions added for the
+	 *            same event, only the one with the highest priority will be kept
+	 *            (if 2 events have the same priority, the last one will replace the
+	 *            previous one).
+	 * @param priority
+	 *            the priority of the macro instruction being added (to be compared
+	 *            against the priority of other added macro instructions for the
+	 *            same event).
+	 * @throws CancelMacroRecordingException
+	 * @see #addMacroInstruction(IMacroInstruction)
+	 */
+	public void addMacroInstruction(IMacroInstruction macroInstruction, Object event, int priority)
+			throws CancelMacroRecordingException {
+		ComposableMacro macroBeingRecorded = fMacroBeingRecorded;
+		if (macroBeingRecorded != null) {
+			for (IMacroInstructionsListener listener : fMacroInstructionsListeners) {
+				listener.beforeMacroInstructionAdded(macroInstruction);
+			}
+			if (macroBeingRecorded.addMacroInstruction(macroInstruction, event, priority)) {
+				for (IMacroInstructionsListener listener : fMacroInstructionsListeners) {
+					listener.afterMacroInstructionAdded(macroInstruction);
+				}
+			}
+		}
+	}
+
+	private static final class MacroRecordContext implements IMacroRecordContext {
+
+		private final Map<Object, Object> ctx = new HashMap<>();
+
+		@Override
+		public Object get(String key) {
+			return ctx.get(key);
+		}
+
+		@Override
+		public void set(String key, Object value) {
+			ctx.put(key, value);
+		}
+	}
+
+	/**
+	 * Toggles the macro record (either starts recording or stops an existing
+	 * record).
+	 *
+	 * @param macroService
+	 *            service to record macros.
+	 * @param macroInstructionIdToFactory
+	 *            a mapping of the available macro instruction ids to the factory
+	 *            which is able to recreate the related macro instruction.
+	 */
+	public void toggleMacroRecord(final EMacroService macroService,
+			Map<String, IMacroInstructionFactory> macroInstructionIdToFactory) {
+		if (fIsPlayingBack) {
+			// Can't toggle the macro record mode while playing back.
+			return;
+		}
+		if (fMacroBeingRecorded == null) {
+			// Start recording
+			fMacroRecordContext = new MacroRecordContext();
+			fMacroBeingRecorded = new ComposableMacro(macroInstructionIdToFactory);
+			for (IMacroStateListener listener : this.fStateListeners) {
+				if (listener instanceof IMacroStateListener1) {
+					IMacroStateListener1 macroStateListener = (IMacroStateListener1) listener;
+					SafeRunner.run(() -> macroStateListener.onMacroRecordContextCreated(fMacroRecordContext));
+				}
+			}
+			if (!notifyMacroStateChange(macroService, StateChange.RECORD_STARTED)) {
+				stopRecording(macroService);
+			}
+		} else {
+			stopRecording(macroService);
+		}
+	}
+
+	/**
+	 * Stops the macro recording.
+	 *
+	 * @param macroService
+	 *            service to record macros.
+	 */
+	private void stopRecording(final EMacroService macroService) {
+		try {
+			fMacroBeingRecorded.clearCachedInfo();
+			if (fMacroBeingRecorded.getLength() > 0) {
+				// No point in saving an empty macro.
+				saveTemporaryMacro(fMacroBeingRecorded);
+				fLastMacro = fMacroBeingRecorded;
+			}
+		} finally {
+			fMacroBeingRecorded = null;
+			// Notify only after setting fMacroBeingRecorded to null (which will
+			// make isRecording return false on the notification);
+			notifyMacroStateChange(macroService, StateChange.RECORD_FINISHED);
+			fMacroRecordContext = null;
+		}
+	}
+
+	/**
+	 * Helper class to store a path an a time.
+	 */
+	public static final class PathAndTime {
+
+		public final Path fPath;
+		public final long fLastModified;
+
+		public PathAndTime(Path path, long lastModified) {
+			this.fPath = path;
+			this.fLastModified = lastModified;
+		}
+
+	}
+
+	/**
+	 * @param macro
+	 *            the macro to be recorded as a temporary macro.
+	 */
+	private void saveTemporaryMacro(ComposableMacro macro) {
+		if (fMacrosDirectories == null || this.fMacrosDirectories.length == 0) {
+			return;
+		}
+		// The first one is the one we use as a working directory to store
+		// temporary macros.
+		File macroDirectory = this.fMacrosDirectories[0];
+		if (!macroDirectory.isDirectory()) {
+			Activator.log(new RuntimeException(
+					String.format("Unable to save macro. Expected: %s to be a directory.", macroDirectory))); //$NON-NLS-1$
+			return;
+		}
+
+		List<PathAndTime> pathAndTime = listTemporaryMacrosPathAndTime(macroDirectory);
+
+		try {
+			Path tempFile = Files.createTempFile(Paths.get(macroDirectory.toURI()), TEMP_MACRO_PREFIX, JS_EXT);
+			Files.write(tempFile, macro.toJSBytes(), StandardOpenOption.CREATE, StandardOpenOption.WRITE,
+					StandardOpenOption.TRUNCATE_EXISTING);
+		} catch (IOException e) {
+			Activator.log(e);
+			return; // Can't create file at expected place;
+		}
+
+		// Remove older files
+		while (pathAndTime.size() >= fMaxNumberOfTemporaryMacros) {
+			PathAndTime removeFile = pathAndTime.remove(pathAndTime.size() - 1);
+			try {
+				Files.deleteIfExists(removeFile.fPath);
+			} catch (Exception e) {
+				Activator.log(e);
+			}
+		}
+	}
+
+	/**
+	 * @param macroDirectory
+	 *            the directory from where we should get the temporary macros.
+	 *
+	 * @return The path/time for the temporary macros at a given directory as an
+	 *         array list sorted such that the last element is the oldest one and
+	 *         the first is the newest.
+	 */
+	public List<PathAndTime> listTemporaryMacrosPathAndTime(File macroDirectory) {
+		// It's a sorted list and not a tree map to deal with the case of
+		// multiple times pointing to the same file (although hard to happen,
+		// it's not impossible).
+		List<PathAndTime> pathAndTime = new ArrayList<>();
+
+		try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(macroDirectory.toURI()),
+				new DirectoryStream.Filter<Path>() {
+
+					@Override
+					public boolean accept(Path entry) {
+						String name = entry.getFileName().toString().toLowerCase();
+						return name.startsWith(TEMP_MACRO_PREFIX) && name.endsWith(JS_EXT);
+					}
+				})) {
+			for (Path p : directoryStream) {
+				pathAndTime.add(new PathAndTime(p, Files.getLastModifiedTime(p).to(TimeUnit.NANOSECONDS)));
+			}
+		} catch (IOException e1) {
+			Activator.log(e1);
+		}
+
+		// Sort by reversed modified time (because it's faster to remove the
+		// last element from an ArrayList later on).
+		Collections.sort(pathAndTime, new Comparator<PathAndTime>() {
+
+			@Override
+			public int compare(PathAndTime o1, PathAndTime o2) {
+				return Long.compare(o2.fLastModified, o1.fLastModified);
+			}
+		});
+		return pathAndTime;
+	}
+
+	/**
+	 * Notifies that a macro state change occurred (see
+	 * {@link org.eclipse.e4.core.macros.IMacroStateListener}).
+	 *
+	 * @return false if a listener has throw a CancelMacroException and true
+	 *         otherwise.
+	 */
+	private boolean notifyMacroStateChange(final EMacroService macroService, final StateChange stateChange) {
+		boolean okToGo = true;
+		for (final IMacroStateListener listener : fStateListeners) {
+			try {
+				listener.macroStateChanged(macroService, stateChange);
+			} catch (CancelMacroException e) {
+				okToGo = false;
+			} catch (Exception e) {
+				Activator.log(e);
+			}
+		}
+		return okToGo;
+	}
+
+	/**
+	 * Playback the last recorded macro.
+	 *
+	 * @param macroService
+	 *            the macro service (used to notify listeners of the change.
+	 * @param macroPlaybackContext
+	 *            a context to be used to playback the macro (passed to the macro to
+	 *            be played back).
+	 * @throws MacroPlaybackException
+	 *             if some error happens when running the macro.
+	 */
+	public void playbackLastMacro(EMacroService macroService, final IMacroPlaybackContext macroPlaybackContext)
+			throws MacroPlaybackException {
+		if (fLastMacro != null && !fIsPlayingBack) {
+			// Note that we can play back while recording, but we can't change
+			// the recording mode while playing back.
+			fIsPlayingBack = true;
+			try {
+				fMacroPlaybackContext = macroPlaybackContext;
+				for (IMacroStateListener listener : this.fStateListeners) {
+					if (listener instanceof IMacroStateListener1) {
+						IMacroStateListener1 macroStateListener = (IMacroStateListener1) listener;
+						SafeRunner.run(() -> macroStateListener.onMacroPlaybackContextCreated(macroPlaybackContext));
+					}
+				}
+
+				if (notifyMacroStateChange(macroService, StateChange.PLAYBACK_STARTED)) {
+					fLastMacro.playback(macroPlaybackContext);
+				}
+			} finally {
+				fIsPlayingBack = false;
+				notifyMacroStateChange(macroService, StateChange.PLAYBACK_FINISHED);
+				fMacroPlaybackContext = null;
+			}
+		}
+	}
+
+	/**
+	 * A list with the listeners to be notified of changes in the macro service.
+	 */
+	private final ListenerList<IMacroStateListener> fStateListeners = new ListenerList<>();
+
+	/**
+	 * Adds a macro listener to be notified on changes in the macro record/playback
+	 * state.
+	 *
+	 * @param listener
+	 *            the listener to be added.
+	 */
+	public void addMacroStateListener(IMacroStateListener listener) {
+		fStateListeners.add(listener);
+	}
+
+	/**
+	 * @param listener
+	 *            the macro listener which should no longer be notified of changes.
+	 */
+	public void removeMacroStateListener(IMacroStateListener listener) {
+		fStateListeners.remove(listener);
+	}
+
+	/**
+	 * @return the currently registered listeners.
+	 */
+	public IMacroStateListener[] getMacroStateListeners() {
+		Object[] listeners = fStateListeners.getListeners();
+		IMacroStateListener[] macroStateListeners = new IMacroStateListener[listeners.length];
+		System.arraycopy(listeners, 0, macroStateListeners, 0, listeners.length);
+		return macroStateListeners;
+	}
+
+	/**
+	 * Reloads the macros available from the disk.
+	 */
+	public void reloadMacros() {
+		for (File macroDirectory : this.fMacrosDirectories) {
+			if (macroDirectory.isDirectory()) {
+				List<PathAndTime> listPathsAndTimes = listTemporaryMacrosPathAndTime(macroDirectory);
+				if (listPathsAndTimes.size() > 0) {
+					this.fLastMacro = new SavedJSMacro(listPathsAndTimes.get(0).fPath.toFile());
+					return; // Load the last from the first directory (others aren't used for the last
+							// macro).
+				}
+			} else {
+				Activator.log(new RuntimeException(String.format("Expected: %s to be a directory.", macroDirectory))); //$NON-NLS-1$
+			}
+		}
+	}
+
+	private final ListenerList<IMacroInstructionsListener> fMacroInstructionsListeners = new ListenerList<>();
+
+	/**
+	 * Adds a macro instructions listener (it may be added to validate the current
+	 * state of the macro recording).
+	 *
+	 * @param macroInstructionsListener
+	 *            the listener for macro instructions.
+	 */
+	public void addMacroInstructionsListener(IMacroInstructionsListener macroInstructionsListener) {
+		fMacroInstructionsListeners.add(macroInstructionsListener);
+	}
+
+	/**
+	 * Removes a macro instructions listener.
+	 *
+	 * @param macroInstructionsListener
+	 *            the listener for macro instructions.
+	 */
+	public void removeMacroInstructionsListener(IMacroInstructionsListener macroInstructionsListener) {
+		fMacroInstructionsListeners.remove(macroInstructionsListener);
+	}
+
+	/**
+	 * @return the macro record context created when macro record started or null if
+	 *         it's not currently recording.
+	 */
+	public IMacroRecordContext getMacroRecordContext() {
+		return fMacroRecordContext;
+	}
+
+	/**
+	 * @return the macro playback context created when macro playback started or
+	 *         null if it's not currently recording.
+	 */
+	public IMacroPlaybackContext getMacroPlaybackContext() {
+		return fMacroPlaybackContext;
+	}
+
+	/**
+	 * @return the number of macro instructions in the macro currently recorded or
+	 *         -1 if no macro is being recorded.
+	 */
+	public int getLenOfMacroBeingRecorded() {
+		if (fMacroBeingRecorded != null) {
+			return fMacroBeingRecorded.getLength();
+		}
+		return -1;
+	}
+
+
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroPlaybackContextImpl.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroPlaybackContextImpl.java
new file mode 100644
index 0000000..c45cb1e
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroPlaybackContextImpl.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.e4.core.macros.IMacroInstructionFactory;
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+
+/**
+ * Provides a way to recreate commands when playing back a macro.
+ */
+public class MacroPlaybackContextImpl implements IMacroPlaybackContext {
+
+	/**
+	 * Map from the macro instruction id to the factory which should recreate it.
+	 */
+	private Map<String, IMacroInstructionFactory> fMacroInstructionIdToFactory;
+
+	/**
+	 * @param macroInstructionIdToFactory
+	 *            a map from the macro instruction id to the factory which should
+	 *            recreate it.
+	 */
+	public MacroPlaybackContextImpl(Map<String, IMacroInstructionFactory> macroInstructionIdToFactory) {
+		this.fMacroInstructionIdToFactory = macroInstructionIdToFactory;
+	}
+
+	@Override
+	public IMacroInstruction createMacroInstruction(String macroInstructionId, Map<String, String> stringMap)
+			throws Exception {
+		IMacroInstructionFactory macroFactory = fMacroInstructionIdToFactory.get(macroInstructionId);
+		if (macroFactory == null) {
+			throw new RuntimeException(
+					"Unable to find IMacroInstructionFactory for macro instruction: " + macroInstructionId); //$NON-NLS-1$
+		}
+		return macroFactory.create(stringMap);
+	}
+
+	private final Map<Object, Object> ctx = new HashMap<>();
+
+	@Override
+	public Object get(String key) {
+		return ctx.get(key);
+	}
+
+	@Override
+	public void set(String key, Object value) {
+		ctx.put(key, value);
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroServiceCreationFunction.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroServiceCreationFunction.java
new file mode 100644
index 0000000..da1fd60
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroServiceCreationFunction.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros.internal;
+
+import org.eclipse.e4.core.contexts.ContextFunction;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.macros.EMacroService;
+
+/**
+ * Creates a
+ * {@link org.eclipse.e4.core.macros.internal.MacroServiceImplementation} (to be
+ * bound to EMacroService).
+ *
+ * @note internal API: users should generally just get the EMacroService as a
+ *       service or with @Inject. Will always return the same instance (only a
+ *       single macro service is expected per application).
+ */
+public class MacroServiceCreationFunction extends ContextFunction {
+
+	private static EMacroService fService;
+
+	@Override
+	public Object compute(IEclipseContext context, String contextKey) {
+		if (fService == null) {
+			fService = ContextInjectionFactory.make(MacroServiceImplementation.class, context);
+		}
+		return fService;
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroServiceImplementation.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroServiceImplementation.java
new file mode 100644
index 0000000..8672c30
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/MacroServiceImplementation.java
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros.internal;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import javax.inject.Inject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.macros.Activator;
+import org.eclipse.e4.core.macros.CancelMacroRecordingException;
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.e4.core.macros.IMacroInstructionFactory;
+import org.eclipse.e4.core.macros.IMacroInstructionsListener;
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+import org.eclipse.e4.core.macros.IMacroRecordContext;
+import org.eclipse.e4.core.macros.IMacroStateListener;
+import org.eclipse.e4.core.macros.MacroPlaybackException;
+
+/**
+ * An implementation of the public API for dealing with macros (mostly passes
+ * things to an internal MacroManager instance and sets it up properly, dealing
+ * with the eclipse context and extension points).
+ */
+public class MacroServiceImplementation implements EMacroService {
+
+	/**
+	 * The instance of the macro manager.
+	 */
+	private MacroManager fMacroManager;
+
+	/**
+	 * Gets the macro manager (lazily creates it if needed).
+	 *
+	 * @return the macro manager responsible for managing macros.
+	 */
+	public MacroManager getMacroManager() {
+		if (fMacroManager == null) {
+			// user.home/.eclipse is already used by oomph and recommenders, so,
+			// it seems a good place to read additional macros which should be
+			// persisted for the user who wants to store macros across
+			// workspaces.
+			Activator plugin = Activator.getDefault();
+			File[] macrosDirectory;
+			if (plugin != null) {
+				IPath stateLocation = plugin.getStateLocation();
+				stateLocation.append("macros"); //$NON-NLS-1$
+				File userHome = new File(System.getProperty("user.home")); //$NON-NLS-1$
+				File eclipseUserHome = new File(userHome, ".eclipse"); //$NON-NLS-1$
+				File eclipseUserHomeMacros = new File(eclipseUserHome, "org.eclipse.e4.core.macros"); //$NON-NLS-1$
+				File eclipseUserHomeMacrosLoadDir = new File(eclipseUserHomeMacros, "macros"); //$NON-NLS-1$
+				if (!eclipseUserHomeMacrosLoadDir.exists()) {
+					eclipseUserHomeMacrosLoadDir.mkdirs();
+				}
+				macrosDirectory = new File[] { stateLocation.toFile(), eclipseUserHomeMacrosLoadDir };
+				// By default macros are saved/loaded under the workspace, but
+				// can also be loaded from the
+				//
+				// user.home/.eclipse/org.eclipse.e4.macros/macros
+				//
+				// directory.
+			} else {
+				macrosDirectory = new File[] {};
+			}
+			fMacroManager = new MacroManager(macrosDirectory);
+		}
+		return fMacroManager;
+	}
+
+	public static final String MACRO_INSTRUCTION_FACTORY_EXTENSION_POINT = "org.eclipse.e4.core.macros.macroInstructionsFactory"; //$NON-NLS-1$
+	public static final String MACRO_INSTRUCTION_ID = "macroInstructionId"; //$NON-NLS-1$
+	public static final String MACRO_INSTRUCTION_FACTORY_CLASS = "class"; //$NON-NLS-1$
+
+	// Globally loaded id to factory
+	private static Map<String, IMacroInstructionFactory> fCachedMacroInstructionIdToFactory;
+
+	// id to factory used in instance
+	private Map<String, IMacroInstructionFactory> fMacroInstructionIdToFactory;
+
+	public static final String MACRO_LISTENERS_EXTENSION_POINT = "org.eclipse.e4.core.macros.macroStateListeners"; //$NON-NLS-1$
+	public static final String MACRO_LISTENER_CLASS = "class"; //$NON-NLS-1$
+
+	private boolean fLoadedExtensionListeners = false;
+
+	private IEclipseContext fEclipseContext;
+
+	private IExtensionRegistry fExtensionRegistry;
+
+	@Inject
+	public MacroServiceImplementation(IEclipseContext eclipseContext, IExtensionRegistry extensionRegistry) {
+		this.fEclipseContext = eclipseContext;
+		this.fExtensionRegistry = extensionRegistry;
+	}
+
+
+	/**
+	 * Loads the macro listeners provided through extension points.
+	 */
+	private void loadExtensionPointsmacroStateListeners() {
+		if (!fLoadedExtensionListeners && fExtensionRegistry != null) {
+			fLoadedExtensionListeners = true;
+
+			MacroManager macroManager = getMacroManager();
+			for (IConfigurationElement ce : fExtensionRegistry
+					.getConfigurationElementsFor(MACRO_LISTENERS_EXTENSION_POINT)) {
+				String macroStateListenerClass = ce.getAttribute(MACRO_LISTENER_CLASS);
+				if (macroStateListenerClass != null) {
+					try {
+						IMacroStateListener macroStateListener = (IMacroStateListener) ce
+								.createExecutableExtension(MACRO_LISTENER_CLASS);
+						// Make sure that it has the proper eclipse context.
+						ContextInjectionFactory.inject(macroStateListener, fEclipseContext);
+						macroManager.addMacroStateListener(macroStateListener);
+					} catch (CoreException e) {
+						Activator.log(e);
+					}
+				} else {
+					Activator.log(new RuntimeException(
+							"Wrong definition for extension: " + MACRO_LISTENERS_EXTENSION_POINT + ": " + ce)); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+	}
+
+	/**
+	 * @return Returns the fMacroInstructionIdToFactory (creates it lazily if it
+	 *         still wasn't created).
+	 */
+	private Map<String, IMacroInstructionFactory> getMacroInstructionIdToFactory() {
+		if (fMacroInstructionIdToFactory == null) {
+			if (fCachedMacroInstructionIdToFactory == null && fEclipseContext != null && fExtensionRegistry != null) {
+				Map<String, IMacroInstructionFactory> validMacroInstructionIds = new HashMap<>();
+				for (IConfigurationElement ce : fExtensionRegistry
+						.getConfigurationElementsFor(MACRO_INSTRUCTION_FACTORY_EXTENSION_POINT)) {
+					String macroInstructionId = ce.getAttribute(MACRO_INSTRUCTION_ID);
+					String macroInstructionFactoryClass = ce.getAttribute(MACRO_INSTRUCTION_FACTORY_CLASS);
+					if (macroInstructionId != null && macroInstructionFactoryClass != null) {
+						try {
+							IMacroInstructionFactory macroInstructionFactory = (IMacroInstructionFactory) ce
+									.createExecutableExtension(MACRO_INSTRUCTION_FACTORY_CLASS);
+
+							// Make sure that it has the proper eclipse context.
+							ContextInjectionFactory.inject(macroInstructionFactory, fEclipseContext);
+							validMacroInstructionIds.put(macroInstructionId, macroInstructionFactory);
+						} catch (CoreException e) {
+							Activator.log(e);
+						}
+					} else {
+						Activator.log(new RuntimeException("Wrong definition for extension: " //$NON-NLS-1$
+								+ MACRO_INSTRUCTION_FACTORY_EXTENSION_POINT + ": " + ce)); //$NON-NLS-1$
+					}
+				}
+				fCachedMacroInstructionIdToFactory = validMacroInstructionIds;
+			}
+			fMacroInstructionIdToFactory = fCachedMacroInstructionIdToFactory;
+		}
+		return fMacroInstructionIdToFactory;
+	}
+
+	@Override
+	public boolean isRecording() {
+		if (fMacroManager == null) {
+			// Avoid creating if possible
+			return false;
+		}
+		return getMacroManager().isRecording();
+	}
+
+	@Override
+	public boolean isPlayingBack() {
+		if (fMacroManager == null) {
+			// Avoid creating if possible
+			return false;
+		}
+		return getMacroManager().isPlayingBack();
+	}
+
+	@Override
+	public void addMacroInstruction(IMacroInstruction macroInstruction) {
+		if (this.isRecording()) {
+			try {
+				getMacroManager().addMacroInstruction(macroInstruction);
+			} catch (CancelMacroRecordingException e) {
+				stopMacroRecording();
+			}
+		}
+	}
+
+	@Override
+	public void addMacroInstruction(IMacroInstruction macroInstruction, Object event, int priority) {
+		if (this.isRecording()) {
+			try {
+				getMacroManager().addMacroInstruction(macroInstruction, event, priority);
+			} catch (CancelMacroRecordingException e) {
+				stopMacroRecording();
+			}
+		}
+	}
+
+	/**
+	 * Stops the macro recording.
+	 */
+	private void stopMacroRecording() {
+		if (this.isRecording()) {
+			this.toggleMacroRecord();
+		}
+	}
+
+	@Override
+	public void toggleMacroRecord() {
+		loadExtensionPointsmacroStateListeners();
+		getMacroManager().toggleMacroRecord(this, getMacroInstructionIdToFactory());
+	}
+
+	@Override
+	public void playbackLastMacro() throws MacroPlaybackException {
+		loadExtensionPointsmacroStateListeners();
+		IMacroPlaybackContext macroPlaybackContext = new MacroPlaybackContextImpl(getMacroInstructionIdToFactory());
+		getMacroManager().playbackLastMacro(this, macroPlaybackContext);
+	}
+
+	@Override
+	public void addMacroStateListener(IMacroStateListener listener) {
+		getMacroManager().addMacroStateListener(listener);
+	}
+
+	@Override
+	public void removeMacroStateListener(IMacroStateListener listener) {
+		getMacroManager().removeMacroStateListener(listener);
+	}
+
+	@Override
+	public IMacroRecordContext getMacroRecordContext() {
+		return getMacroManager().getMacroRecordContext();
+	}
+
+	@Override
+	public IMacroPlaybackContext getMacroPlaybackContext() {
+		return getMacroManager().getMacroPlaybackContext();
+	}
+
+	/**
+	 * Note that this is only available in this implementation, not on the public
+	 * API (EMacroService). Needed for testing.
+	 *
+	 * @return the currently registered listeners.
+	 */
+	public IMacroStateListener[] getMacroStateListeners() {
+		return getMacroManager().getMacroStateListeners();
+	}
+
+	/**
+	 * A map which maps accepted command ids when recording a macro to whether they
+	 * should be recorded as a macro instruction to be played back later on.
+	 */
+	private Map<String, Boolean> fCustomizedCommandIds;
+
+	/**
+	 * @return a set with the commands that are accepted when macro recording.
+	 */
+	private Map<String, Boolean> getInternalmacroCommandCustomization() {
+		if (fCustomizedCommandIds == null) {
+			fCustomizedCommandIds = new HashMap<>();
+			if (fEclipseContext != null) {
+				IExtensionRegistry registry = fEclipseContext.get(IExtensionRegistry.class);
+				if (registry != null) {
+					for (IConfigurationElement ce : registry
+							.getConfigurationElementsFor("org.eclipse.e4.core.macros.macroCommandCustomization")) { //$NON-NLS-1$
+						if ("customizedCommand".equals(ce.getName()) && ce.getAttribute("id") != null //$NON-NLS-1$ //$NON-NLS-2$
+								&& ce.getAttribute("recordMacroInstruction") != null) { //$NON-NLS-1$
+							Boolean recordMacroInstruction = Boolean
+									.parseBoolean(ce.getAttribute("recordMacroInstruction")) //$NON-NLS-1$
+											? Boolean.TRUE
+											: Boolean.FALSE;
+							fCustomizedCommandIds.put(ce.getAttribute("id"), recordMacroInstruction); //$NON-NLS-1$
+						}
+					}
+				}
+			}
+		}
+		return fCustomizedCommandIds;
+	}
+
+	@Override
+	public boolean getRecordCommandInMacro(String commandId) {
+		Map<String, Boolean> macromacroCommandCustomization = getInternalmacroCommandCustomization();
+		Boolean recordMacro = macromacroCommandCustomization.get(commandId);
+		if (recordMacro == null) {
+			return true;
+		}
+		return recordMacro;
+	}
+
+	@Override
+	public void setRecordCommandInMacro(String commandId, boolean recordMacroInstruction) {
+		getInternalmacroCommandCustomization().put(commandId, recordMacroInstruction);
+	}
+
+	@Override
+	public void addMacroInstructionsListener(IMacroInstructionsListener macroInstructionsListener) {
+		getMacroManager().addMacroInstructionsListener(macroInstructionsListener);
+	}
+
+	@Override
+	public void removeMacroInstructionsListener(IMacroInstructionsListener macroInstructionsListener) {
+		getMacroManager().removeMacroInstructionsListener(macroInstructionsListener);
+	}
+
+	@Override
+	public int getLenOfMacroBeingRecorded() {
+		return getMacroManager().getLenOfMacroBeingRecorded();
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/Messages.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/Messages.java
new file mode 100644
index 0000000..5734d1d
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/Messages.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @since 0.1.0
+ */
+public class Messages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.e4.core.macros.internal.messages"; //$NON-NLS-1$
+	public static String SavedJSMacro_MacrosEvalError;
+	static {
+		// initialize resource bundle
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+
+	private Messages() {
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/SavedJSMacro.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/SavedJSMacro.java
new file mode 100644
index 0000000..84403b4
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/SavedJSMacro.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.core.macros.internal;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.SimpleScriptContext;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+import org.eclipse.e4.core.macros.MacroPlaybackException;
+
+/**
+ * Actually loads a macro from a JS file to be played back. Works with the
+ * contents saved from {@link ComposableMacro#toJSBytes()}.
+ * <p>
+ * Currently the saved macro is a JavaScript file to be played back again with a
+ * "runMacro" function which may have multiple "runMacroInstruction" calls to
+ * run a macro instruction which was previously persisted with
+ * {@link IMacroInstruction#toMap()}.
+ * </p>
+ */
+public class SavedJSMacro implements IMacro {
+
+	/**
+	 * The file which contains the contents of the macro.
+	 */
+	private final File fFile;
+
+	/**
+	 * Creates a macro which is backed up by the contents of a javascript file.
+	 *
+	 * @param file
+	 *            the file with the contents of the macro.
+	 */
+	public SavedJSMacro(File file) {
+		this.fFile = file;
+	}
+
+	/**
+	 * Static method to be called when playing back a macro to run a macro
+	 * instruction..
+	 *
+	 * @param macroPlaybackContext
+	 *            the context for the macro playback.
+	 * @param macroInstructionId
+	 *            the id of the macro instruction to be executed.
+	 * @param macroInstructionParameters
+	 *            the parameters to create the macro instruction.
+	 * @throws Exception
+	 *             if something happened when creating the macro instruction or
+	 *             actually executing it.
+	 */
+	@SuppressWarnings({ "rawtypes" })
+	public static void runMacroInstruction(IMacroPlaybackContext macroPlaybackContext, String macroInstructionId,
+			Object macroInstructionParameters) throws Exception {
+		Map<String, String> stringMap = new HashMap<>();
+		Map m = (Map) macroInstructionParameters;
+		Set<Map.Entry> entrySet = m.entrySet();
+		for (Map.Entry entry : entrySet) {
+			Object key = entry.getKey();
+			Object value = entry.getValue();
+			stringMap.put(key.toString(), value.toString());
+		}
+		IMacroInstruction macroInstruction = macroPlaybackContext.createMacroInstruction(macroInstructionId, stringMap);
+		macroInstruction.execute(macroPlaybackContext);
+	}
+
+	@Override
+	public void playback(IMacroPlaybackContext macroPlaybackContext) throws MacroPlaybackException {
+		ScriptEngineManager manager = new ScriptEngineManager();
+		ScriptEngine engine = manager.getEngineByName("nashorn"); //$NON-NLS-1$
+		SimpleScriptContext context = new SimpleScriptContext();
+		context.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
+		Bindings engineScope = context.getBindings(ScriptContext.ENGINE_SCOPE);
+
+		// Setup the default context.
+		engineScope.put("__macroPlaybackContext", macroPlaybackContext); //$NON-NLS-1$
+
+		try {
+			engine.eval("" + //$NON-NLS-1$
+					"__macro = Java.type('org.eclipse.e4.core.macros.internal.SavedJSMacro');\n" //$NON-NLS-1$
+					+ "function runMacroInstruction(macroMacroInstructionId, macroInstructionParameters){" //$NON-NLS-1$
+					+ "    __macro.runMacroInstruction(__macroPlaybackContext, macroMacroInstructionId, macroInstructionParameters);" //$NON-NLS-1$
+					+ "}" //$NON-NLS-1$
+					+ "", context); //$NON-NLS-1$
+
+			// The contents to execute are actually built at:
+			// org.eclipse.e4.core.macros.internal.ComposableMacro.toJSBytes()
+			try (BufferedReader reader = new BufferedReader(
+					new InputStreamReader(new FileInputStream(fFile), "UTF-8"))) { //$NON-NLS-1$
+				// Let any exception running it go through.
+				// It should define a runMacro() method which we can run later on.
+				engine.eval(reader, context);
+
+				// Actually run the macro now.
+				engine.eval("runMacro();", context); //$NON-NLS-1$
+			}
+		} catch (Exception e) {
+			throw new MacroPlaybackException(
+					MessageFormat.format(Messages.SavedJSMacro_MacrosEvalError, e.getMessage()), e);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/messages.properties b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/messages.properties
new file mode 100644
index 0000000..3677ab5
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/internal/messages.properties
@@ -0,0 +1 @@
+SavedJSMacro_MacrosEvalError=Error when evaluating macro:\n\n{0}
diff --git a/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/package-info.java b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/package-info.java
new file mode 100644
index 0000000..0a71baf
--- /dev/null
+++ b/bundles/org.eclipse.e4.core.macros/src/org/eclipse/e4/core/macros/package-info.java
@@ -0,0 +1,257 @@
+package org.eclipse.e4.core.macros;
+
+/**
+ * Package providing abstractions for dealing with macro record/playback.
+ *
+ * <p>
+ * The basic idea in this implementation is that the macro plugin is a thin
+ * layer used to record macro instructions and then play it back. The actual
+ * work is done on other plugins, which should be macro-aware.
+ * </p>
+ *
+ * <p>
+ * The macro recording doesn't only map to text editions. Anything done in the
+ * IDE could be recorded in a macro to be played back later on. For instance, it
+ * may be possible to record and playback changes to preferences, importing some
+ * git repository, finding text, etc. Later on, when playing it back, it should
+ * be even possible to ask if the user wants to edit some of the values which
+ * were saved during record.
+ * </p>
+ *
+ * <p>
+ * Still, note that while that support may be possible in the future, currently
+ * the implementation only targets the text editor and its operations.
+ * </p>
+ *
+ *
+ * <hr/>
+ * <h3>Rationale</h3>
+ *
+ * <p>
+ * The basic idea is that editors listen or detect when macro record mode is
+ * active and upon entering macro mode, they make sure actions are properly
+ * tracked so that they can be played back accordingly.
+ * </p>
+ *
+ * <p>
+ * -- note that it's important that things are not the other way around: the
+ * macro plugin is a thin layer to start/stop macro recording and provide the
+ * basic abstractions and management of macros, it's up to the clients to be
+ * aware that they are in macro record mode and act accordingly, issuing
+ * commands to be recorded and later played back.
+ * </p>
+ *
+ * <hr/>
+ * <h3>Related APIs</h3>
+ *
+ * <p>
+ * Note that currently the only APIs available are exposed as interfaces:
+ * </p>
+ *
+ * <p>
+ * {@link org.eclipse.e4.core.macros.EMacroService} can be used to:
+ *
+ * <ul>
+ * <li>query the current record/playback state;</li>
+ * <li>listen changes in the current record/playback state;</li>
+ * <li>add macro instructions when in record mode;</li>
+ * <li>start and stop the macro record;</li>
+ * <li>playback a previous macro;</li>
+ * <li>get commands customization from the
+ * org.eclipse.e4.core.macros.macroCommandCustomization extension point;</li>
+ * <li>programatically customize commands.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * {@link org.eclipse.e4.core.macros.IMacroInstruction}: A macro is actually
+ * composed of multiple macro instructions. Each time the user does some action
+ * which should be recorded, a macro instruction should be created and added to
+ * the EMacroService. (note that currently the basic macro abstraction -- IMacro
+ * -- is only internally available, but the idea is that a macro is composed of
+ * multiple macro instructions).
+ * </p>
+ *
+ * <p>
+ * {@link org.eclipse.e4.core.macros.IMacroInstructionFactory}: provides a way
+ * to recreate an {@link org.eclipse.e4.core.macros.IMacroInstruction} from its
+ * id and persisted contents.
+ * </p>
+ *
+ * <p>
+ * {@link org.eclipse.e4.core.macros.IMacroPlaybackContext}: received by a macro
+ * instruction when it's being played back.
+ * </p>
+ *
+ * <p>
+ * {@link org.eclipse.e4.core.macros.IMacroStateListener}: listener to hear
+ * changes in the record/playback state (added to the EMacroService).
+ * </p>
+ *
+ *
+ * <hr/>
+ * <h3>Actually dealing with macro record/playback</h3>
+ *
+ * <p>
+ * Clients should:
+ * <ul>
+ * <li>listen when a macro record will start to set up their internal state and
+ * add if needed, add listeners which records actions/events when they happen so
+ * that they're properly added the macro being recorded;</li>
+ * <li>listen when a macro record session finished to remove any used listener
+ * and restore previous state;</li>
+ * <li>listen when a macro playback starts/finishes and set up/reset the
+ * internal state properly</li>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * -- Note: it's possible for the user to start a record mode and playback a
+ * previous macro in such a mode (although the opposite is not true).
+ * </p>
+ *
+ * <h4>Scenario 1:</h4>
+ *
+ * <p>
+ * Setting up state when entering macro record/playback mode:
+ * </p>
+ *
+ * <p>
+ * This gives an example where some state must be set for both macro and record
+ * mode (i.e.: disabling code-completion) and in the record mode it also has to
+ * record keypresses to be played back later on.
+ * </p>
+ *
+ * <pre>
+ * public class MyMacroAwareEditor implements IMacroStateListener {
+ *
+ * 	public void init(final IEditorSite site) {
+ * 		fMacroService = site.getService(EMacroService.class);
+ * 		if (fMacroService != null) {
+ * 			// Start listening to the service so that events are properly
+ * 			// recorded.
+ * 			fMacroService.addmacroStateListener(this);
+ * 			if (fMacroService.isRecording() || fMacroService.isPlayingBack()) {
+ * 				this.macroStateChanged(fMacroService);
+ * 			}
+ * 		}
+ * 	}
+ *
+ * 	public final void macroStateChanged(EMacroService macroService) {
+ * 		// Note: state must be set with care because record/playback may
+ * 		// happen simultaneously.
+ * 		if (macroService.isRecording() || macroService.isPlayingBack()) {
+ * 			// Code completion disabled in both, record and playback.
+ * 			this.disableCodeCompletion();
+ * 		} else {
+ * 			this.enableCodeCompletion();
+ * 		}
+ *
+ * 		if (macroService.isRecording()) {
+ * 			this.startRecordingKeyEvents(macroService);
+ * 		} else {
+ * 			this.endRecordingKeyEvents();
+ * 		}
+ * 	}
+ *
+ * 	protected void startRecordingKeyEvents(final EMacroService macroService) {
+ * 		// Note: if simultaneously recording/playing back, this may be called
+ * 		// multiple times.
+ * 		if (this.fKeyEventListener == null) {
+ * 			this.fKeyEventListener = new Listener() {
+ * 				&#64;Override
+ * 				public void handleEvent(Event event) {
+ * 					if (event.type == SWT.KeyDown && fMacroService.isRecording()) {
+ * 						fMacroService.addMacroInstruction(new KeyDownMacroInstruction(event));
+ * 					}
+ * 				}
+ * 			};
+ * 			this.addListener(SWT.KeyDown, this.fKeyEventListener);
+ * 		}
+ * 	}
+ *
+ * 	protected void endRecordingKeyEvents() {
+ * 		if (this.fKeyEventListener != null) {
+ * 			this.removeListener(SWT.KeyDown, this.fKeyEventListener);
+ * 			this.fKeyEventListener = null;
+ * 		}
+ * 	}
+ *
+ * }
+ * </pre>
+ *
+ * <p>
+ * An actual implementation using this strategy is:
+ * </p>
+ *
+ * <p>
+ * {@link org.eclipse.ui.workbench.texteditor.macros.internal.MacroStyledTextInstaller}
+ * </p>
+ *
+ *
+ * <h4>Scenario 2</h4>
+ *
+ * <p>
+ * Just issuing macro instructions when no setup is needed:
+ * </p>
+ *
+ * <pre>
+ * public class MyMacroAwareClass {
+ *
+ *		&#64;Inject
+ *     	EMacroService fMacroService;
+ *
+ *		public void run(String myCommand) {
+ *			...
+ *			// Actually run command
+ *			if(fMacroService.isRecording()){
+ *				fMacroService.addMacroInstruction(new MyRunCommandMacroInstruction(myCommand));
+ *			}
+ *		}
+ * }
+ *
+ * </pre>
+ *
+ * <p>
+ * An actual implementation using this strategy is:
+ * {@link org.eclipse.e4.ui.macros.internal.keybindings.CommandManagerExecutionListener}
+ * </p>
+ *
+ * <p>
+ * -- Note: commands registered through the eclipse commands extensions will be
+ * already recorded by default if they aren't registered in the
+ * org.eclipse.e4.core.macros.macroCommandCustomization extension point and
+ * their activation will already be recorded for proper playback by default (so,
+ * clients only actually need to customize actions which currently aren't
+ * implemented as eclipse actions or to disable recording of some eclipse
+ * action).
+ * </p>
+ *
+ * <hr/>
+ * <h3>Macro playback</h3>
+ *
+ * <p>
+ * After a command is actually added to the EMacroService and a record session
+ * is finished, all the recorded IMacroInstructions will be saved to disk using
+ * the contents of their
+ * {@link org.eclipse.e4.core.macros.IMacroInstruction#toMap()} method to enable
+ * playing it back later on.
+ * </p>
+ *
+ * <p>
+ * Afterward, when it's time to play a macro instruction back, the contents of
+ * the map are gotten from disk and will be recreated through factories
+ * registered in the org.eclipse.e4.core.macros.macroInstructionsFactory
+ * extension point (so it's important to note that if a custom macro instruction
+ * is created, a factory to recreate it must be registered).
+ * </p>
+ *
+ * <p>
+ * On playback, the macro instruction must perform the same action which was
+ * recorded (so, for instance, if a command to delete the current line of the
+ * editor was issued, on playback the current line of the current editor must be
+ * deleted).
+ * </p>
+ *
+ *
+ **/
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.macros.jdt/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.ui.macros.jdt/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index f42de36..0000000
--- a/bundles/org.eclipse.e4.ui.macros.jdt/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,7 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
-org.eclipse.jdt.core.compiler.compliance=1.7
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.7
diff --git a/bundles/org.eclipse.e4.ui.macros.jdt/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.macros.jdt/META-INF/MANIFEST.MF
deleted file mode 100644
index 697afe5..0000000
--- a/bundles/org.eclipse.e4.ui.macros.jdt/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,9 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: E4 Macros - JDT Support
-Bundle-SymbolicName: org.eclipse.e4.ui.macros.jdt;singleton:=true
-Bundle-Version: 0.1.0.qualifier
-Bundle-Vendor: Eclipse.org
-Fragment-Host: org.eclipse.jdt.ui
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Require-Bundle: org.eclipse.e4.ui.macros
diff --git a/bundles/org.eclipse.e4.ui.macros.jdt/fragment.xml b/bundles/org.eclipse.e4.ui.macros.jdt/fragment.xml
deleted file mode 100644
index ebc2bae..0000000
--- a/bundles/org.eclipse.e4.ui.macros.jdt/fragment.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.4"?>
-<fragment>
-   <extension
-         point="org.eclipse.e4.ui.macros.hooks">
-      <hook
-            class="org.eclipse.e4.ui.macros.jdt.JdtContentAssistMacroHook" />
-   </extension>
-
-   <extension
-         point="org.eclipse.e4.ui.macros.commands">
-      <whitelist id="org.eclipse.jdt.ui.edit.text.java.open.editor" />		<!-- F3 -->
-      
-      <blacklist id="org.eclipse.jdt.ui.edit.text.java.open.hierarchy" />	<!-- Ctrl-T -->
-      <blacklist id="org.eclipse.jdt.ui.edit.text.java.show.outline" />		<!-- Ctrl-O -->
-      
-      <!-- Quick Fix -->
-      <blacklist id="org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals" /> 
-      <blacklist id="org.eclipse.jdt.ui.edit.text.java.open.type.hierarchy" />	<!-- F4 -->
-      <blacklist id="org.eclipse.jdt.ui.navigate.open.type" />				<!-- Ctrl-Shift-O -->
-   </extension>
-</fragment>
diff --git a/bundles/org.eclipse.e4.ui.macros.jdt/pom.xml b/bundles/org.eclipse.e4.ui.macros.jdt/pom.xml
deleted file mode 100644
index dd9b241..0000000
--- a/bundles/org.eclipse.e4.ui.macros.jdt/pom.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
--->
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.eclipse.e4.ui</groupId>
-    <artifactId>e4-ui-aggregator</artifactId>
-    <version>0.17.0-SNAPSHOT</version>
-    <relativePath>../../</relativePath>
-  </parent>
-
-  <artifactId>org.eclipse.e4.ui.macros.jdt</artifactId>
-  <version>0.1.0-SNAPSHOT</version>
-  <packaging>eclipse-plugin</packaging>
-</project>
diff --git a/bundles/org.eclipse.e4.ui.macros.jdt/src/org/eclipse/e4/ui/macros/jdt/JdtContentAssistMacroHook.java b/bundles/org.eclipse.e4.ui.macros.jdt/src/org/eclipse/e4/ui/macros/jdt/JdtContentAssistMacroHook.java
deleted file mode 100644
index 198c6e7..0000000
--- a/bundles/org.eclipse.e4.ui.macros.jdt/src/org/eclipse/e4/ui/macros/jdt/JdtContentAssistMacroHook.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.macros.jdt;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.e4.ui.macros.IMacroHook;
-import org.eclipse.jdt.internal.ui.JavaPlugin;
-import org.eclipse.jdt.ui.PreferenceConstants;
-import org.eclipse.jface.preference.IPreferenceStore;
-
-/**
- * Disable content assist for macro recording and playback as it introduces
- * non-determinism: we can't be certain of the ordering of the items shown is
- * stable.
- */
-public class JdtContentAssistMacroHook implements IMacroHook {
-	private boolean autoActivates;
-
-	@Override
-	public IStatus start(Mode mode) {
-		IPreferenceStore preferenceStore = JavaPlugin.getDefault().getPreferenceStore();
-		autoActivates = preferenceStore.getBoolean(PreferenceConstants.CODEASSIST_AUTOACTIVATION);
-		preferenceStore.setValue(PreferenceConstants.CODEASSIST_AUTOACTIVATION, false);
-		return Status.OK_STATUS;
-	}
-
-	@Override
-	public void stop(Mode mode) {
-		IPreferenceStore preferenceStore = JavaPlugin.getDefault().getPreferenceStore();
-		preferenceStore.setValue(PreferenceConstants.CODEASSIST_AUTOACTIVATION, autoActivates);
-	}
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/.gitignore b/bundles/org.eclipse.e4.ui.macros/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/bundles/org.eclipse.e4.ui.macros/.project b/bundles/org.eclipse.e4.ui.macros/.project
index 1bc56d2..fb2d5bb 100644
--- a/bundles/org.eclipse.e4.ui.macros/.project
+++ b/bundles/org.eclipse.e4.ui.macros/.project
@@ -20,9 +20,20 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ds.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.pde.PluginNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
 	</natures>
 </projectDescription>
diff --git a/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..5a0ad22
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.jdt.core.prefs
index f42de36..e2f298f 100644
--- a/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.jdt.core.prefs
@@ -1,7 +1,424 @@
 eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..b058cde
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,125 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment"/><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
diff --git a/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..a09ec9c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,97 @@
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Warning
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2ce5047
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=1
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=2
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=1
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.e4.ui.macros/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.macros/META-INF/MANIFEST.MF
index 30e4f3b..0180cbe 100644
--- a/bundles/org.eclipse.e4.ui.macros/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.e4.ui.macros/META-INF/MANIFEST.MF
@@ -3,23 +3,34 @@
 Bundle-Name: E4 Macro Recording and Playback
 Bundle-SymbolicName: org.eclipse.e4.ui.macros;singleton:=true
 Bundle-Version: 0.1.0.qualifier
+Bundle-Activator: org.eclipse.e4.ui.macros.Activator
 Bundle-Vendor: Eclipse.org
-Require-Bundle: org.eclipse.e4.ui.bindings;bundle-version="0.10.200",
- org.eclipse.e4.ui.model.workbench;bundle-version="1.1.100",
+Export-Package: org.eclipse.e4.ui.macros,
+ org.eclipse.e4.ui.macros.internal;x-friends:="org.eclipse.ui.workbench.texteditor.macros",
+ org.eclipse.e4.ui.macros.internal.actions;x-friends:="org.eclipse.e4.ui.bindings.tests",
+ org.eclipse.e4.ui.macros.internal.keybindings;x-friends:="org.eclipse.e4.ui.bindings.tests"
+Require-Bundle: org.eclipse.e4.ui.model.workbench;bundle-version="1.1",
  org.eclipse.e4.ui.workbench.renderers.swt,
  org.eclipse.e4.ui.workbench,
  org.eclipse.ui.workbench;resolution:=optional,
- org.eclipse.jface;bundle-version="3.11.0",
- org.eclipse.swt;bundle-version="3.104.0",
- org.eclipse.osgi
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Bundle-ActivationPolicy: lazy
+ org.eclipse.jface;bundle-version="3.11",
+ org.eclipse.swt;bundle-version="3.104",
+ org.eclipse.osgi,
+ org.eclipse.ui;bundle-version="3.108",
+ org.eclipse.core.commands,
+ org.eclipse.e4.core.contexts;bundle-version="1.0",
+ org.eclipse.e4.core.di;bundle-version="1.1",
+ org.eclipse.e4.core.macros;bundle-version="0.1",
+ org.eclipse.ui.console,
+ org.eclipse.e4.ui.bindings;bundle-version="0.11",
+ org.eclipse.e4.core.services;bundle-version="2.0",
+ org.eclipse.e4.core.commands
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Import-Package: javax.inject,
- org.eclipse.core.runtime;version="3.5.0",
+ org.eclipse.core.runtime;version="3.5",
  org.eclipse.e4.core.commands,
  org.eclipse.e4.core.contexts,
  org.eclipse.e4.core.di,
  org.eclipse.e4.core.di.annotations,
- org.osgi.framework;version="1.8.0"
-Export-Package: org.eclipse.e4.ui.internal.macros,
- org.eclipse.e4.ui.macros
+ org.osgi.framework;version="1.8"
+Bundle-ActivationPolicy: lazy
diff --git a/bundles/org.eclipse.e4.ui.macros/OSGI-INF/l10n/bundle.properties b/bundles/org.eclipse.e4.ui.macros/OSGI-INF/l10n/bundle.properties
new file mode 100644
index 0000000..9603a46
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/OSGI-INF/l10n/bundle.properties
@@ -0,0 +1,5 @@
+#Properties file for org.eclipse.e4.ui.macros
+category.macros.name = Macros
+command.macro_playback.name = Playback Last Macro
+toolbar.macro.label = Macro
+command.toggle_macro_record.label = Toggle Macro Record
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.macros/build.properties b/bundles/org.eclipse.e4.ui.macros/build.properties
index 5dc29cb..163cdac 100644
--- a/bundles/org.eclipse.e4.ui.macros/build.properties
+++ b/bundles/org.eclipse.e4.ui.macros/build.properties
@@ -2,6 +2,5 @@
 bin.includes = META-INF/,\
                .,\
                plugin.xml,\
-               fragment.e4xmi
+               OSGI-INF/
 source.. = src/
-src.includes = schema/
diff --git a/bundles/org.eclipse.e4.ui.macros/icons/full/dtool16/macro_playback.png b/bundles/org.eclipse.e4.ui.macros/icons/full/dtool16/macro_playback.png
new file mode 100644
index 0000000..a5ca398
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/icons/full/dtool16/macro_playback.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.macros/icons/full/dtool16/macro_record.png b/bundles/org.eclipse.e4.ui.macros/icons/full/dtool16/macro_record.png
new file mode 100644
index 0000000..2b203d5
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/icons/full/dtool16/macro_record.png
Binary files differ
diff --git a/bundles/org.eclipse.e4.ui.macros/plugin.xml b/bundles/org.eclipse.e4.ui.macros/plugin.xml
index 89e82db..907a6cb 100644
--- a/bundles/org.eclipse.e4.ui.macros/plugin.xml
+++ b/bundles/org.eclipse.e4.ui.macros/plugin.xml
@@ -1,121 +1,87 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.4"?>
 <plugin>
-   <extension-point id="hooks" name="Macro Recording and Playback Hooks" schema="schema/hooks.exsd"/>
-   <extension-point id="commands" name="Describe commands that have been vetted or disallowed for macros" schema="schema/commands.exsd"/>
 
-   <extension
-         id="macroinstaller"
-         point="org.eclipse.e4.workbench.model">
-      <processor
-            apply="always"
-            beforefragment="true"
-            class="org.eclipse.e4.ui.internal.macros.MacroRecorderInstaller">
-      </processor>
+
+   <extension point="org.eclipse.e4.core.macros.macroCommandCustomization">
+
+      <!-- We should be able to stop the macro recording after the recording started. -->
+      <customizedCommand id="org.eclipse.e4.ui.macros.toggleRecordMacro" recordMacroInstruction="false"/>
+
+      <!-- Playback is Ok during recording, but only its side-effects are recorded, not the command itself. -->
+      <customizedCommand id="org.eclipse.e4.ui.macros.macroPlayback" recordMacroInstruction="false"/>
+
+      <!-- Disable recording of actions not related to the editor (which the user may choose to do
+      but shouldn't interfere with the macro recording). -->
+      <customizedCommand id="org.eclipse.ui.window.nextEditor" recordMacroInstruction="false"/>
+      <customizedCommand id="org.eclipse.ui.window.nextView" recordMacroInstruction="false"/>
+      <customizedCommand id="org.eclipse.ui.window.nextPerspective" recordMacroInstruction="false"/>
+      <customizedCommand id="org.eclipse.ui.navigate.showInQuickMenu" recordMacroInstruction="false"/>
+      <customizedCommand id="org.eclipse.ui.window.showKeyAssist" recordMacroInstruction="false"/>
+      <customizedCommand id="org.eclipse.ui.window.openEditorDropDown" recordMacroInstruction="false"/>
+      <customizedCommand id="org.eclipse.ui.window.quickAccess" recordMacroInstruction="false"/>
+      <customizedCommand id="org.eclipse.ui.edit.findReplace" recordMacroInstruction="false"/>
    </extension>
 
    <extension
-         point="org.eclipse.e4.ui.macros.commands">
-      <whitelist id="org.eclipse.e4.ui.macros.toggleRecording" />
-            
-      <whitelist id="org.eclipse.ui.edit.cut" />
-      <whitelist id="org.eclipse.ui.edit.copy" />
-      <whitelist id="org.eclipse.ui.edit.paste" />
-      <whitelist id="org.eclipse.ui.edit.delete" />
-      <whitelist id="org.eclipse.ui.edit.undo" />
-      <whitelist id="org.eclipse.ui.edit.redo" />
-      <whitelist id="org.eclipse.ui.edit.text.join.lines" />
-      <whitelist id="org.eclipse.ui.edit.text.delete.line" />
-      <whitelist id="org.eclipse.ui.edit.text.removeTrailingWhitespace" />
-      <whitelist id="org.eclipse.ui.edit.text.delete.line.to.beginning" />
-      <whitelist id="org.eclipse.ui.edit.text.delete.line.to.end" />
-      <whitelist id="org.eclipse.ui.edit.text.cut.line" />
-      <whitelist id="org.eclipse.ui.edit.text.cut.line.to.beginning" />
-      <whitelist id="org.eclipse.ui.edit.text.cut.line.to.end" />
-      <whitelist id="org.eclipse.ui.edit.findIncremental" />
-      <whitelist id="org.eclipse.ui.edit.findIncrementalReverse" />
-      <whitelist id="org.eclipse.ui.edit.revertToSaved" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.lineUp" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.lineDown" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.lineStart" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.lineEnd" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.columnPrevious" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.columnNext" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.pageUp" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.pageDown" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.wordPrevious" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.wordNext" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.textStart" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.textEnd" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.windowStart" />
-      <whitelist id="org.eclipse.ui.edit.text.goto.windowEnd" />
-      <whitelist id="org.eclipse.ui.edit.text.scroll.lineUp" />
-      <whitelist id="org.eclipse.ui.edit.text.scroll.lineDown" />
-      <whitelist id="org.eclipse.ui.edit.text.select.lineUp" />
-      <whitelist id="org.eclipse.ui.edit.text.select.lineDown" />
-      <whitelist id="org.eclipse.ui.edit.text.select.lineStart" />
-      <whitelist id="org.eclipse.ui.edit.text.select.lineEnd" />
-      <whitelist id="org.eclipse.ui.edit.text.select.columnPrevious" />
-      <whitelist id="org.eclipse.ui.edit.text.select.columnNext" />
-      <whitelist id="org.eclipse.ui.edit.text.select.pageUp" />
-      <whitelist id="org.eclipse.ui.edit.text.select.pageDown" />
-      <whitelist id="org.eclipse.ui.edit.text.select.wordPrevious" />
-      <whitelist id="org.eclipse.ui.edit.text.select.wordNext" />
-      <whitelist id="org.eclipse.ui.edit.text.select.textStart" />
-      <whitelist id="org.eclipse.ui.edit.text.select.textEnd" />
-      <whitelist id="org.eclipse.ui.edit.text.select.windowStart" />
-      <whitelist id="org.eclipse.ui.edit.text.select.windowEnd" />
-      <whitelist id="org.eclipse.ui.edit.text.deletePrevious" />
-      <whitelist id="org.eclipse.ui.edit.text.deleteNext" />
-      <whitelist id="org.eclipse.ui.edit.text.deletePreviousWord" />
-      <whitelist id="org.eclipse.ui.edit.text.deleteNextWord" />
-      <whitelist id="org.eclipse.ui.edit.text.shiftRight" />
-      <whitelist id="org.eclipse.ui.edit.text.shiftLeft" />
-      <whitelist id="org.eclipse.ui.edit.text.toggleOverwrite" />
-      <whitelist id="org.eclipse.ui.edit.text.smartEnter" />
-      <whitelist id="org.eclipse.ui.edit.text.smartEnterInverse" />
-      <whitelist id="org.eclipse.ui.edit.text.moveLineUp" />
-      <whitelist id="org.eclipse.ui.edit.text.moveLineDown" />
-      <whitelist id="org.eclipse.ui.edit.text.copyLineUp" />
-      <whitelist id="org.eclipse.ui.edit.text.copyLineDown" />
-      <whitelist id="org.eclipse.ui.edit.text.upperCase" />
-      <whitelist id="org.eclipse.ui.edit.text.lowerCase" />
-      <whitelist id="org.eclipse.ui.edit.text.toggleBlockSelectionMode" />
-      <whitelist id="org.eclipse.ui.edit.text.toggleInsertMode" />
-      <whitelist id="org.eclipse.ui.edit.text.recenter" />
-      <whitelist id="org.eclipse.ui.edit.text.open.hyperlink" />
-      
-      <whitelist id="org.eclipse.ui.window.showViewMenu" />
+         point="org.eclipse.e4.core.macros.macroInstructionsFactory">
+      <macroInstructionsFactory
+            class="org.eclipse.e4.ui.macros.internal.keybindings.MacroInstructionForParameterizedCommandFactory"
+            macroInstructionId="Command">
+      </macroInstructionsFactory>
    </extension>
-      
-   <extension
-         point="org.eclipse.e4.ui.macros.commands">
-      <!-- can't play a macro during recording -->
-      <blacklist id="org.eclipse.e4.ui.macros.playRecording" />
 
-      <!-- non deterministic order -->
-      <blacklist id="org.eclipse.ui.edit.text.contentAssist.proposals" />
-      
-      <!-- Can tap F6 repeatedly to alternate, which we can't intercept -->
-      <blacklist id="org.eclipse.ui.window.nextEditor" />
-      <blacklist id="org.eclipse.ui.window.previousEditor" />
-      <blacklist id="org.eclipse.ui.window.nextView" />
-      <blacklist id="org.eclipse.ui.window.previousView" />
-      <blacklist id="org.eclipse.ui.window.nextPerspective" />
-      <blacklist id="org.eclipse.ui.window.previousPerspective" />
-      
-      <blacklist id="org.eclipse.ui.file.openWorkspace" />
-      <blacklist id="org.eclipse.ui.file.newQuickMenu" />
-      <blacklist id="org.eclipse.ui.edit.text.openLocalFile" />
-      <blacklist id="org.eclipse.ui.navigate.showInQuickMenu" />
-      <blacklist id="org.eclipse.ui.navigate.goToResource" />
-      <blacklist id="org.eclipse.ui.navigate.openResource" />
-      <blacklist id="org.eclipse.ui.project.openProject" />
-      <blacklist id="org.eclipse.ui.project.closeProject" />
-      <blacklist id="org.eclipse.ui.project.closeUnrelatedProjects" />
-      <blacklist id="org.eclipse.ui.project.properties" />
-      <blacklist id="org.eclipse.ui.edit.addTask" />
-      <blacklist id="org.eclipse.ui.navigate.selectWorkingSets" />
+   <extension
+         point="org.eclipse.e4.core.macros.macroStateListeners">
+      <macroStateListener
+            class="org.eclipse.e4.ui.macros.internal.keybindings.CommandManagerExecutionListenerInstaller">
+      </macroStateListener>
+      <macroStateListener
+            class="org.eclipse.e4.ui.macros.internal.actions.KeepMacroUIUpdated">
+      </macroStateListener>
+   </extension>
+
+   <extension
+         point="org.eclipse.ui.commands">
+      <category
+            id="org.eclipse.e4.ui.macros.category"
+            name="%category.macros.name">
+      </category>
+      <command
+            categoryId="org.eclipse.e4.ui.macros.category"
+            defaultHandler="org.eclipse.e4.ui.macros.internal.actions.ToggleMacroRecordAction"
+            id="org.eclipse.e4.ui.macros.toggleRecordMacro"
+            name="%command.toggle_macro_record.label">
+      </command>
+      <command
+            categoryId="org.eclipse.e4.ui.macros.category"
+            defaultHandler="org.eclipse.e4.ui.macros.internal.actions.MacroPlaybackAction"
+            id="org.eclipse.e4.ui.macros.macroPlayback"
+            name="%command.macro_playback.name">
+      </command>
+   </extension>
+
+   <extension
+         point="org.eclipse.ui.menus">
+      <menuContribution
+            allPopups="false"
+            locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
+         <toolbar
+               id="org.eclipse.e4.ui.macros.toolbar"
+               label="%toolbar.macro.label">
+            <command
+                  commandId="org.eclipse.e4.ui.macros.toggleRecordMacro"
+                  icon="icons/full/dtool16/macro_record.png"
+                  label="%command.toggle_macro_record.label"
+                  style="toggle">
+            </command>
+            <command
+                  commandId="org.eclipse.e4.ui.macros.macroPlayback"
+                  icon="icons/full/dtool16/macro_playback.png"
+                  label="%command.macro_playback.name"
+                  style="push">
+            </command>
+         </toolbar>
+      </menuContribution>
    </extension>
 
 </plugin>
diff --git a/bundles/org.eclipse.e4.ui.macros/pom.xml b/bundles/org.eclipse.e4.ui.macros/pom.xml
index 32d5a80..93c827a 100644
--- a/bundles/org.eclipse.e4.ui.macros/pom.xml
+++ b/bundles/org.eclipse.e4.ui.macros/pom.xml
@@ -1,16 +1,15 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- 
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
+<!--
+  Copyright (c) 2017 Fabio Zadrozny and others.
+  All rights reserved. This program and the accompanying materials
+  are made available under the terms of the Eclipse Distribution License v1.0
+  which accompanies this distribution, and is available at
+  http://www.eclipse.org/org/documents/edl-v10.php
+
+  Contributors:
+     Fabio Zadrozny - initial implementation
 -->
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.eclipse.e4.ui</groupId>
diff --git a/bundles/org.eclipse.e4.ui.macros/schema/commands.exsd b/bundles/org.eclipse.e4.ui.macros/schema/commands.exsd
deleted file mode 100644
index 4f8d4b3..0000000
--- a/bundles/org.eclipse.e4.ui.macros/schema/commands.exsd
+++ /dev/null
@@ -1,128 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- Schema file written by PDE -->
-<schema targetNamespace="org.eclipse.e4.ui.macros" xmlns="http://www.w3.org/2001/XMLSchema">
-<annotation>
-      <appinfo>
-         <meta.schema plugin="org.eclipse.e4.ui.macros" id="commands" name="Describe commands that have been vetted or disallowed for macros"/>
-      </appinfo>
-      <documentation>
-         [Enter description of this extension point.]
-      </documentation>
-   </annotation>
-
-   <element name="extension">
-      <annotation>
-         <appinfo>
-            <meta.element />
-         </appinfo>
-      </annotation>
-      <complexType>
-         <choice minOccurs="1" maxOccurs="unbounded">
-            <element ref="blacklist"/>
-            <element ref="whitelist"/>
-         </choice>
-         <attribute name="point" type="string" use="required">
-            <annotation>
-               <documentation>
-                  
-               </documentation>
-            </annotation>
-         </attribute>
-         <attribute name="id" type="string">
-            <annotation>
-               <documentation>
-                  
-               </documentation>
-            </annotation>
-         </attribute>
-         <attribute name="name" type="string">
-            <annotation>
-               <documentation>
-                  
-               </documentation>
-               <appinfo>
-                  <meta.attribute translatable="true"/>
-               </appinfo>
-            </annotation>
-         </attribute>
-      </complexType>
-   </element>
-
-   <element name="whitelist">
-      <annotation>
-         <documentation>
-            A black-listed command, one that is always allowed during keyboard macro recording
-         </documentation>
-      </annotation>
-      <complexType>
-         <attribute name="id" type="string" use="required">
-            <annotation>
-               <documentation>
-                  A command identifier
-               </documentation>
-               <appinfo>
-                  <meta.attribute kind="identifier" basedOn="org.eclipse.ui.commands/command/@id"/>
-               </appinfo>
-            </annotation>
-         </attribute>
-      </complexType>
-   </element>
-
-   <element name="blacklist">
-      <annotation>
-         <documentation>
-            A black-listed command, one that is never allowed during keyboard macro recording
-         </documentation>
-      </annotation>
-      <complexType>
-         <attribute name="id" type="string" use="required">
-            <annotation>
-               <documentation>
-                  A command identifier
-               </documentation>
-               <appinfo>
-                  <meta.attribute kind="identifier" basedOn="org.eclipse.ui.commands/command/@id"/>
-               </appinfo>
-            </annotation>
-         </attribute>
-      </complexType>
-   </element>
-
-   <annotation>
-      <appinfo>
-         <meta.section type="since"/>
-      </appinfo>
-      <documentation>
-         [Enter the first release in which this extension point appears.]
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appinfo>
-         <meta.section type="examples"/>
-      </appinfo>
-      <documentation>
-         [Enter extension point usage example here.]
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appinfo>
-         <meta.section type="apiinfo"/>
-      </appinfo>
-      <documentation>
-         [Enter API information here.]
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appinfo>
-         <meta.section type="implementation"/>
-      </appinfo>
-      <documentation>
-         [Enter information about supplied implementation of this extension point.]
-      </documentation>
-   </annotation>
-
-
-</schema>
diff --git a/bundles/org.eclipse.e4.ui.macros/schema/hooks.exsd b/bundles/org.eclipse.e4.ui.macros/schema/hooks.exsd
deleted file mode 100644
index a84e0c9..0000000
--- a/bundles/org.eclipse.e4.ui.macros/schema/hooks.exsd
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!-- Schema file written by PDE -->
-<schema targetNamespace="org.eclipse.e4.ui.macros" xmlns="http://www.w3.org/2001/XMLSchema">
-<annotation>
-      <appinfo>
-         <meta.schema plugin="org.eclipse.e4.ui.macros" id="hooks" name="Macro Recording and Playback Hooks"/>
-      </appinfo>
-      <documentation>
-         Provides hooks for packages to prepare for a macro being recorded.
-      </documentation>
-   </annotation>
-
-   <element name="extension">
-      <annotation>
-         <appinfo>
-            <meta.element />
-         </appinfo>
-      </annotation>
-      <complexType>
-         <choice>
-            <element ref="hook" minOccurs="1" maxOccurs="unbounded"/>
-         </choice>
-         <attribute name="point" type="string" use="required">
-            <annotation>
-               <documentation>
-                  
-               </documentation>
-            </annotation>
-         </attribute>
-         <attribute name="id" type="string">
-            <annotation>
-               <documentation>
-                  
-               </documentation>
-            </annotation>
-         </attribute>
-         <attribute name="name" type="string">
-            <annotation>
-               <documentation>
-                  
-               </documentation>
-               <appinfo>
-                  <meta.attribute translatable="true"/>
-               </appinfo>
-            </annotation>
-         </attribute>
-      </complexType>
-   </element>
-
-   <element name="hook">
-      <annotation>
-         <documentation>
-            A hook is notified before and after a macro is recorded or re-play. They are typically used to disable non-deterministic behaviours in the UI (i.e., where the results or ordering of results may change on subsequent re-invocations).
-         </documentation>
-      </annotation>
-      <complexType>
-         <attribute name="class" type="string" use="required">
-            <annotation>
-               <documentation>
-                  The hook class.
-               </documentation>
-               <appinfo>
-                  <meta.attribute kind="java" basedOn=":org.eclipse.e4.ui.macros.IMacroHook"/>
-               </appinfo>
-            </annotation>
-         </attribute>
-      </complexType>
-   </element>
-
-   <annotation>
-      <appinfo>
-         <meta.section type="since"/>
-      </appinfo>
-      <documentation>
-         [Enter the first release in which this extension point appears.]
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appinfo>
-         <meta.section type="examples"/>
-      </appinfo>
-      <documentation>
-         [Enter extension point usage example here.]
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appinfo>
-         <meta.section type="apiinfo"/>
-      </appinfo>
-      <documentation>
-         [Enter API information here.]
-      </documentation>
-   </annotation>
-
-   <annotation>
-      <appinfo>
-         <meta.section type="implementation"/>
-      </appinfo>
-      <documentation>
-         [Enter information about supplied implementation of this extension point.]
-      </documentation>
-   </annotation>
-
-
-</schema>
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ApplicationMacroPlayer.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ApplicationMacroPlayer.java
deleted file mode 100644
index 3020c30..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ApplicationMacroPlayer.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.eclipse.e4.ui.macros.IMacroAction;
-import org.eclipse.e4.ui.model.application.MApplication;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Shell;
-
-public class ApplicationMacroPlayer {
-	@Inject
-	MApplication application;
-	@Inject
-	Display display;
-
-	private LinkedList<IMacroAction> recording;
-
-	public void replay() {
-		recording = new LinkedList<>((List<IMacroAction>) application.getTransientData()
-				.get(ApplicationMacroRecorder.ACTIVE_RECORDING_MACRO_KEY));
-		if (recording == null || recording.isEmpty()) {
-			System.out.println("Recording is empty");
-			return;
-		}
-
-		hookListeners();
-		Event e = new Event();
-		e.display = display;
-		while (!display.isDisposed() && processNext(e)) {
-			if (!display.readAndDispatch()) {
-				display.sleep();
-			}
-		}
-		unhookListeners();
-	}
-
-	/** Return true if still more to come */
-	private boolean processNext(Event e) {
-		if (recording.isEmpty()) {
-			unhookListeners();
-			// System.out.println("REPLAY FINISHED");
-			return false;
-		}
-		IMacroAction nextAction = recording.peek();
-
-		switch (nextAction.process(e)) {
-		case NEXT:
-			// System.out.println("PROCESSED " + nextAction);
-			recording.removeFirst();
-			return true;
-		case WAITING:
-			// FIXME: set display timeout
-			// System.out.println("WAITING ON " + nextAction);
-			return true;
-		case ABORT:
-		default:
-			unhookListeners();
-			System.out.println("REPLAY ABORTED");
-			return false;
-		}
-	}
-
-	private void hookListeners() {
-		display.addFilter(SWT.Activate, shellActivatedListener);
-		display.addFilter(SWT.FocusIn, focusInListener);
-	}
-
-	private void unhookListeners() {
-		display.removeFilter(SWT.Activate, shellActivatedListener);
-		display.removeFilter(SWT.FocusIn, focusInListener);
-	}
-
-	private Listener shellActivatedListener = new Listener() {
-		@Override
-		public void handleEvent(Event event) {
-			if (event.widget instanceof Shell) {
-				processNext(event);
-			}
-		}
-	};
-
-	private Listener focusInListener = new Listener() {
-		@Override
-		public void handleEvent(Event event) {
-			processNext(event);
-		}
-	};
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ApplicationMacroRecorder.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ApplicationMacroRecorder.java
deleted file mode 100644
index a7d8989..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ApplicationMacroRecorder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.eclipse.e4.core.commands.EHandlerService;
-import org.eclipse.e4.ui.macros.IMacroAction;
-import org.eclipse.e4.ui.macros.IMacroActionProcessor;
-import org.eclipse.e4.ui.model.application.MApplication;
-
-public class ApplicationMacroRecorder implements IMacroActionProcessor {
-	static final String MACRO_RECORDING_KEY = "macro:recorded";
-	static final String ACTIVE_RECORDING_MACRO_KEY = "macro:current";
-
-	@Inject
-	MApplication application;
-
-	@Inject
-	EHandlerService handlerService;
-
-	@Override
-	public void started() {
-		application.getTransientData().put(ACTIVE_RECORDING_MACRO_KEY, new ArrayList<IMacroAction>());
-	}
-
-	@Override
-	public void finished() {
-		@SuppressWarnings("unchecked")
-		List<IMacroAction> recording = (List<IMacroAction>) application.getTransientData()
-				.get(ACTIVE_RECORDING_MACRO_KEY);
-		if (recording != null && !recording.isEmpty()) {
-			application.getTransientData().put(MACRO_RECORDING_KEY, recording);
-		}
-	}
-
-	@Override
-	public void aborted() {
-		application.getTransientData().remove(ACTIVE_RECORDING_MACRO_KEY);
-	}
-
-	@Override
-	public void process(IMacroAction action) {
-		List<IMacroAction> recording = (List<IMacroAction>) application.getTransientData()
-				.get(ACTIVE_RECORDING_MACRO_KEY);
-		recording.add(action);
-	}
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/DebuggingProcessor.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/DebuggingProcessor.java
deleted file mode 100644
index 67b8c3b..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/DebuggingProcessor.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros;
-
-import org.eclipse.e4.ui.macros.BaseProcessor;
-import org.eclipse.e4.ui.macros.IMacroAction;
-import org.eclipse.e4.ui.macros.IMacroActionProcessor;
-
-public class DebuggingProcessor implements IMacroActionProcessor {
-	private IMacroActionProcessor delegate = new BaseProcessor();
-
-	public void setDelegateRecorder(IMacroActionProcessor delegate) {
-		this.delegate = delegate;
-	}
-
-	public void started() {
-		System.out.println(">> STARTED");
-		delegate.started();
-	}
-
-	public void finished() {
-		System.out.println(">> FINISHED");
-		delegate.finished();
-	}
-
-	public void aborted() {
-		System.out.println(">> ABORTED");
-		delegate.finished();
-	}
-
-	@Override
-	public void process(IMacroAction action) {
-		System.out.println(">> " + action.toString());
-		delegate.process(action);
-	}
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/GestureInterpreter.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/GestureInterpreter.java
deleted file mode 100644
index 821c407..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/GestureInterpreter.java
+++ /dev/null
@@ -1,486 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Inject;
-
-import org.eclipse.core.commands.Command;
-import org.eclipse.core.commands.CommandManager;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.commands.IExecutionListener;
-import org.eclipse.core.commands.NotHandledException;
-import org.eclipse.core.commands.Parameterization;
-import org.eclipse.core.commands.ParameterizedCommand;
-import org.eclipse.core.commands.common.NotDefinedException;
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.IExtensionRegistry;
-import org.eclipse.e4.core.commands.EHandlerService;
-import org.eclipse.e4.core.contexts.IEclipseContext;
-import org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher;
-import org.eclipse.e4.ui.internal.macros.actions.InsertKeyStroke;
-import org.eclipse.e4.ui.internal.macros.actions.InvokeCommand;
-import org.eclipse.e4.ui.internal.macros.actions.WaitForShellActivation;
-import org.eclipse.e4.ui.internal.macros.actions.WaitForWidgetFocus;
-import org.eclipse.e4.ui.macros.IMacroAction;
-import org.eclipse.e4.ui.macros.IMacroActionProcessor;
-import org.eclipse.e4.ui.model.application.MApplication;
-import org.eclipse.e4.ui.workbench.renderers.swt.HandledContributionItem;
-import org.eclipse.jface.action.ActionContributionItem;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.action.IContributionItem;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.osgi.util.NLS;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.MenuItem;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.ToolBar;
-import org.eclipse.swt.widgets.ToolItem;
-import org.eclipse.swt.widgets.Widget;
-import org.eclipse.ui.internal.ActionSetContributionItem;
-import org.eclipse.ui.menus.CommandContributionItem;
-
-/**
- * Responsible for translating UI events into macro actions and sending them
- * along to interested parties implementing {@link IMacroActionProcessor} (e.g.,
- * to record the actions for future playback, or provide a UI/visualization).
- * 
- * The idea was this interpreter would act as an orchestrator of multiple
- * sources that produce {@link IMacroAction}s. But there are sufficiently
- * intertwined that we've just kept them together for now.
- */
-public class GestureInterpreter {
-	private static Class<?> commandContributionItemClass;
-
-	static {
-		try {
-			commandContributionItemClass = Class.forName("org.eclipse.ui.menus.CommandContributionItem");
-		} catch (Exception e) {
-			/* ignore */
-		}
-	}
-
-	@Inject
-	private MApplication application;
-
-	@Inject
-	private IEclipseContext context;
-
-	@Inject
-	private Display display;
-
-	@Inject
-	private CommandManager commandManager;
-
-	@Inject
-	private KeyBindingDispatcher dispatcher;
-
-	@Inject
-	EHandlerService handlerService;
-
-	@Inject
-	IExtensionRegistry registry;
-
-	/** Notified of macro actions */
-	private List<IMacroActionProcessor> processors = Collections
-			.synchronizedList(new LinkedList<IMacroActionProcessor>());
-
-	/**
-	 * Controls whether events should be turned into macro actions; used to
-	 * ignore events when popping up macro-related dialogs
-	 */
-	private boolean listeningPaused = false;
-
-	/******* Command white-listing and black-listing *******/
-	private static final String MACRO_COMMANDS_EXTPT = "org.eclipse.e4.ui.macros.commands";
-	private static final String NAME_BLACKLIST = "blacklist";
-	private static final String NAME_WHITELIST = "whitelist";
-	private static final String ATTR_ID = "id";
-
-	private Set<String> whitelistedCommandIds;
-	private Set<String> blacklistedCommandIds;
-
-
-
-	/** SWT.KeyDown listener to turn key presses into {@link IMacroAction}s */
-	private Listener keyDownListener = new Listener() {
-		@Override
-		public void handleEvent(Event event) {
-			dispatcher.getKeyDownFilter().handleEvent(event);
-			if (listeningPaused) {
-				return;
-			}
-			if (event.widget instanceof Control && shouldIgnore(event)) {
-				return;
-			}
-			// if not swallowed by the key dispatcher
-			if (event.doit && (event.keyCode & SWT.KEY_MASK) != SWT.NONE) {
-				// List<KeyStroke> strokes =
-				// KeyBindingDispatcher.generatePossibleKeyStrokes(event);
-				// System.out.println(">> keyCode: " + event.keyCode + "
-				// Strokes: " + strokes);
-				inject(new InsertKeyStroke(event, event.widget));
-			}
-		}
-	};
-
-	/**
-	 * SWT.Selection listener for menu and toolbar selections to pull out
-	 * commands
-	 */
-	private Listener menuToolbarSelectionListener = new Listener() {
-		@Override
-		public void handleEvent(Event event) {
-			if (listeningPaused) {
-				return;
-			}
-			// we're only interested in MenuItem and ToolItems
-			if (event.widget instanceof Control || shouldIgnore(event)) {
-				return;
-			}
-
-			Object object = event.widget.getData();
-			if (!processPotentialCommand(object)) {
-				abort();
-				MessageDialog.openError(null, "Unknown Action", "Command cannot be determined from this item");
-			}
-		}
-	};
-
-	/**
-	 * SWT.Activate listener for shells
-	 */
-	private Listener shellActivatedListener = new Listener() {
-		@Override
-		public void handleEvent(Event event) {
-			if (listeningPaused) {
-				return;
-			}
-			// should we track shell-activation because of a click in that
-			// window vs a command that opens a new Shell?
-			if (event.widget instanceof Shell && !shouldIgnore(event)) {
-				inject(new WaitForShellActivation(event.widget));
-			}
-		}
-	};
-
-	/**
-	 * SWT.FocusIn listener
-	 */
-	private Listener focusInListener = new Listener() {
-		@Override
-		public void handleEvent(Event event) {
-			if (listeningPaused) {
-				return;
-			}
-			if (event.widget instanceof Control && !shouldIgnore(event)) {
-				inject(new WaitForWidgetFocus(event.widget));
-			}
-		}
-	};
-
-	/** Turn successful command executions into actions */
-	private IExecutionListener commandExecutionListener = new IExecutionListener() {
-		private Map<String, ParameterizedCommand> inProgress = new HashMap<>();
-
-		@Override
-		public void preExecute(String commandId, ExecutionEvent event) {
-			// System.out.println("preExecute: " + commandId);
-			if (listeningPaused) {
-				return;
-			}
-			try {
-				if (!checkWhitelistedCommand(event.getCommand())) {
-					return;
-				}
-				ParameterizedCommand pc = ParameterizedCommand.generateCommand(event.getCommand(),
-						event.getParameters());
-				inProgress.put(commandId, pc);
-			} catch (NotDefinedException e) {
-				// ignore
-			}
-		}
-
-		@Override
-		public void postExecuteSuccess(String commandId, Object returnValue) {
-			// System.out.println("postExecuteSuccess: " + commandId);
-			ParameterizedCommand pc = inProgress.remove(commandId);
-			if (pc != null) {
-				inject(new InvokeCommand(handlerService, pc));
-			}
-		}
-
-		@Override
-		public void notHandled(String commandId, NotHandledException exception) {
-			// ignore these commands
-			inProgress.remove(commandId);
-		}
-
-		@Override
-		public void postExecuteFailure(String commandId, ExecutionException exception) {
-			// ignore these commands
-			inProgress.remove(commandId);
-		}
-	};
-
-	/**
-	 * Mouse events are difficult to turn into keyboard macro actions, except
-	 * for menu and tool items.
-	 */
-	private Listener mouseUpListener = new Listener() {
-		@Override
-		public void handleEvent(Event event) {
-			if (listeningPaused) {
-				return;
-			}
-			// Ignore SWT.MouseUp events on Menu and ToolBar as they're
-			// turned into SWT.Selection events on the corresponding item
-			// and handled in our SWT.Selection listener
-			if (!(event.widget instanceof Menu) && !(event.widget instanceof ToolBar)) {
-				// use asyncExec as any mouse and key events may be dispatched
-				// to the MessageDialog instead
-				event.display.asyncExec(new Runnable() {
-					@Override
-					public void run() {
-						abort();
-						MessageDialog.openError(null, "Macro Recording Aborted",
-								"Mouse click cannot be incorporated into macro");
-					}
-				});
-			}
-		}
-	};
-
-	/** List of {@link Shell}s that should be ignored */
-	private Set<Shell> ignoredShells = new HashSet<Shell>();
-
-	public void start() {
-		loadCommandWhiteAndBlacklists();
-		if (context != null) {
-			context.set(GestureInterpreter.class, this);
-		}
-
-		hookListeners();
-		synchronized (processors) {
-			for (IMacroActionProcessor recorder : processors) {
-				recorder.started();
-			}
-		}
-	}
-
-	public void finish() {
-		unhookListeners();
-
-		synchronized (processors) {
-			for (IMacroActionProcessor recorder : processors) {
-				recorder.finished();
-			}
-		}
-		if (context != null && context.get(GestureInterpreter.class) == this) {
-			context.remove(GestureInterpreter.class);
-		}
-	}
-
-	public void abort() {
-		unhookListeners();
-
-		synchronized (processors) {
-			for (IMacroActionProcessor recorder : processors) {
-				recorder.aborted();
-			}
-		}
-		if (context != null && context.get(GestureInterpreter.class) == this) {
-			context.remove(GestureInterpreter.class);
-		}
-	}
-
-	private void inject(IMacroAction action) {
-		synchronized (processors) {
-			for (IMacroActionProcessor recorder : processors) {
-				recorder.process(action);
-			}
-		}
-	}
-
-	protected boolean processPotentialCommand(Object object) {
-		if(object instanceof ParameterizedCommand) {
-			inject(new InvokeCommand(handlerService, (ParameterizedCommand) object));
-			return true;
-		} else if (object instanceof IContributionItem) {
-			IContributionItem item = (IContributionItem) object;
-			String id = item.getId();
-			if (commandContributionItemClass != null && commandContributionItemClass.isInstance(item)) {
-				CommandContributionItem cci = (CommandContributionItem) item;
-				return processPotentialCommand(cci.getCommand());
-			} else if (item instanceof HandledContributionItem) {
-				HandledContributionItem hci = (HandledContributionItem) item;
-				return processPotentialCommand(hci.getModel().getWbCommand());
-			} else if (item instanceof ActionContributionItem) {
-				return processPotentialCommand(((ActionContributionItem) item).getAction());
-			} else if (item instanceof ActionSetContributionItem) {
-				return processPotentialCommand(((ActionSetContributionItem) item).getInnerItem());
-			} else if (item instanceof ActionContributionItem) {
-				return processPotentialCommand(((ActionContributionItem) item).getAction());
-			}
-			return false;
-		} else if (object instanceof IAction) {
-			IAction action = (IAction) object;
-			if (action.getActionDefinitionId() != null) {
-				Command cmd = commandManager.getCommand(action.getActionDefinitionId());
-				if (cmd.isDefined()) {
-					return processPotentialCommand(new ParameterizedCommand(cmd, new Parameterization[0]));
-				}
-				System.err.println("Unable to find referenced command: " + action.getActionDefinitionId());
-			} else {
-				System.err.println("We do not currently support selecting actions");
-			}
-			return false;
-		}
-		return false;
-	}
-
-	protected boolean shouldIgnore(Event event) {
-		Shell shell = getShell(event.widget);
-		while (shell != null) {
-			if (ignoredShells.contains(shell)) {
-				return true;
-			}
-			shell = (Shell) shell.getParent();
-		}
-		return false;
-	}
-
-	private static Shell getShell(Widget widget) {
-		if (widget instanceof MenuItem) {
-			return ((MenuItem) widget).getParent().getShell();
-		} else if (widget instanceof ToolItem) {
-			return ((ToolItem) widget).getParent().getShell();
-		}
-		return ((Control) widget).getShell();
-	}
-
-	private void loadCommandWhiteAndBlacklists() {
-		whitelistedCommandIds = new HashSet<>();
-		blacklistedCommandIds = new HashSet<>();
-		String csv = application.getPersistedState().get(MACRO_COMMANDS_EXTPT + ":" + NAME_WHITELIST);
-		if (csv != null) {
-			Collections.addAll(whitelistedCommandIds, csv.split(","));
-		}
-		csv = application.getPersistedState().get(MACRO_COMMANDS_EXTPT + ":" + NAME_BLACKLIST);
-		if (csv != null) {
-			Collections.addAll(blacklistedCommandIds, csv.split(","));
-		}
-		for (IConfigurationElement ce : registry.getConfigurationElementsFor(MACRO_COMMANDS_EXTPT)) {
-			if (NAME_BLACKLIST.equals(ce.getName()) && ce.getAttribute(ATTR_ID) != null) {
-				blacklistedCommandIds.add(ce.getAttribute(ATTR_ID));
-			} else if (NAME_WHITELIST.equals(ce.getName()) && ce.getAttribute(ATTR_ID) != null) {
-				whitelistedCommandIds.add(ce.getAttribute(ATTR_ID));
-			}
-		}
-	}
-
-	protected boolean checkWhitelistedCommand(Command command) throws NotDefinedException {
-		String commandId = command.getId();
-		String commandName = command.getName();
-		if (blacklistedCommandIds.contains(commandId)) {
-			abort(); // unhooks listeners
-			MessageDialog.openError(null, "Disallowed Command",
-					NLS.bind("Command \"{0}\" ({1}) cannot be used during macro recording", commandName, commandId));
-			return false;
-		} else if (!whitelistedCommandIds.contains(commandId)) {
-			pauseListeners();
-			boolean shouldWhitelist = MessageDialog.openQuestion(null, "Whitelist command?",
-					NLS.bind("Should \"{0}\" ({1}) be allowed for macros?", commandName, commandId));
-			resumeListeners();
-			if (shouldWhitelist) {
-				System.err.println("FIXME: <whitelist id=\"" + commandId + "\" />");
-				whitelistedCommandIds.add(commandId);
-				String csv = application.getPersistedState().get(MACRO_COMMANDS_EXTPT + ":" + NAME_WHITELIST);
-				application.getPersistedState().put(MACRO_COMMANDS_EXTPT + ":" + NAME_WHITELIST,
-						csv == null ? commandId : csv + "," + commandId);
-			} else {
-				// FIXME: record the user's direction
-				System.err.println("FIXME: <blacklist id=\"" + commandId + "\" />");
-				// FIXME: record this more permanently
-				blacklistedCommandIds.add(commandId);
-				String csv = application.getPersistedState().get(MACRO_COMMANDS_EXTPT + ":" + NAME_BLACKLIST);
-				application.getPersistedState().put(MACRO_COMMANDS_EXTPT + ":" + NAME_BLACKLIST,
-						csv == null ? commandId : csv + "," + commandId);
-				abort();
-			}
-			return shouldWhitelist;
-		}
-		return true;
-	}
-
-	private void resumeListeners() {
-		listeningPaused = false;
-	}
-
-	private void pauseListeners() {
-		listeningPaused = true;
-	}
-
-	private void hookListeners() {
-		Listener keyFilter = dispatcher.getKeyDownFilter();
-		display.removeFilter(SWT.KeyDown, keyFilter);
-		display.removeFilter(SWT.Traverse, keyFilter);
-		display.addFilter(SWT.Traverse, keyDownListener);
-		display.addFilter(SWT.KeyDown, keyDownListener);
-
-		display.addFilter(SWT.MouseUp, mouseUpListener);
-		display.addFilter(SWT.Selection, menuToolbarSelectionListener);
-		display.addFilter(SWT.Activate, shellActivatedListener);
-		display.addFilter(SWT.FocusIn, focusInListener);
-		commandManager.addExecutionListener(commandExecutionListener);
-	}
-
-	private void unhookListeners() {
-		Listener keyFilter = dispatcher.getKeyDownFilter();
-		display.addFilter(SWT.KeyDown, keyFilter);
-		display.addFilter(SWT.Traverse, keyFilter);
-		display.removeFilter(SWT.Traverse, keyDownListener);
-		display.removeFilter(SWT.KeyDown, keyDownListener);
-
-		display.removeFilter(SWT.MouseUp, mouseUpListener);
-		display.removeFilter(SWT.Selection, menuToolbarSelectionListener);
-		display.removeFilter(SWT.Activate, shellActivatedListener);
-		display.removeFilter(SWT.FocusIn, focusInListener);
-		commandManager.removeExecutionListener(commandExecutionListener);
-	}
-
-	public void addListener(IMacroActionProcessor recorder) {
-		processors.add(recorder);
-	}
-
-	public void removeListener(IMacroActionProcessor recorder) {
-		processors.remove(recorder);
-	}
-
-	/** Ignore events coming from the provided shell */
-	public void addIgnoreShell(Shell shell) {
-		ignoredShells.add(shell);
-	}
-
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/MacroHooksManager.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/MacroHooksManager.java
deleted file mode 100644
index 4f5fd00..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/MacroHooksManager.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.IExtensionRegistry;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.e4.ui.macros.IMacroHook;
-import org.eclipse.e4.ui.model.application.MApplication;
-
-public class MacroHooksManager {
-
-	static final String HOOKS_EXTPT = "org.eclipse.e4.ui.macros.hooks";
-	static final String NAME_HOOK = "hook";
-	static final String ATTR_CLASS = "class";
-
-	@Inject
-	private MApplication application;
-
-	@Inject
-	private IExtensionRegistry registry;
-
-	private List<IMacroHook> hooks;
-
-	public IStatus runStartHooks(IMacroHook.Mode mode) {
-		if (hooks != null) {
-			System.out.println(">> Hooks exist: already in progress?");
-			return new Status(IStatus.ERROR, "org.eclipse.e4.ui.macros", "Macro operation already in progress");
-		}
-		// System.out.println(">> Running starting hooks (" + mode + ")...");
-		hooks = new LinkedList<>();
-		for (IConfigurationElement ce : registry.getConfigurationElementsFor(HOOKS_EXTPT)) {
-			if (ce.getName().equals(NAME_HOOK) && ce.getAttribute(ATTR_CLASS) != null) {
-				try {
-					IMacroHook hook = (IMacroHook) ce.createExecutableExtension(ATTR_CLASS);
-					IStatus rc = hook.start(mode);
-					if (!rc.isOK()) {
-						return rc;
-					}
-					hooks.add(hook);
-				} catch (CoreException e) {
-					System.err.println("Unable to instantiate class: " + e);
-				}
-			}
-		}
-		return Status.OK_STATUS;
-	}
-
-	public void runFinishHooks(IMacroHook.Mode mode) {
-		// may not have been running
-		if (hooks != null) {
-			// System.out.println(">> Running finished hooks (" + mode +
-			// ")...");
-			for (IMacroHook hook : hooks) {
-				hook.stop(mode);
-			}
-			hooks = null;
-		}
-	}
-
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/MacroRecorderInstaller.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/MacroRecorderInstaller.java
deleted file mode 100644
index 4da49c7..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/MacroRecorderInstaller.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros;
-
-import java.util.Comparator;
-import java.util.TreeSet;
-
-import javax.inject.Inject;
-
-import org.eclipse.e4.core.di.annotations.Execute;
-import org.eclipse.e4.ui.model.application.MApplication;
-import org.eclipse.e4.ui.model.application.commands.MBindingContext;
-import org.eclipse.e4.ui.model.application.commands.MBindingTable;
-import org.eclipse.e4.ui.model.application.commands.MCommand;
-import org.eclipse.e4.ui.model.application.commands.MHandler;
-import org.eclipse.e4.ui.model.application.commands.MKeyBinding;
-import org.eclipse.e4.ui.workbench.modeling.EModelService;
-import org.osgi.framework.FrameworkUtil;
-
-/**
- * E4 Model Processor to set up macro recording and playback commands
- */
-public class MacroRecorderInstaller {
-	private static final String TOGGLE_RECORDING_COMMAND = "org.eclipse.e4.ui.macros.toggleRecording";
-
-	private static final String PLAY_MACRO_COMMAND = "org.eclipse.e4.ui.macros.playRecording";
-
-	@Inject
-	private MApplication application;
-
-	@Inject
-	private EModelService modelService;
-
-	private String bundleId = FrameworkUtil.getBundle(getClass()).getSymbolicName();
-
-
-	@Execute
-	public void process() {
-		MCommand recordMacro = installCommand(TOGGLE_RECORDING_COMMAND, "Start/Stop recording a macro",
-				"Start recording a macro or stop the current macro");
-		installHandler(recordMacro, ToggleRecordingHandler.class);
-		installKeyBinding("org.eclipse.ui.contexts.window", "M2+M3+M", recordMacro);
-
-		MCommand replay = installCommand(PLAY_MACRO_COMMAND, "Play macro", "Replay the last recorded macro");
-		installHandler(replay, ReplayMacroHandler.class);
-		installKeyBinding("org.eclipse.ui.contexts.window", "M1+M2+M", replay);
-	}
-
-	private MCommand installCommand(String commandId, String name, String description) {
-		for (MCommand cmd : application.getCommands()) {
-			if (commandId.equals(cmd.getElementId())) {
-				// Already exists
-				return cmd;
-			}
-		}
-
-		MCommand command = modelService.createModelElement(MCommand.class);
-		command.setElementId(commandId);
-		command.setCommandName(name);
-		command.setDescription(description);
-		command.setContributorURI("platform:/plugin/" + bundleId);
-
-		application.getCommands().add(command);
-		return command;
-	}
-
-	private MHandler installHandler(MCommand command, Class<?> handlerClass) {
-		String handlerBundleId = FrameworkUtil.getBundle(handlerClass).getSymbolicName();
-		String contributionURI = "bundleclass://" + handlerBundleId + "/" + handlerClass.getName();
-
-		for (MHandler handler : application.getHandlers()) {
-			if (contributionURI.equals(handler.getContributionURI())) {
-				// Already exists
-				return handler;
-			}
-		}
-
-		MHandler handler = modelService.createModelElement(MHandler.class);
-		handler.setElementId(handlerClass.getName());
-		handler.setCommand(command);
-		handler.setContributionURI(contributionURI);
-		handler.setContributorURI("platform:/plugin/" + handlerBundleId);
-		application.getHandlers().add(handler);
-		return handler;
-	}
-
-	private MKeyBinding installKeyBinding(String bindingContextId, String keySeq, MCommand command) {
-		MBindingContext bindingContext = findBindingContext(bindingContextId);
-		if (bindingContext == null) {
-			bindingContext = modelService.createModelElement(MBindingContext.class);
-			bindingContext.setElementId(bindingContextId);
-			application.getBindingContexts().add(bindingContext);
-		}
-
-		MBindingTable bindingTable = null;
-		for (MBindingTable bt : application.getBindingTables()) {
-			if (bt.getBindingContext() == bindingContext) {
-				bindingTable = bt;
-				break;
-			}
-		}
-		if (bindingTable == null) {
-			bindingTable = modelService.createModelElement(MBindingTable.class);
-			bindingTable.setBindingContext(bindingContext);
-			application.getBindingTables().add(bindingTable);
-		}
-		for (MKeyBinding kb : bindingTable.getBindings()) {
-			if (kb.getCommand() == command) {
-				// already bound
-				return kb;
-			}
-		}
-
-		MKeyBinding keyBinding = modelService.createModelElement(MKeyBinding.class);
-		keyBinding.setKeySequence(keySeq);
-		keyBinding.setContributorURI("platform:/plugin/" + bundleId);
-		keyBinding.setCommand(command);
-		bindingTable.getBindings().add(keyBinding);
-		return keyBinding;
-	}
-
-	private MBindingContext findBindingContext(String bindingContextId) {
-		TreeSet<MBindingContext> contexts = new TreeSet<>(new Comparator<MBindingContext>() {
-			@Override
-			public int compare(MBindingContext o1, MBindingContext o2) {
-				return o1.getElementId().compareTo(o2.getElementId());
-			}
-		});
-		contexts.addAll(application.getBindingContexts());
-		while (!contexts.isEmpty()) {
-			MBindingContext bc = contexts.first();
-			if (bindingContextId.equals(bc.getElementId())) {
-				return bc;
-			}
-			contexts.remove(bc);
-			contexts.addAll(bc.getChildren());
-		}
-		return null;
-	}
-
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/MacroStatusPopup.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/MacroStatusPopup.java
deleted file mode 100644
index 334ebd1..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/MacroStatusPopup.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import org.eclipse.e4.ui.macros.BaseProcessor;
-import org.eclipse.e4.ui.macros.IMacroAction;
-import org.eclipse.e4.ui.macros.IMacroActionProcessor;
-import org.eclipse.jface.layout.GridDataFactory;
-import org.eclipse.jface.layout.GridLayoutFactory;
-import org.eclipse.jface.viewers.ArrayContentProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.window.Window;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Layout;
-import org.eclipse.swt.widgets.Shell;
-
-/**
- * Provides a visualization on the macro recording process.
- */
-public class MacroStatusPopup extends Window {
-	private GestureInterpreter interpreter;
-	private List<IMacroAction> actions;
-	private TableViewer viewer;
-	private Label status;
-
-	/** Visualize an interpreter instance */
-	public static void monitor(GestureInterpreter interpreter) {
-		MacroStatusPopup popup = new MacroStatusPopup(interpreter);
-		interpreter.addListener(popup.listener);
-	}
-
-	private IMacroActionProcessor listener = new BaseProcessor() {
-		@Override
-		public void started() {
-			open();
-		}
-
-		@Override
-		public void finished() {
-			closeWindow();
-		}
-
-		@Override
-		public void aborted() {
-			closeWindow();
-		}
-
-		@Override
-		public void process(IMacroAction action) {
-			addAction(action);
-		}
-	};
-
-	private MacroStatusPopup(GestureInterpreter interpreter) {
-		super((Shell) null);
-		setShellStyle(SWT.DIALOG_TRIM | SWT.ON_TOP | SWT.RESIZE);
-		setBlockOnOpen(false);
-		this.interpreter = interpreter;
-	}
-
-	@Override
-	public int open() {
-		// call create() to ensure our Shell is created -- but not visible --
-		// to find the Display instance so that we can restore focus
-		// back to the current shell
-		create();
-		Shell activeShell = getShell().getDisplay().getActiveShell();
-		int rc = super.open();
-		if (activeShell != null) {
-			activeShell.forceActive();
-		}
-		return rc;
-	}
-
-	@Override
-	protected Point getInitialSize() {
-		return new Point(200, 150);
-	}
-
-	@Override
-	protected Layout getLayout() {
-		return new FillLayout();
-	}
-
-	@Override
-	protected Control createContents(final Composite container) {
-		final Display display = container.getDisplay();
-
-		interpreter.addIgnoreShell(container.getShell());
-
-		Composite parent = new Composite(container, SWT.NONE);
-		status = new Label(parent, SWT.NONE);
-		viewer = new TableViewer(parent, SWT.FULL_SELECTION);
-		GridDataFactory.fillDefaults().applyTo(status);
-		GridDataFactory.fillDefaults().grab(true, true).applyTo(viewer.getControl());
-		GridLayoutFactory.fillDefaults().applyTo(parent);
-
-		// poor man's button
-		status.setText("FINISH");
-		status.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
-		status.setBackground(display.getSystemColor(SWT.COLOR_RED));
-		status.addMouseListener(new MouseAdapter() {
-			@Override
-			public void mouseDown(MouseEvent e) {
-				finish();
-			}
-		});
-
-		// stop recording if the window is disposed of
-		container.addDisposeListener(new DisposeListener() {
-			@Override
-			public void widgetDisposed(DisposeEvent e) {
-				finish();
-			}
-		});
-
-		viewer.setContentProvider(new ArrayContentProvider());
-		viewer.setLabelProvider(new LabelProvider());
-		actions = new LinkedList<>();
-		viewer.setInput(actions);
-
-		return parent;
-	}
-
-	protected void finish() {
-		interpreter.finish();
-	}
-
-	private void closeWindow() {
-		final Shell shell = getShell();
-		if (shell == null || shell.isDisposed()) {
-			return;
-		}
-		shell.getDisplay().asyncExec(new Runnable() {
-			@Override
-			public void run() {
-				close();
-			}
-		});
-	}
-
-
-	protected void addAction(final IMacroAction action) {
-		final Shell shell = getShell();
-		if (shell == null || shell.isDisposed()) {
-			return;
-		}
-		// should just use databinding
-		actions.add(action);
-		shell.getDisplay().asyncExec(new Runnable() {
-			public void run() {
-				if (shell != null && !shell.isDisposed()) {
-					viewer.refresh();
-					// scroll to bottom
-					int count = viewer.getTable().getItemCount();
-					viewer.getTable().showItem(viewer.getTable().getItem(count - 1));
-				}
-			}
-		});
-	}
-
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ReplayMacroHandler.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ReplayMacroHandler.java
deleted file mode 100644
index ee9fb8b..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ReplayMacroHandler.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.e4.core.contexts.ContextInjectionFactory;
-import org.eclipse.e4.core.contexts.IEclipseContext;
-import org.eclipse.e4.core.di.annotations.CanExecute;
-import org.eclipse.e4.core.di.annotations.Execute;
-import org.eclipse.e4.core.di.annotations.Optional;
-import org.eclipse.e4.ui.macros.IMacroHook;
-import org.eclipse.e4.ui.macros.IMacroHook.Mode;
-import org.eclipse.e4.ui.model.application.MApplication;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.osgi.framework.FrameworkUtil;
-
-public class ReplayMacroHandler {
-	private static String pluginId = FrameworkUtil.getBundle(ToggleRecordingHandler.class).getSymbolicName();
-
-	@CanExecute
-	public boolean canExecute(MApplication application) {
-		// if we have hooks then a macro recording or replay is in progress
-		return application.getTransientData().get(MacroHooksManager.class.getName()) == null;
-	}
-
-	@Execute
-	public void execute(MApplication application, Display display, @Optional Event triggeringEvent) {
-		IEclipseContext context = application.getContext();
-		assert context != null; // still not certain if this is required
-
-		waitForModifiers(display, triggeringEvent);
-
-		ApplicationMacroPlayer player = ContextInjectionFactory.make(ApplicationMacroPlayer.class, context);
-		IStatus rc = runStartHooks(application, IMacroHook.Mode.PLAYBACK);
-		try {
-			if (rc.isOK()) {
-				player.replay();
-			} else {
-				System.err.println("Playback aborted: " + rc);
-			}
-		} finally {
-			runFinishHooks(application, IMacroHook.Mode.PLAYBACK);
-		}
-	}
-
-	/**
-	 * The triggering event is likely a KeyDown event; wait for any modifier
-	 * keys to be released
-	 * @param display
-	 * @param triggeringEvent (may be null)
-	 */
-	private void waitForModifiers(Display display, Event triggeringEvent) {
-		if (triggeringEvent == null || (triggeringEvent.type != SWT.KeyUp && triggeringEvent.type != SWT.KeyDown)
-				|| (triggeringEvent.type == SWT.KeyDown
-						&& ((triggeringEvent.stateMask | triggeringEvent.keyCode) & SWT.MODIFIER_MASK) == 0)
-				|| (triggeringEvent.type == SWT.KeyUp
-						&& (triggeringEvent.stateMask & ~(triggeringEvent.keyCode & SWT.MODIFIER_MASK)) == 0)) {
-			return;
-		}
-		final boolean ready[] = { false };
-		Listener keyUpListener = new Listener() {
-			@Override
-			public void handleEvent(Event event) {
-				// stateMask has the modifiers *prior* to this KeyUp so, providing
-				// this keyCode is a modifier, we need to remove it
-				int stateMask = event.stateMask & ~(event.keyCode & SWT.MODIFIER_MASK);
-				ready[0] = stateMask == 0;
-			}
-		};
-
-		// Wait for the keyboard modifiers to be released
-		display.addFilter(SWT.KeyUp, keyUpListener);
-		while (!ready[0] && !display.isDisposed()) {
-			if (!display.readAndDispatch()) {
-				display.sleep();
-			}
-		}
-		display.removeFilter(SWT.KeyUp, keyUpListener);
-	}
-
-	private IStatus runStartHooks(MApplication application, Mode mode) {
-		MacroHooksManager mgr = (MacroHooksManager) application.getTransientData()
-				.get(MacroHooksManager.class.getName());
-		if (mgr != null) {
-			return new Status(IStatus.ERROR, pluginId, "Macro already in progress");
-		}
-		mgr = ContextInjectionFactory.make(MacroHooksManager.class, application.getContext());
-		application.getTransientData().put(MacroHooksManager.class.getName(), mgr);
-		return mgr.runStartHooks(mode);
-	}
-
-	private IStatus runFinishHooks(MApplication application, Mode mode) {
-		MacroHooksManager mgr = (MacroHooksManager) application.getTransientData()
-				.remove(MacroHooksManager.class.getName());
-		if (mgr == null) {
-			return new Status(IStatus.ERROR, pluginId, "No macro in progress");
-		}
-		mgr.runFinishHooks(mode);
-		return Status.OK_STATUS;
-	}
-
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ToggleRecordingHandler.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ToggleRecordingHandler.java
deleted file mode 100644
index f5e0cb7..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/ToggleRecordingHandler.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.e4.core.contexts.ContextInjectionFactory;
-import org.eclipse.e4.core.contexts.IEclipseContext;
-import org.eclipse.e4.core.di.annotations.Execute;
-import org.eclipse.e4.ui.macros.BaseProcessor;
-import org.eclipse.e4.ui.macros.IMacroActionProcessor;
-import org.eclipse.e4.ui.macros.IMacroHook;
-import org.eclipse.e4.ui.macros.IMacroHook.Mode;
-import org.eclipse.e4.ui.model.application.MApplication;
-import org.osgi.framework.FrameworkUtil;
-
-public class ToggleRecordingHandler {
-	private static String pluginId = FrameworkUtil.getBundle(ToggleRecordingHandler.class).getSymbolicName();
-
-	@Execute
-	public void execute(MApplication application) {
-		IEclipseContext context = application.getContext();
-		assert context != null;
-		GestureInterpreter interpreter = context.get(GestureInterpreter.class);
-		if (interpreter == null) {
-			// start recording
-			interpreter = ContextInjectionFactory.make(GestureInterpreter.class, context);
-
-			IMacroActionProcessor recorder = ContextInjectionFactory.make(ApplicationMacroRecorder.class, context);
-			// interpreter.addListener(recorder);
-
-			DebuggingProcessor debugging = ContextInjectionFactory.make(DebuggingProcessor.class, context);
-			debugging.setDelegateRecorder(recorder);
-			interpreter.addListener(debugging);
-
-			openMacroWindow(interpreter, application);
-			start(interpreter, application);
-		} else {
-			finish(interpreter, application);
-		}
-	}
-
-	private void start(GestureInterpreter interpreter, final MApplication application) {
-		IStatus rc = runStartHooks(application, IMacroHook.Mode.RECORDING);
-		if (!rc.isOK()) {
-			runFinishHooks(application, IMacroHook.Mode.RECORDING);
-		} else {
-			interpreter.addListener(new BaseProcessor() {
-				@Override
-				public void finished() {
-					runFinishHooks(application, IMacroHook.Mode.RECORDING);
-				}
-
-				@Override
-				public void aborted() {
-					runFinishHooks(application, IMacroHook.Mode.RECORDING);
-				}
-			});
-			interpreter.start();
-		}
-	}
-
-	private void finish(GestureInterpreter interpreter, MApplication application) {
-		interpreter.finish();
-	}
-
-	private void openMacroWindow(final GestureInterpreter interpreter, final MApplication application) {
-		MacroStatusPopup.monitor(interpreter);
-	}
-
-	// should probably be moved outside of the handlers
-	private IStatus runStartHooks(MApplication application, Mode mode) {
-		MacroHooksManager mgr = (MacroHooksManager) application.getTransientData()
-				.get(MacroHooksManager.class.getName());
-		if (mgr != null) {
-			return new Status(IStatus.ERROR, pluginId, "Macro already in progress");
-		}
-		mgr = ContextInjectionFactory.make(MacroHooksManager.class, application.getContext());
-		application.getTransientData().put(MacroHooksManager.class.getName(), mgr);
-		return mgr.runStartHooks(mode);
-	}
-
-	private IStatus runFinishHooks(MApplication application, Mode mode) {
-		MacroHooksManager mgr = (MacroHooksManager) application.getTransientData()
-				.remove(MacroHooksManager.class.getName());
-		if (mgr == null) {
-			return new Status(IStatus.ERROR, pluginId, "No macro in progress");
-		}
-		mgr.runFinishHooks(mode);
-		return Status.OK_STATUS;
-	}
-
-
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/InsertKeyStroke.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/InsertKeyStroke.java
deleted file mode 100644
index 39a9e47..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/InsertKeyStroke.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros.actions;
-
-import org.eclipse.e4.ui.macros.IMacroAction;
-import org.eclipse.jface.bindings.keys.SWTKeySupport;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Widget;
-
-/**
- * Keyboard macro performed some key stroke
- */
-public class InsertKeyStroke implements IMacroAction {
-	private static int[] stateKeyCodes = { SWT.MOD1, SWT.MOD2, SWT.MOD3, SWT.MOD4 };
-	private char character;
-	private int stateMask;
-	private int keyCode;
-
-	public InsertKeyStroke(Event event, Widget widget) {
-		this.character = event.character;
-		this.stateMask = event.stateMask;
-		this.keyCode = event.keyCode;
-	}
-
-	@Override
-	public ReplayState process(Event e) {
-		postKeyStroke(e.display);
-		return ReplayState.NEXT;
-	}
-
-	private void postKeyStroke(final Display display) {
-		Event event;
-		for (int i = 0; i < stateKeyCodes.length; i++) {
-			if (stateKeyCodes[i] > 0 && (stateMask & stateKeyCodes[i]) != 0) {
-				event = new Event();
-				event.type = SWT.KeyDown;
-				event.keyCode = stateKeyCodes[i];
-				display.post(event);
-			}
-		}
-		event = new Event();
-		event.type = SWT.KeyDown;
-		event.character = character;
-		event.keyCode = keyCode;
-		display.post(event);
-
-		event = new Event();
-		event.type = SWT.KeyUp;
-		event.character = character;
-		event.keyCode = keyCode;
-		display.post(event);
-
-		for (int i = 0; i < stateKeyCodes.length; i++) {
-			if (stateKeyCodes[i] > 0 && (stateMask & stateKeyCodes[i]) != 0) {
-				event = new Event();
-				event.type = SWT.KeyUp;
-				event.keyCode = stateKeyCodes[i];
-				display.post(event);
-			}
-		}
-	}
-
-	@Override
-	public String toString() {
-		return "Key " + SWTKeySupport.getKeyFormatterForPlatform().format(keyCode);
-	}
-
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/InvokeCommand.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/InvokeCommand.java
deleted file mode 100644
index 544efdc..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/InvokeCommand.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros.actions;
-
-import org.eclipse.core.commands.ParameterizedCommand;
-import org.eclipse.e4.core.commands.EHandlerService;
-import org.eclipse.e4.ui.macros.IMacroAction;
-import org.eclipse.swt.widgets.Event;
-
-/**
- * Keyboard macro invoked an Eclipse-level command.
- */
-public class InvokeCommand implements IMacroAction {
-	private EHandlerService handlerService;
-	private ParameterizedCommand command;
-
-	public InvokeCommand(EHandlerService hs, ParameterizedCommand command) {
-		this.handlerService = hs;
-		this.command = command;
-	}
-
-	@Override
-	public ReplayState process(Event e) {
-		if (!handlerService.canExecute(command)) {
-			return ReplayState.ABORT;
-		}
-		handlerService.executeHandler(command);
-		return ReplayState.NEXT;
-	}
-
-	@Override
-	public String toString() {
-		return "Invoke " + command.getId();
-	}
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/WaitForShellActivation.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/WaitForShellActivation.java
deleted file mode 100644
index 89b7bb6..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/WaitForShellActivation.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros.actions;
-
-import org.eclipse.e4.ui.macros.IMacroAction;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Widget;
-
-public class WaitForShellActivation implements IMacroAction {
-	public WaitForShellActivation(Widget widget) {
-		// FIXME: store identifying information for the widget shell details?
-	}
-
-	@Override
-	public ReplayState process(Event e) {
-		// if (e.type == SWT.Activate && e.widget.getClass() == Shell.class) {
-		// return ReplayState.NEXT;
-		// }
-		// return ReplayState.WAITING;
-
-		return ReplayState.NEXT;
-	}
-
-	public String toString() {
-		return "Wait for shell activation";
-	}
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/WaitForWidgetFocus.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/WaitForWidgetFocus.java
deleted file mode 100644
index c341d3b..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/internal/macros/actions/WaitForWidgetFocus.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.internal.macros.actions;
-
-import org.eclipse.e4.ui.macros.IMacroAction;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Widget;
-
-public class WaitForWidgetFocus implements IMacroAction {
-	private Class<? extends Widget> widgetClass;
-
-	public WaitForWidgetFocus(Widget widget) {
-		this.widgetClass = widget.getClass();
-	}
-
-	@Override
-	public ReplayState process(Event e) {
-		Control focus = e.display.getFocusControl();
-		if (focus != null && focus.getClass() == widgetClass) {
-			return ReplayState.NEXT;
-		} else if (e.type == SWT.FocusIn && e.widget.getClass() == widgetClass) {
-			return ReplayState.NEXT;
-		}
-		return ReplayState.WAITING;
-	}
-
-	public String toString() {
-		return "Wait for focus onto " + widgetClass.getName();
-	}
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/Activator.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/Activator.java
new file mode 100644
index 0000000..9c7cc18
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/Activator.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+@SuppressWarnings("javadoc")
+public class Activator extends AbstractUIPlugin {
+
+	private static Activator plugin;
+
+	public Activator() {
+		super();
+		plugin = this;
+	}
+
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+	public static ImageDescriptor getImageDescriptor(String key) {
+		return getDefault().getImageRegistry().getDescriptor(key);
+	}
+
+	public static void log(Throwable exception) {
+		try {
+			if (plugin != null) {
+				plugin.getLog().log(new Status(IStatus.ERROR, plugin.getBundle().getSymbolicName(),
+						exception.getMessage(), exception));
+			} else {
+				// The plugin is not available. Just print to stderr.
+				exception.printStackTrace();
+			}
+		} catch (Exception e) {
+			// Print the original error if something happened, not the one
+			// related to the log not working.
+			exception.printStackTrace();
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/BaseProcessor.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/BaseProcessor.java
deleted file mode 100644
index faad601..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/BaseProcessor.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.macros;
-
-/** A processor that does nothing */
-public class BaseProcessor implements IMacroActionProcessor {
-
-	@Override
-	public void started() {
-	}
-
-	@Override
-	public void process(IMacroAction action) {
-	}
-
-	@Override
-	public void finished() {
-	}
-
-	@Override
-	public void aborted() {
-	}
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/IMacroAction.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/IMacroAction.java
deleted file mode 100644
index 33beb02..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/IMacroAction.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.macros;
-
-import org.eclipse.swt.widgets.Event;
-
-public interface IMacroAction {
-	/** The state of this action after processing an event */
-	public enum ReplayState {
-		/** This event has not changed the state of this action */
-		WAITING,
-
-		/**
-		 * This event is not compatible with this action; the macro should be
-		 * aborted
-		 */
-		ABORT,
-
-		/**
-		 * This event has been processed and the macro should move to the next
-		 * action
-		 */
-		NEXT
-	};
-
-	public ReplayState process(Event e);
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/IMacroActionProcessor.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/IMacroActionProcessor.java
deleted file mode 100644
index 19b1192..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/IMacroActionProcessor.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.macros;
-
-/**
- * A party interested in receiving macro actions (e.g., to record them for
- * playback, or providing a UI for visualizing the status). The idea behind the
- * {@link IMacroActionProcessor}s was that there could could be intermediates that coalesce
- * some of these actions, but it hasn't proven necessary so far.
- */
-public interface IMacroActionProcessor {
-
-	/** A macro recording has begun */
-	void started();
-
-	/** The macro recording has finished */
-	void finished();
-
-	/** The macro recording has been aborted */
-	void aborted();
-
-	/** An action occurred during the macro */
-	void process(IMacroAction action);
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/IMacroHook.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/IMacroHook.java
deleted file mode 100644
index fa4e0ac..0000000
--- a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/IMacroHook.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Manumitting Technologies Inc and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     Manumitting Technologies - initial API and implementation
- *******************************************************************************/
-package org.eclipse.e4.ui.macros;
-
-import org.eclipse.core.runtime.IStatus;
-
-/**
- * A hook is notified before and after a macro is recorded or re-played. They
- * are typically used to disable non-deterministic behaviours in the UI (i.e.,
- * where the results or ordering of results may change on subsequent
- * re-invocations). These hooks are configured with the
- * <code>org.eclipse.e4.ui.macros.hooks</code> extension point.
- * 
- * <p>
- * The macro system guarantees:
- * </p>
- * <ol>
- * <li>An instance that receives {{@link #start(Mode)} will receive a
- * corresponding {@link #stop(Mode)}.</li>
- * <li>The same instance that receives {{@link #start(Mode)} will receive
- * {@link #stop(Mode)}.</li>
- * </ol>
- */
-public interface IMacroHook {
-	enum Mode {
-		/** A macro is about to be or finished being recorded */
-		RECORDING,
-
-		/** A macro is about to be or finished being replayed */
-		PLAYBACK
-	};
-
-	/**
-	 * Prepare for a macro to be recorded or played-back. Returns a status
-	 * object; if not OK then the macro will be aborted.
-	 * 
-	 * @param mode
-	 *            the macro mode
-	 * @return the status
-	 */
-	IStatus start(Mode mode);
-
-	/**
-	 * The macro recording or playback has been completed (perhaps successfully
-	 * but also may have been aborted).
-	 * 
-	 * @param mode
-	 *            the macro mode
-	 */
-	void stop(Mode mode);
-}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/EditorUtils.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/EditorUtils.java
new file mode 100644
index 0000000..8a80cb9
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/EditorUtils.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal;
+
+import org.eclipse.e4.core.macros.IMacroContext;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Utilities related to getting/storing the current editor from/to the macro
+ * context.
+ */
+public class EditorUtils {
+
+	/**
+	 * A variable which holds the current editor when macro record or playback
+	 * started.
+	 */
+	private final static String TARGET_STYLED_TEXT = "TARGET_STYLED_TEXT"; //$NON-NLS-1$
+
+	/**
+	 * A variable which holds the current editor part when macro record or playback
+	 * started.
+	 */
+	private final static String TARGET_EDITOR_PART = "TARGET_EDITOR_PART"; //$NON-NLS-1$
+
+	/**
+	 * @return the StyledText related to the current editor or null if there's no
+	 *         such widget available (i.e.: if the current editor is not a text
+	 *         editor or if there's no open editor).
+	 */
+	public static StyledText getActiveStyledText() {
+		IEditorPart activeEditor = getActiveEditorPart();
+		if (activeEditor == null) {
+			return null;
+		}
+		return getEditorPartStyledText(activeEditor);
+	}
+
+	public static IEditorPart getActiveEditorPart() {
+		IWorkbenchWindow activeWorkbenchWindow = getActivateWorkbenchWindow();
+		if (activeWorkbenchWindow == null) {
+			return null;
+		}
+		IWorkbenchPage activePage = activeWorkbenchWindow.getActivePage();
+		if (activePage == null) {
+			return null;
+		}
+		return activePage.getActiveEditor();
+	}
+
+	/**
+	 * @return the currently active workbench window or null if not available.
+	 */
+	public static IWorkbenchWindow getActivateWorkbenchWindow() {
+		IWorkbench workbench;
+		try {
+			workbench = PlatformUI.getWorkbench();
+		} catch (IllegalStateException e) { // java.lang.IllegalStateException: Workbench has not been created yet.
+			return null;
+		}
+		return workbench.getActiveWorkbenchWindow();
+	}
+
+	/**
+	 * @param editor
+	 *            the editor for which we want the StyledText.
+	 * @return the StyledText related to the current editor or null if it doesn't
+	 *         have a StyledText.
+	 */
+	public static StyledText getEditorPartStyledText(IEditorPart editor) {
+		Control control = editor.getAdapter(Control.class);
+		StyledText styledText = null;
+		if (control instanceof StyledText) {
+			styledText = (StyledText) control;
+		}
+		return styledText;
+	}
+
+	/**
+	 * Caches the current styled text as being the one active in the passed macro
+	 * context.
+	 *
+	 * @param macroContext
+	 *            the macro context where it should be set.
+	 */
+	public static void cacheTargetStyledText(IMacroContext macroContext) {
+		if (macroContext != null) {
+			Object object = macroContext.get(TARGET_STYLED_TEXT);
+			if (object == null) {
+				macroContext.set(TARGET_STYLED_TEXT, getActiveStyledText());
+			}
+		}
+	}
+
+	/**
+	 * Caches the current editor part as being the one active in the passed macro
+	 * context.
+	 *
+	 * @param macroContext
+	 *            the macro context where it should be set.
+	 */
+	public static void cacheTargetEditorPart(IMacroContext macroContext) {
+		if (macroContext != null) {
+			Object object = macroContext.get(TARGET_EDITOR_PART);
+			if (object == null) {
+				macroContext.set(TARGET_EDITOR_PART, getActiveEditorPart());
+			}
+		}
+	}
+
+
+	/**
+	 * Gets the styled text which was set as the current when the macro context was
+	 * created.
+	 *
+	 * @param macroContext
+	 *            the macro context.
+	 * @return the StyledText which was current when the recording started or null
+	 *         if there was no StyledText active when recording started.
+	 */
+	public static StyledText getTargetStyledText(IMacroContext macroContext) {
+		if (macroContext != null) {
+			Object object = macroContext.get(TARGET_STYLED_TEXT);
+			if (object instanceof StyledText) {
+				return (StyledText) object;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Gets the editor part which was set as the current when the macro context was
+	 * created.
+	 *
+	 * @param macroContext
+	 *            the macro context.
+	 * @return the editor part which was current when the recording started or null
+	 *         if there was no editor part active when the context was created.
+	 */
+	public static IEditorPart getTargetEditorPart(IMacroContext macroContext) {
+		if (macroContext != null) {
+			Object object = macroContext.get(TARGET_EDITOR_PART);
+			if (object instanceof IEditorPart) {
+				return (IEditorPart) object;
+			}
+		}
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/Messages.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/Messages.java
new file mode 100644
index 0000000..e6c8dcc
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/Messages.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ *
+ */
+public class Messages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.e4.ui.macros.internal.messages"; //$NON-NLS-1$
+	public static String Activator_ErrorMacroRecording;
+	public static String UserNotifications_DontShowAgain;
+	public static String UserNotifications_EditorChangedMessage;
+	public static String UserNotifications_EditorChangedTitle;
+	public static String UserNotifications_FindReplaceDialogMessage;
+	public static String UserNotifications_FindReplaceDialogTitle;
+	public static String UserNotifications_NoEditorForPlaybackMsg;
+	public static String UserNotifications_NoEditorForPlaybackTitle;
+	public static String UserNotifications_NoEditorForRecordMsg;
+	public static String UserNotifications_NoEditorForRecordTitle;
+	static {
+		// initialize resource bundle
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+
+	private Messages() {
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/UserNotifications.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/UserNotifications.java
new file mode 100644
index 0000000..68bfa4c
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/UserNotifications.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.e4.ui.macros.Activator;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.MessageDialogWithToggle;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Helper class to show notifications to the user.
+ */
+public class UserNotifications {
+
+	private static final String FIND_REPLACE_USER_NOTIFICATION_MSG = "FIND_REPLACE_USER_NOTIFICATION_MSG"; //$NON-NLS-1$
+
+	private static final String CURRENT_EDITOR_NOTIFICATION_MSG = "CURRENT_EDITOR_NOTIFICATION_MSG"; //$NON-NLS-1$
+
+	private static final String NO_EDITOR_ON_MACRO_RECORD_STARTUP_NOTIFICATION_MSG = "NO_EDITOR_ON_MACRO_RECORD_STARTUP_NOTIFICATION_MSG"; //$NON-NLS-1$
+
+	/**
+	 * Sets a given message to be shown to the user.
+	 *
+	 * @param message
+	 *            the message to be shown or null to clear it.
+	 */
+	public static void setMessage(String message) {
+		IStatusLineManager statusLineManager = UserNotifications.getStatusLineManager();
+		if (statusLineManager != null) {
+			statusLineManager.setMessage(message);
+			if (message == null) {
+				// Also clear any previous error message we might have set.
+				statusLineManager.setErrorMessage(null);
+			}
+		}
+	}
+
+	/**
+	 * Shows some error message related to the macro to the user.
+	 *
+	 * @param message
+	 *            the error message to be shown (cannot be null).
+	 */
+	public static void showErrorMessage(String message) {
+		Activator plugin = Activator.getDefault();
+		if (plugin != null) {
+			// Log it
+			plugin.getLog().log(new Status(IStatus.INFO, plugin.getBundle().getSymbolicName(), message));
+		}
+
+		// Make it visible to the user.
+		IStatusLineManager statusLineManager = UserNotifications.getStatusLineManager();
+		if (statusLineManager == null) {
+			Shell parent = UserNotifications.getParent();
+			if (parent == null) {
+				System.err.println(Messages.Activator_ErrorMacroRecording + ": " + message); //$NON-NLS-1$
+			} else {
+				MessageDialog.openWarning(parent, Messages.Activator_ErrorMacroRecording, message);
+			}
+		} else {
+			statusLineManager.setErrorMessage(message);
+			Display current = Display.getCurrent();
+			if (current != null) {
+				// Also beep to say something strange happened.
+				current.beep();
+			}
+		}
+	}
+
+	/**
+	 * @return a shell to be used as a dialog's parent.
+	 */
+	private static Shell getParent() {
+		IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+		if (activeWorkbenchWindow == null) {
+			return null;
+		}
+		return activeWorkbenchWindow.getShell();
+	}
+
+	/**
+	 * @return the available status line manager for the current editor.
+	 */
+	private static IStatusLineManager getStatusLineManager() {
+		IWorkbenchWindow activeWorkbenchWindow = EditorUtils.getActivateWorkbenchWindow();
+		if (activeWorkbenchWindow == null) {
+			return null;
+		}
+		IWorkbenchPage activePage = activeWorkbenchWindow.getActivePage();
+		if (activePage == null) {
+			return null;
+		}
+		IEditorPart activeEditor = activePage.getActiveEditor();
+		if (activeEditor == null) {
+			return null;
+		}
+		IEditorSite editorSite = activeEditor.getEditorSite();
+		if (editorSite == null) {
+			return null;
+		}
+		return editorSite.getActionBars().getStatusLineManager();
+	}
+
+	/**
+	 * Show a notification regarding limitations on find/replace.
+	 */
+	public static void notifyFindReplace() {
+		openWarningWithIgnoreToggle(Messages.UserNotifications_FindReplaceDialogTitle,
+				Messages.UserNotifications_FindReplaceDialogMessage, FIND_REPLACE_USER_NOTIFICATION_MSG);
+	}
+
+	/**
+	 * Show a notification regarding limitations on the editor changing.
+	 */
+	public static void notifyCurrentEditor() {
+		openWarningWithIgnoreToggle(Messages.UserNotifications_EditorChangedTitle,
+				Messages.UserNotifications_EditorChangedMessage, CURRENT_EDITOR_NOTIFICATION_MSG);
+	}
+
+	/**
+	 * Show a notification regarding not having an editor opened when record
+	 * started.
+	 */
+	public static void notifyNoEditorOnMacroRecordStartup() {
+		openWarningWithIgnoreToggle(Messages.UserNotifications_NoEditorForRecordTitle,
+				Messages.UserNotifications_NoEditorForRecordMsg, NO_EDITOR_ON_MACRO_RECORD_STARTUP_NOTIFICATION_MSG);
+	}
+
+	/**
+	 * Show a notification regarding not having an editor opened when playback
+	 * started.
+	 */
+	public static void notifyNoEditorOnMacroPlaybackStartup() {
+		openWarningWithIgnoreToggle(Messages.UserNotifications_NoEditorForPlaybackTitle,
+				Messages.UserNotifications_NoEditorForPlaybackMsg, NO_EDITOR_ON_MACRO_RECORD_STARTUP_NOTIFICATION_MSG);
+	}
+
+	private static void openWarningWithIgnoreToggle(String title, String message, String key) {
+		IWorkbenchWindow activateWorkbenchWindow = EditorUtils.getActivateWorkbenchWindow();
+		if (activateWorkbenchWindow == null) {
+			return;
+		}
+		Shell shell = activateWorkbenchWindow.getShell();
+
+		IPreferenceStore store = Activator.getDefault().getPreferenceStore();
+		String val = store.getString(key);
+		if (val.trim().length() == 0) {
+			val = MessageDialogWithToggle.PROMPT; // Initial value if not specified
+		}
+
+		if (!val.equals(MessageDialogWithToggle.ALWAYS)) {
+			MessageDialogWithToggle.openWarning(shell, title, message, Messages.UserNotifications_DontShowAgain, false,
+					store, key);
+		}
+		return;
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/KeepMacroUIUpdated.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/KeepMacroUIUpdated.java
new file mode 100644
index 0000000..2086518
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/KeepMacroUIUpdated.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal.actions;
+
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.e4.core.macros.IMacroInstructionsListener;
+import org.eclipse.e4.core.macros.IMacroStateListener;
+import org.eclipse.e4.ui.macros.internal.UserNotifications;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.ICommandService;
+
+/**
+ * Make sure that the toolbar elements are kept properly updated even if the
+ * macro is programmatically stopped.
+ */
+public class KeepMacroUIUpdated implements IMacroStateListener {
+
+	/**
+	 * A listener which will show messages to the user while he types macro
+	 * instructions.
+	 */
+	private static final class MacroInstructionsListener implements IMacroInstructionsListener {
+		@Override
+		public void beforeMacroInstructionAdded(IMacroInstruction macroInstruction) {
+
+		}
+
+		@Override
+		public void afterMacroInstructionAdded(IMacroInstruction macroInstruction) {
+			UserNotifications.setMessage(Messages.KeepMacroUIUpdated_RecordedInMacro + macroInstruction);
+		}
+	}
+
+	boolean wasRecording = false;
+
+	boolean wasPlayingBack = false;
+
+	IMacroInstructionsListener fMacroInstructionsListener;
+
+	@Override
+	public void macroStateChanged(EMacroService macroService, StateChange stateChange) {
+		// Update the toggle action state.
+		ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class);
+		commandService.refreshElements(ToggleMacroRecordAction.COMMAND_ID, null);
+
+		// Show a message to the user saying about the macro state.
+		if (macroService.isRecording() != wasRecording) {
+			if (!wasRecording) {
+				UserNotifications.setMessage(Messages.KeepMacroUIUpdated_StartMacroRecord);
+			} else {
+				// When we stop the record, clear the message.
+				UserNotifications.setMessage(null);
+			}
+			wasRecording = macroService.isRecording();
+		}
+		if (macroService.isPlayingBack() != wasPlayingBack) {
+			if (!wasPlayingBack) {
+				UserNotifications.setMessage(Messages.KeepMacroUIUpdated_StartMacroPlayback);
+			} else {
+				// When we stop the playback, clear the message.
+				UserNotifications.setMessage(null);
+			}
+			wasPlayingBack = macroService.isPlayingBack();
+		}
+
+		if (macroService.isRecording()) {
+			if (fMacroInstructionsListener == null) {
+				fMacroInstructionsListener = new MacroInstructionsListener();
+				macroService.addMacroInstructionsListener(fMacroInstructionsListener);
+			}
+		} else {
+			if (fMacroInstructionsListener != null) {
+				macroService.removeMacroInstructionsListener(fMacroInstructionsListener);
+				fMacroInstructionsListener = null;
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/MacroPlaybackAction.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/MacroPlaybackAction.java
new file mode 100644
index 0000000..78fd113
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/MacroPlaybackAction.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal.actions;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.e4.core.macros.Activator;
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.core.macros.MacroPlaybackException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Activates the playback of the last macro.
+ */
+public class MacroPlaybackAction extends AbstractHandler {
+
+	@Override
+	public Object execute(ExecutionEvent event) {
+		try {
+			PlatformUI.getWorkbench().getService(EMacroService.class).playbackLastMacro();
+		} catch (MacroPlaybackException e) {
+			Activator.log(e);
+			IWorkbenchWindow activeWorkbenchWindow = HandlerUtil.getActiveWorkbenchWindow(event);
+			if (activeWorkbenchWindow != null) {
+				// When it comes from evaluating JS it adds
+				// "org.eclipse.e4.core.macros.MacroPlaybackException: "
+				// which isn't really interesting to the user (so, just remove that part).
+				String msg = e.getMessage().replace("org.eclipse.e4.core.macros.MacroPlaybackException: ", ""); //$NON-NLS-1$//$NON-NLS-2$
+				MessageDialog.openError(activeWorkbenchWindow.getShell(),
+						Messages.MacroPlaybackAction_ErrorRunningMacro, msg);
+			}
+
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/Messages.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/Messages.java
new file mode 100644
index 0000000..74df082
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/Messages.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal.actions;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ *
+ */
+@SuppressWarnings("javadoc")
+public class Messages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.e4.ui.macros.internal.actions.messages"; //$NON-NLS-1$
+	public static String KeepMacroUIUpdated_RecordedInMacro;
+	public static String KeepMacroUIUpdated_StartMacroRecord;
+	public static String KeepMacroUIUpdated_StartMacroPlayback;
+	public static String MacroPlaybackAction_ErrorRunningMacro;
+	static {
+		// initialize resource bundle
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+
+	private Messages() {
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/ToggleMacroRecordAction.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/ToggleMacroRecordAction.java
new file mode 100644
index 0000000..9cecffb
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/ToggleMacroRecordAction.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal.actions;
+
+import java.util.Map;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.IElementUpdater;
+import org.eclipse.ui.menus.UIElement;
+
+/**
+ * Toggles macro recording.
+ */
+public class ToggleMacroRecordAction extends AbstractHandler implements IElementUpdater {
+
+	/**
+	 * The id of the toggle macro record action.
+	 */
+	public static final String COMMAND_ID = "org.eclipse.e4.ui.macros.toggleRecordMacro"; //$NON-NLS-1$
+
+	@Override
+	public Object execute(ExecutionEvent event) {
+		PlatformUI.getWorkbench().getService(EMacroService.class).toggleMacroRecord();
+		return null;
+	}
+
+	@Override
+	public void updateElement(UIElement element, Map parameters) {
+		element.setChecked(PlatformUI.getWorkbench().getService(EMacroService.class).isRecording());
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/messages.properties b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/messages.properties
new file mode 100644
index 0000000..4566bf7
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/actions/messages.properties
@@ -0,0 +1,4 @@
+KeepMacroUIUpdated_RecordedInMacro=Recorded in macro: 
+KeepMacroUIUpdated_StartMacroRecord=Started macro recording
+KeepMacroUIUpdated_StartMacroPlayback=Start macro playback
+MacroPlaybackAction_ErrorRunningMacro=Error running macro
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/CommandManagerExecutionListener.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/CommandManagerExecutionListener.java
new file mode 100644
index 0000000..ba44a3e
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/CommandManagerExecutionListener.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal.keybindings;
+
+import java.util.Stack;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IExecutionListener;
+import org.eclipse.core.commands.NotHandledException;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.ui.macros.Activator;
+import org.eclipse.e4.ui.macros.internal.EditorUtils;
+import org.eclipse.e4.ui.macros.internal.UserNotifications;
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Used to record commands being executed in the current macro.
+ */
+public class CommandManagerExecutionListener implements IExecutionListener {
+
+	private final EMacroService fMacroService;
+
+	private static class ParameterizedCommandAndTrigger {
+
+		private ParameterizedCommand parameterizedCommand;
+		private Object trigger;
+
+		private ParameterizedCommandAndTrigger(ParameterizedCommand parameterizedCommand, Object trigger) {
+			this.parameterizedCommand = parameterizedCommand;
+			this.trigger = trigger;
+		}
+
+		@Override
+		public String toString() {
+			if (parameterizedCommand == null) {
+				return "parameterizedCommand == null"; //$NON-NLS-1$
+			}
+			return parameterizedCommand.getId();
+		}
+	}
+
+	/**
+	 * A stack to keep information on the parameterized commands and what triggered
+	 * it.
+	 */
+	private final Stack<ParameterizedCommandAndTrigger> fParameterizedCommandsAndTriggerStack = new Stack<>();
+
+	/**
+	 * The handler service.
+	 */
+	private final EHandlerService fHandlerService;
+
+	/**
+	 * @param macroService
+	 *            the macro service
+	 * @param handlerService
+	 *            the handler service (used to execute actions).
+	 */
+	public CommandManagerExecutionListener(EMacroService macroService, EHandlerService handlerService) {
+		this.fMacroService = macroService;
+		this.fHandlerService = handlerService;
+	}
+
+	@Override
+	public void notHandled(String commandId, NotHandledException exception) {
+		popCommand(commandId);
+	}
+
+	@Override
+	public void postExecuteFailure(String commandId, ExecutionException exception) {
+		popCommand(commandId);
+	}
+
+	private ParameterizedCommandAndTrigger popCommand(String commandId) {
+		ParameterizedCommandAndTrigger commandAndTrigger = null;
+		while (!fParameterizedCommandsAndTriggerStack.empty()) {
+			commandAndTrigger = fParameterizedCommandsAndTriggerStack.pop();
+			if (commandAndTrigger != null && commandAndTrigger.parameterizedCommand != null) {
+				if (commandId.equals(commandAndTrigger.parameterizedCommand.getCommand().getId())) {
+					return commandAndTrigger;
+				}
+			}
+		}
+		if (commandAndTrigger != null) {
+			Activator.log(new RuntimeException(
+					String.format("Expected to find %s in parameterizedCommand stack. Found: %s", commandId, //$NON-NLS-1$
+							commandAndTrigger)));
+		}
+		return null;
+	}
+
+	@Override
+	public void postExecuteSuccess(String commandId, Object returnValue) {
+		ParameterizedCommandAndTrigger commandAndTrigger = popCommand(commandId);
+		if (commandAndTrigger == null) {
+			// Can happen if we didn't get the preExecute (i.e.: the toggle
+			// macro record is executed and post executed only (the pre execute
+			// is skipped because recording still wasn't in place).
+			//
+			// Another reason could be that it was an event generated for another
+			// editor, not the one we should recording.
+			return;
+		}
+		if (fMacroService.isRecording()) {
+			// Record it if needed.
+			if (fMacroService.getRecordCommandInMacro(commandId)) {
+				if (commandAndTrigger.trigger instanceof Event) {
+					Event swtEvent = (Event) commandAndTrigger.trigger;
+					// Only record commands executed in the initial editor.
+					if (fFilter.acceptEvent(swtEvent)) {
+						fMacroService.addMacroInstruction(new MacroInstructionForParameterizedCommand(
+								commandAndTrigger.parameterizedCommand, swtEvent, this.fHandlerService));
+					}
+				} else {
+					fMacroService.addMacroInstruction(new MacroInstructionForParameterizedCommand(
+							commandAndTrigger.parameterizedCommand, this.fHandlerService));
+				}
+			}
+		}
+	}
+
+	@Override
+	public void preExecute(String commandId, ExecutionEvent event) {
+		if (acceptEvent(event)) {
+			if ("org.eclipse.ui.edit.findReplace".equals(commandId)) { //$NON-NLS-1$
+				// We can't deal with find/replace at this point. Let the user know.
+				UserNotifications.notifyFindReplace();
+			}
+		}
+		// Let's check if it should actually be recorded.
+		if (fMacroService.getRecordCommandInMacro(commandId)) {
+			if (!acceptEvent(event)) {
+				fParameterizedCommandsAndTriggerStack.add(null);
+				return;
+			}
+			ParameterizedCommand command = ParameterizedCommand.generateCommand(event.getCommand(),
+					event.getParameters());
+			fParameterizedCommandsAndTriggerStack.add(new ParameterizedCommandAndTrigger(command, event.getTrigger()));
+		}
+	}
+
+	/**
+	 * Filter to accept or reject an event (accepting means we can generate a macro
+	 * instruction for it and false means we shouldn't).
+	 */
+	public static interface IFilter {
+
+		/**
+		 * @param swtEvent
+		 * @return true if the given swtEvent should be accepted.
+		 */
+		boolean acceptEvent(Event swtEvent);
+	}
+
+	private boolean acceptEvent(ExecutionEvent event) {
+		Object trigger = event.getTrigger();
+		if (trigger instanceof Event) {
+			Event swtEvent = (Event) trigger;
+			return fFilter.acceptEvent(swtEvent);
+		}
+		return true;
+	}
+
+	/**
+	 * Note that it's private and shouldn't be usually changed, although the current
+	 * structure is helpful as it allows us to accept any event on tests through
+	 * reflection.
+	 */
+	private IFilter fFilter = new IFilter() {
+
+		@Override
+		public boolean acceptEvent(Event swtEvent) {
+			if (EditorUtils.getActiveStyledText() != EditorUtils
+					.getTargetStyledText(fMacroService.getMacroRecordContext())) {
+				// Note: it previously checked swtEvent.widget, but sometimes the event was
+				// generated from the wrong control (i.e.: opening a new editor and doing
+				// some action sometimes had the widget from a different editor).
+				return false;
+			}
+			return true;
+		}
+	};
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/CommandManagerExecutionListenerInstaller.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/CommandManagerExecutionListenerInstaller.java
new file mode 100644
index 0000000..073654f
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/CommandManagerExecutionListenerInstaller.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal.keybindings;
+
+import javax.inject.Inject;
+import org.eclipse.core.commands.CommandManager;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+import org.eclipse.e4.core.macros.IMacroRecordContext;
+import org.eclipse.e4.core.macros.IMacroStateListener;
+import org.eclipse.e4.core.macros.IMacroStateListener1;
+import org.eclipse.e4.ui.macros.internal.EditorUtils;
+
+/**
+ * A macro state listener that will install the execution listener when in a
+ * record context.
+ */
+public class CommandManagerExecutionListenerInstaller implements IMacroStateListener, IMacroStateListener1 {
+
+	@Inject
+	private CommandManager fCommandManager;
+
+	@Inject
+	private EHandlerService fHandlerService;
+
+	private CommandManagerExecutionListener fCommandManagerExecutionListener;
+
+	public CommandManagerExecutionListener getCommandManagerExecutionListener() {
+		return fCommandManagerExecutionListener;
+	}
+
+	@Override
+	public void macroStateChanged(EMacroService macroService, StateChange stateChange) {
+		if (macroService.isRecording()) {
+			if (fCommandManagerExecutionListener == null) {
+				fCommandManagerExecutionListener = new CommandManagerExecutionListener(macroService, fHandlerService);
+				fCommandManager.addExecutionListener(fCommandManagerExecutionListener);
+			}
+		} else {
+			if (fCommandManagerExecutionListener != null) {
+				fCommandManager.removeExecutionListener(fCommandManagerExecutionListener);
+				fCommandManagerExecutionListener = null;
+			}
+		}
+	}
+
+	@Override
+	public void onMacroPlaybackContextCreated(IMacroPlaybackContext macroContext) {
+		EditorUtils.cacheTargetStyledText(macroContext);
+	}
+
+	@Override
+	public void onMacroRecordContextCreated(IMacroRecordContext macroContext) {
+		EditorUtils.cacheTargetStyledText(macroContext);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/MacroInstructionForParameterizedCommand.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/MacroInstructionForParameterizedCommand.java
new file mode 100644
index 0000000..1cc0213
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/MacroInstructionForParameterizedCommand.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal.keybindings;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.CommandManager;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.commands.internal.HandlerServiceImpl;
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.macros.Activator;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+import org.eclipse.e4.core.macros.MacroPlaybackException;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * A macro instruction for parameterized commands.
+ */
+public class MacroInstructionForParameterizedCommand implements IMacroInstruction {
+
+	private static final String ID = "Command"; //$NON-NLS-1$
+
+	private static final String CHARACTER = "character"; //$NON-NLS-1$
+
+	private static final String TYPE = "type"; //$NON-NLS-1$
+
+	private static final String STATE_MASK = "stateMask"; //$NON-NLS-1$
+
+	private static final String KEY_CODE = "keyCode"; //$NON-NLS-1$
+
+	private static final String COMMAND = "command"; //$NON-NLS-1$
+
+	private static final String NO_EVENT = "no_event"; //$NON-NLS-1$
+
+	private EHandlerService fHandlerService;
+
+	private ParameterizedCommand fCmd;
+
+	private Event fEvent;
+
+	public MacroInstructionForParameterizedCommand(ParameterizedCommand cmd, EHandlerService handlerService) {
+		this.fCmd = cmd;
+		this.fHandlerService = handlerService;
+	}
+
+	/**
+	 * @param cmd
+	 *            the command recorded.
+	 * @param event
+	 *            the related event.
+	 * @param keybindingDispatcher
+	 *            the dispatcher to be used to execute commands.
+	 */
+	public MacroInstructionForParameterizedCommand(ParameterizedCommand cmd, Event event,
+			EHandlerService keybindingDispatcher) {
+		this(cmd, keybindingDispatcher);
+
+		// Create a new event (we want to make sure that only the given info is
+		// really needed on playback and don't want to keep a reference to the
+		// original widget).
+		Event newEvent = new Event();
+		newEvent.keyCode = event.keyCode;
+		newEvent.stateMask = event.stateMask;
+		newEvent.type = event.type;
+		newEvent.character = event.character;
+
+		this.fEvent = newEvent;
+	}
+
+	@Override
+	public void execute(IMacroPlaybackContext macroPlaybackContext) throws MacroPlaybackException {
+		ParameterizedCommand cmd = fCmd;
+		if (cmd == null) {
+			throw new MacroPlaybackException("Parameterized command not set."); //$NON-NLS-1$
+		}
+		final EHandlerService handlerService = fHandlerService;
+		final Command command = cmd.getCommand();
+
+		final IEclipseContext staticContext = EclipseContextFactory.create("keys-staticContext"); //$NON-NLS-1$
+		staticContext.set(Event.class, this.fEvent);
+
+		if (!command.isDefined()) {
+			throw new MacroPlaybackException(
+					String.format("Command: %s not defined (unable to playback macro).", cmd.getId())); //$NON-NLS-1$
+		}
+
+		try {
+			boolean commandEnabled = handlerService.canExecute(cmd, staticContext);
+			if (!commandEnabled) {
+				// This is to handle the following case:
+				// 1. Open an editor and record keypresses and an undo
+				// 2. Close editor/Open editor
+				// 3. Playback macro: at this point, the undo action is actually
+				// disabled, so, we need to process the current events in the
+				// queue and wait for it to be enabled (or fail if it can't be
+				// enabled in the current situation).
+				for (int i = 0; i < 100; i++) {
+					Display.getCurrent().readAndDispatch();
+					commandEnabled = handlerService.canExecute(cmd, staticContext);
+					if (commandEnabled) {
+						break;
+					}
+				}
+				commandEnabled = handlerService.canExecute(cmd, staticContext);
+				if (!commandEnabled) {
+					String name;
+					try {
+						name = cmd.getName();
+					} catch (NotDefinedException e) {
+						name = Messages.MacroInstructionForParameterizedCommand_CommandUnknown;
+					}
+					throw new MacroPlaybackException(
+							String.format(Messages.MacroInstructionForParameterizedCommand_CommandNotEnabled, name, cmd.getId()));
+				}
+			}
+
+			handlerService.executeHandler(cmd, staticContext);
+			final Object commandException = staticContext.get(HandlerServiceImpl.HANDLER_EXCEPTION);
+			if (commandException instanceof Exception) {
+				Activator.log((Exception) commandException);
+			}
+
+		} finally {
+			staticContext.dispose();
+		}
+	}
+
+	@Override
+	public String getId() {
+		return ID;
+	}
+
+	@Override
+	public String toString() {
+		try {
+			return String.format(Messages.MacroInstructionForParameterizedCommand_0, this.fCmd.getName());
+		} catch (NotDefinedException e) {
+			return String.format(Messages.MacroInstructionForParameterizedCommand_0, "Undefined"); //$NON-NLS-1$
+		}
+	}
+
+	@Override
+	public Map<String, String> toMap() {
+		Map<String, String> map = new HashMap<>();
+		String serialized = fCmd.serialize();
+		Assert.isNotNull(serialized);
+		map.put(COMMAND, serialized);
+		if (this.fEvent == null) {
+			map.put(NO_EVENT, NO_EVENT);
+		}
+		map.put(KEY_CODE, Integer.toString(fEvent.keyCode));
+		map.put(STATE_MASK, Integer.toString(fEvent.stateMask));
+		map.put(TYPE, Integer.toString(fEvent.type));
+		map.put(CHARACTER, Character.toString(fEvent.character));
+
+		return map;
+	}
+
+	/**
+	 * @param map
+	 *            a map (created from {@link #toMap()}.
+	 * @param commandManager
+	 *            the command manager used to deserialize commands.
+	 * @param keybindingDispatcher
+	 *            the dispatcher for commands.
+	 * @return a macro instruction created from the map (created from
+	 *         {@link #toMap()}.
+	 * @throws Exception
+	 *             if it was not possible to recreate the macro instruction.
+	 */
+	/* default */ static MacroInstructionForParameterizedCommand fromMap(Map<String, String> map,
+			CommandManager commandManager, EHandlerService keybindingDispatcher) throws Exception {
+		Assert.isNotNull(commandManager);
+		Assert.isNotNull(map);
+		Assert.isNotNull(keybindingDispatcher);
+		ParameterizedCommand cmd = commandManager.deserialize(map.get(COMMAND));
+		if (map.containsKey(NO_EVENT)) {
+			return new MacroInstructionForParameterizedCommand(cmd, keybindingDispatcher);
+		}
+		Event event = new Event();
+		event.keyCode = Integer.parseInt(map.get(KEY_CODE));
+		event.stateMask = Integer.parseInt(map.get(STATE_MASK));
+		event.type = Integer.parseInt(map.get(TYPE));
+		event.character = map.get(CHARACTER).charAt(0);
+		return new MacroInstructionForParameterizedCommand(cmd, event, keybindingDispatcher);
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/MacroInstructionForParameterizedCommandFactory.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/MacroInstructionForParameterizedCommandFactory.java
new file mode 100644
index 0000000..32ceb91
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/MacroInstructionForParameterizedCommandFactory.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal.keybindings;
+
+import java.util.Map;
+import javax.inject.Inject;
+import org.eclipse.core.commands.CommandManager;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.e4.core.macros.IMacroInstructionFactory;
+
+/**
+ * Factory for macro instructions which were created from parameterized
+ * commands.
+ */
+public class MacroInstructionForParameterizedCommandFactory implements IMacroInstructionFactory {
+
+	@Inject
+	private CommandManager fCommandManager;
+
+	@Inject
+	private EHandlerService fHandlerService;
+
+	@Override
+	public IMacroInstruction create(Map<String, String> stringMap) throws Exception {
+		return MacroInstructionForParameterizedCommand.fromMap(stringMap, fCommandManager, fHandlerService);
+	}
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/Messages.java b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/Messages.java
new file mode 100644
index 0000000..0c3c5b8
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/Messages.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.internal.keybindings;
+
+import org.eclipse.osgi.util.NLS;
+
+@SuppressWarnings("javadoc")
+public class Messages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.e4.ui.macros.internal.keybindings.messages"; //$NON-NLS-1$
+
+	public static String CommandManagerExecutionListener_CommandNotRecorded;
+
+	public static String KeyBindingDispatcherInterceptor_SkipExecutionOfCommand;
+
+	public static String MacroInstructionForParameterizedCommand_0;
+
+	public static String MacroInstructionForParameterizedCommand_CommandNotEnabled;
+
+	public static String MacroInstructionForParameterizedCommand_CommandUnknown;
+
+	static {
+		// initialize resource bundle
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+
+	private Messages() {
+	}
+}
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/messages.properties b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/messages.properties
new file mode 100644
index 0000000..6991310
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/keybindings/messages.properties
@@ -0,0 +1,5 @@
+CommandManagerExecutionListener_CommandNotRecorded=Command %s executed but not recorded in macro.
+KeyBindingDispatcherInterceptor_SkipExecutionOfCommand=Stopped execution of command not whitelisted in macro: %s
+MacroInstructionForParameterizedCommand_0=Command: %s
+MacroInstructionForParameterizedCommand_CommandNotEnabled=Command "%s" (%s) not enabled.
+MacroInstructionForParameterizedCommand_CommandUnknown=Unknown
diff --git a/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/messages.properties b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/messages.properties
new file mode 100644
index 0000000..418b199
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.macros/src/org/eclipse/e4/ui/macros/internal/messages.properties
@@ -0,0 +1,10 @@
+Activator_ErrorMacroRecording=Error macro recording
+UserNotifications_DontShowAgain=Don't show this message again
+UserNotifications_EditorChangedMessage=Macro recording currently is limited to the editor which was active when macro recording started.\n\nActions done in other editors or contexts will not be recorded.
+UserNotifications_EditorChangedTitle=Editor Changed
+UserNotifications_FindReplaceDialogMessage=Macro recording is currently not integrated with the find/replace dialog.\n\nPlease use the find next and the incremental find actions through keybindings in the editor as a workaround.
+UserNotifications_FindReplaceDialogTitle=Find Replace Dialog
+UserNotifications_NoEditorForPlaybackMsg=Macro playback currently only works within the scope of a text editor. As no text editor was found to be active, no playback will take place.
+UserNotifications_NoEditorForPlaybackTitle=No Editor for Playback
+UserNotifications_NoEditorForRecordMsg=Macro recording currently only works within the scope of a text editor. As no text editor was found to be active, no actions will be recorded.
+UserNotifications_NoEditorForRecordTitle=No Editor for Record
diff --git a/bundles/org.eclipse.e4.ui.macros.jdt/.classpath b/bundles/org.eclipse.ui.workbench.texteditor.macros/.classpath
similarity index 100%
rename from bundles/org.eclipse.e4.ui.macros.jdt/.classpath
rename to bundles/org.eclipse.ui.workbench.texteditor.macros/.classpath
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/.gitignore b/bundles/org.eclipse.ui.workbench.texteditor.macros/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/bundles/org.eclipse.e4.ui.macros.jdt/.project b/bundles/org.eclipse.ui.workbench.texteditor.macros/.project
similarity index 63%
copy from bundles/org.eclipse.e4.ui.macros.jdt/.project
copy to bundles/org.eclipse.ui.workbench.texteditor.macros/.project
index 4babb46..8ff43ac 100644
--- a/bundles/org.eclipse.e4.ui.macros.jdt/.project
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/.project
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-	<name>org.eclipse.e4.ui.macros.jdt</name>
+	<name>org.eclipse.ui.workbench.texteditor.macros</name>
 	<comment></comment>
 	<projects>
 	</projects>
@@ -20,9 +20,20 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ds.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
 		<nature>org.eclipse.pde.PluginNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
 	</natures>
 </projectDescription>
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..5a0ad22
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0566737
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,419 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=error
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..b058cde
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,125 @@
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=true
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_methods=false
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_missing_override_annotations_interface_methods=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=false
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.correct_indentation=false
+cleanup.format_source_code=false
+cleanup.format_source_code_changes_only=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_type_abstract_if_missing_method=false
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=true
+cleanup.organize_imports=false
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=false
+cleanup.remove_trailing_whitespaces_all=true
+cleanup.remove_trailing_whitespaces_ignore_empty=false
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=false
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment"/><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=true
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..a09ec9c
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,97 @@
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Warning
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Error
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..2ce5047
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,32 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=1
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.internal=1
+compilers.p.missing-packages=1
+compilers.p.missing-version-export-package=2
+compilers.p.missing-version-import-package=1
+compilers.p.missing-version-require-bundle=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=1
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.workbench.texteditor.macros/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..a4a1104
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/META-INF/MANIFEST.MF
@@ -0,0 +1,25 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Macros for text editors
+Bundle-SymbolicName: org.eclipse.ui.workbench.texteditor.macros;singleton:=true
+Bundle-Version: 0.1.0.qualifier
+Bundle-Activator: org.eclipse.ui.workbench.texteditor.macros.Activator
+Bundle-Vendor: Eclipse.org
+Require-Bundle: org.eclipse.e4.ui.bindings;bundle-version="0.10",
+ org.eclipse.e4.ui.macros;bundle-version="0.1",
+ org.eclipse.ui.workbench;bundle-version="3.108",
+ org.eclipse.e4.core.macros,
+ org.eclipse.swt,
+ org.eclipse.osgi,
+ org.eclipse.jface.text,
+ org.eclipse.ui.workbench.texteditor,
+ org.eclipse.jface;bundle-version="3.13.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Import-Package: javax.inject,
+ org.eclipse.core.runtime;version="3.5",
+ org.eclipse.e4.core.commands,
+ org.eclipse.e4.core.contexts,
+ org.eclipse.e4.core.di,
+ org.eclipse.e4.core.di.annotations,
+ org.osgi.framework;version="1.8"
+Bundle-ActivationPolicy: lazy
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/build.properties b/bundles/org.eclipse.ui.workbench.texteditor.macros/build.properties
new file mode 100644
index 0000000..163cdac
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/build.properties
@@ -0,0 +1,6 @@
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml,\
+               OSGI-INF/
+source.. = src/
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/plugin.xml b/bundles/org.eclipse.ui.workbench.texteditor.macros/plugin.xml
new file mode 100644
index 0000000..1e01cef
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/plugin.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin>
+
+   <extension
+         point="org.eclipse.e4.core.macros.macroStateListeners">
+      <macroStateListener
+            class="org.eclipse.ui.workbench.texteditor.macros.internal.EditorPartMacroInstaller">
+      </macroStateListener>
+      <macroStateListener
+            class="org.eclipse.ui.workbench.texteditor.macros.internal.MacroStyledTextInstaller">
+      </macroStateListener>
+   </extension>
+
+   <extension
+         point="org.eclipse.e4.core.macros.macroInstructionsFactory">
+      <macroInstructionsFactory
+            class="org.eclipse.ui.workbench.texteditor.macros.internal.StyledTextKeyDownMacroInstructionFactory"
+            macroInstructionId="KeyEvent">
+      </macroInstructionsFactory>
+   </extension>
+
+   <extension point="org.eclipse.e4.core.macros.macroCommandCustomization">
+      <customizedCommand id="org.eclipse.ui.edit.text.contentAssist.proposals" recordMacroInstruction="false"/>
+      <customizedCommand id="org.eclipse.ui.edit.text.quick_assist.proposals" recordMacroInstruction="false"/>
+   </extension>
+
+</plugin>
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/pom.xml b/bundles/org.eclipse.ui.workbench.texteditor.macros/pom.xml
new file mode 100644
index 0000000..e21249c
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2017 Fabio Zadrozny and others.
+  All rights reserved. This program and the accompanying materials
+  are made available under the terms of the Eclipse Distribution License v1.0
+  which accompanies this distribution, and is available at
+  http://www.eclipse.org/org/documents/edl-v10.php
+
+  Contributors:
+     Fabio Zadrozny - initial implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.e4.ui</groupId>
+    <artifactId>e4-ui-aggregator</artifactId>
+    <version>0.17.0-SNAPSHOT</version>
+    <relativePath>../../</relativePath>
+  </parent>
+
+  <artifactId>org.eclipse.ui.workbench.texteditor.macros</artifactId>
+  <version>0.1.0-SNAPSHOT</version>
+  <packaging>eclipse-plugin</packaging>
+
+ </project>
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/Activator.java b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/Activator.java
new file mode 100644
index 0000000..830103c
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/Activator.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.ui.workbench.texteditor.macros;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+@SuppressWarnings("javadoc")
+public class Activator extends AbstractUIPlugin {
+
+	private static Activator plugin;
+
+	public Activator() {
+		super();
+		plugin = this;
+	}
+
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/AbstractSWTEventMacroInstruction.java b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/AbstractSWTEventMacroInstruction.java
new file mode 100644
index 0000000..b9f89a2
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/AbstractSWTEventMacroInstruction.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.ui.workbench.texteditor.macros.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Base class for a macro instruction based on events from a given type.
+ *
+ * Note that it doesn't store all the information on events, only character,
+ * stateMask, keyCode, keyLocation and detail (and the actual type is meant to
+ * be gotten from the class which overrides it or passed when needed).
+ *
+ * The actual fields that it stores may grow over time (and when restored, if
+ * those weren't properly saved, default values should be used).
+ */
+public abstract class AbstractSWTEventMacroInstruction implements IMacroInstruction {
+
+	private static final String CHARACTER = "character"; //$NON-NLS-1$
+
+	private static final String STATE_MASK = "stateMask"; //$NON-NLS-1$
+
+	private static final String KEY_CODE = "keyCode"; //$NON-NLS-1$
+
+	private static final String DETAIL = "detail"; //$NON-NLS-1$
+
+	private static final String KEY_LOCATION = "keyLocation"; //$NON-NLS-1$
+
+	protected final Event fEvent;
+
+	/**
+	 * @param event
+	 *            the event for which the macro instruction is being created.
+	 */
+	public AbstractSWTEventMacroInstruction(Event event) {
+		// Create a new event (we want to make sure that only the given info is
+		// really needed on playback and don't want to keep a reference to the
+		// original widget).
+		Assert.isTrue(event.type == getEventType());
+		Event newEvent = copyEvent(event);
+
+		this.fEvent = newEvent;
+	}
+
+	/**
+	 *
+	 * @return the event type of the events that this macro instruction is related
+	 *         to.
+	 */
+	protected abstract int getEventType();
+
+	/**
+	 * Helper to create a copy of some event.
+	 *
+	 * @param event
+	 *            the event to be copied.
+	 * @return a copy of the passed event.
+	 */
+	protected Event copyEvent(Event event) {
+		Event newEvent = new Event();
+		newEvent.keyCode = event.keyCode;
+		newEvent.stateMask = event.stateMask;
+		newEvent.type = event.type;
+		newEvent.character = event.character;
+		newEvent.detail = event.detail;
+		newEvent.keyLocation = event.keyLocation;
+		return newEvent;
+	}
+
+	/**
+	 * Actually creates an event based on the contents previously gotten from
+	 * {@link #toMap()}.
+	 */
+	protected static Event createEventFromMap(Map<String, String> map, int eventType) {
+		Event event = new Event();
+		event.type = eventType;
+
+		String keyCode = map.get(KEY_CODE);
+		if (keyCode != null) {
+			event.keyCode = Integer.parseInt(keyCode);
+		} else {
+			event.keyCode = 0;
+		}
+
+		String stateMask = map.get(STATE_MASK);
+		if (stateMask != null) {
+			event.stateMask = Integer.parseInt(stateMask);
+		} else {
+			event.stateMask = 0;
+		}
+
+		String character = map.get(CHARACTER);
+		if (character != null) {
+			event.character = character.charAt(0);
+		} else {
+			event.character = '\0';
+		}
+
+		String detail = map.get(DETAIL);
+		if (detail != null) {
+			event.detail = Integer.parseInt(detail);
+		} else {
+			event.detail = 0;
+		}
+
+		String keyLocation = map.get(KEY_LOCATION);
+		if (keyLocation != null) {
+			event.keyLocation = Integer.parseInt(keyLocation);
+		} else {
+			event.keyLocation = 0;
+		}
+		return event;
+	}
+
+	@Override
+	public Map<String, String> toMap() {
+		Map<String, String> map = new HashMap<>();
+
+		// Only save non-default values.
+
+		if (fEvent.keyCode != 0) {
+			map.put(KEY_CODE, Integer.toString(fEvent.keyCode));
+		}
+
+		if (fEvent.stateMask != 0) {
+			map.put(STATE_MASK, Integer.toString(fEvent.stateMask));
+		}
+
+		if (fEvent.character != '\0') {
+			map.put(CHARACTER, Character.toString(fEvent.character));
+		}
+
+		if (fEvent.detail != 0) {
+			map.put(DETAIL, Integer.toString(fEvent.detail));
+		}
+
+		if (fEvent.keyLocation != 0) {
+			map.put(KEY_LOCATION, Integer.toString(fEvent.keyLocation));
+		}
+		return map;
+	}
+
+}
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/EditorPartMacroInstaller.java b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/EditorPartMacroInstaller.java
new file mode 100644
index 0000000..885d589
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/EditorPartMacroInstaller.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.ui.workbench.texteditor.macros.internal;
+
+import org.eclipse.e4.core.macros.CancelMacroException;
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.core.macros.IMacroRecordContext;
+import org.eclipse.e4.core.macros.IMacroStateListener;
+
+/**
+ * A listener to the macro context which will enable notifications to the user
+ * regarding limitations of recording only in the current editor.
+ */
+public class EditorPartMacroInstaller implements IMacroStateListener {
+
+	private static final String NOTIFY_MACRO_ONLY_IN_CURRENT_EDITOR = "NOTIFY_MACRO_ONLY_IN_CURRENT_EDITOR"; //$NON-NLS-1$
+
+	@Override
+	public void macroStateChanged(EMacroService macroService, StateChange stateChange)
+			throws CancelMacroException {
+		if (stateChange == StateChange.RECORD_STARTED) {
+			IMacroRecordContext context = macroService.getMacroRecordContext();
+			NotifyMacroOnlyInCurrentEditor notifyMacroOnlyInCurrentEditor = new NotifyMacroOnlyInCurrentEditor(
+					macroService);
+			notifyMacroOnlyInCurrentEditor.checkEditorActiveForMacroRecording();
+
+			notifyMacroOnlyInCurrentEditor.install();
+			context.set(NOTIFY_MACRO_ONLY_IN_CURRENT_EDITOR, notifyMacroOnlyInCurrentEditor);
+
+		} else if (stateChange == StateChange.RECORD_FINISHED) {
+			IMacroRecordContext context = macroService.getMacroRecordContext();
+			Object object = context.get(NOTIFY_MACRO_ONLY_IN_CURRENT_EDITOR);
+			if (object instanceof NotifyMacroOnlyInCurrentEditor) {
+				NotifyMacroOnlyInCurrentEditor notifyMacroOnlyInCurrentEditor = (NotifyMacroOnlyInCurrentEditor) object;
+				notifyMacroOnlyInCurrentEditor.uninstall();
+			}
+		} else if (stateChange == StateChange.PLAYBACK_STARTED) {
+			new NotifyMacroOnlyInCurrentEditor(macroService).checkEditorActiveForMacroPlayback();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/MacroStyledTextInstaller.java b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/MacroStyledTextInstaller.java
new file mode 100644
index 0000000..d4e9e05
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/MacroStyledTextInstaller.java
@@ -0,0 +1,287 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.ui.workbench.texteditor.macros.internal;
+
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.core.macros.IMacroContext;
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+import org.eclipse.e4.core.macros.IMacroRecordContext;
+import org.eclipse.e4.core.macros.IMacroStateListener;
+import org.eclipse.e4.core.macros.IMacroStateListener1;
+import org.eclipse.e4.ui.macros.internal.EditorUtils;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.ITextOperationTargetExtension;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.XMLMemento;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.ITextEditorExtension5;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+/**
+ * Helper class to deal with entering/exiting macro record/playback.
+ */
+public class MacroStyledTextInstaller implements IMacroStateListener, IMacroStateListener1 {
+
+	/**
+	 * Constant used to keep memento on the macro context.
+	 */
+	private static final String MACRO_STYLED_TEXT_INSTALLER_MEMENTO = "MACRO_STYLED_TEXT_INSTALLER_MEMENTO"; //$NON-NLS-1$
+
+	/**
+	 * Constant used to keep macro recorder on the macro context.
+	 */
+	private static final String MACRO_STYLED_TEXT_INSTALLER_MACRO_RECORDER = "MACRO_STYLED_TEXT_INSTALLER_MACRO_RECORDER"; //$NON-NLS-1$
+
+	/**
+	 * Constant used to save whether the content assist was enabled before being
+	 * disabled in disableCodeCompletion.
+	 */
+	private static final String CONTENT_ASSIST_ENABLED = "contentAssistEnabled";//$NON-NLS-1$
+
+	/**
+	 * Constant used to save whether the quick assist was enabled before being
+	 * disabled in disableCodeCompletion.
+	 */
+	private static final String QUICK_ASSIST_ENABLED = "quickAssistEnabled";//$NON-NLS-1$
+
+	/**
+	 * Re-enables the content assist based on the state of the key
+	 * {@link #CONTENT_ASSIST_ENABLED} in the passed memento.
+	 *
+	 * @param memento
+	 *            the memento where a key with {@link #CONTENT_ASSIST_ENABLED} with
+	 *            the enabled state of the content assist to be restored.
+	 */
+	private void leaveMacroMode(IMemento memento, IMacroContext context) {
+		IEditorPart editorPart = EditorUtils.getTargetEditorPart(context);
+		if (editorPart != null) {
+			ITextOperationTarget textOperationTarget = editorPart.getAdapter(ITextOperationTarget.class);
+			if (textOperationTarget instanceof ITextOperationTargetExtension) {
+				ITextOperationTargetExtension targetExtension = (ITextOperationTargetExtension) textOperationTarget;
+				if (textOperationTarget instanceof ITextOperationTargetExtension) {
+					restore(memento, targetExtension, ISourceViewer.CONTENTASSIST_PROPOSALS, CONTENT_ASSIST_ENABLED);
+					restore(memento, targetExtension, ISourceViewer.QUICK_ASSIST, QUICK_ASSIST_ENABLED);
+				}
+			}
+
+			if (editorPart instanceof ITextEditor) {
+				ITextEditor textEditor = (ITextEditor) editorPart;
+				restore(memento, textEditor, ITextEditorActionConstants.CONTENT_ASSIST);
+				restore(memento, textEditor, ITextEditorActionConstants.QUICK_ASSIST);
+				restore(memento, textEditor, ITextEditorActionConstants.BLOCK_SELECTION_MODE);
+			}
+		}
+
+	}
+
+	/**
+	 * Disables the content assist and saves the previous state on the passed
+	 * memento (note that it's only saved if it is actually disabled here).
+	 *
+	 * @param memento
+	 *            memento where the previous state should be saved, to be properly
+	 *            restored later on in {@link #leaveMacroMode(IMemento)}.
+	 */
+	private void enterMacroMode(IMemento memento, IMacroContext context) {
+		IEditorPart editorPart = EditorUtils.getTargetEditorPart(context);
+		if (editorPart instanceof ITextEditorExtension5) {
+			ITextEditorExtension5 iTextEditorExtension5 = (ITextEditorExtension5) editorPart;
+			if (iTextEditorExtension5.isBlockSelectionModeEnabled()) {
+				// Note: macro can't deal with block selections... there's nothing really
+				// inherent to not being able to work, but given:
+				// org.eclipse.jface.text.TextViewer.verifyEventInBlockSelection(VerifyEvent)
+				// and the fact that we don't generate events through the Display (because it's
+				// too error prone -- so much that it could target the wrong IDE instance for
+				// the events because it deals with system messages and not really events
+				// inside the IDE) and the fact that we can't force a new system message time
+				// for temporary events created internally, makes it really hard to work
+				// around the hack in verifyEventInBlockSelection.
+				// So, we simply disable block selection mode as well as the action which would
+				// activate it.
+
+				// Note: ideally we'd have a way to set a new time for the time returned in
+				// org.eclipse.swt.widgets.Display.getLastEventTime()
+				// -- as it is, internally the events time will be always the same because
+				// there's no API to reset it -- if possible we should reset it when we
+				// generate our internal events at:
+				// org.eclipse.ui.workbench.texteditor.macros.internal.StyledTextKeyDownMacroInstruction.execute(IMacroPlaybackContext)
+				iTextEditorExtension5.setBlockSelectionMode(false);
+			}
+		}
+
+		if (editorPart instanceof ITextEditor) {
+			ITextEditor textEditor = (ITextEditor) editorPart;
+			disable(memento, textEditor, ITextEditorActionConstants.CONTENT_ASSIST);
+			disable(memento, textEditor, ITextEditorActionConstants.QUICK_ASSIST);
+			disable(memento, textEditor, ITextEditorActionConstants.BLOCK_SELECTION_MODE);
+		}
+
+		if (editorPart != null) {
+			ITextOperationTarget textOperationTarget = editorPart.getAdapter(ITextOperationTarget.class);
+			if (textOperationTarget instanceof ITextOperationTargetExtension) {
+				ITextOperationTargetExtension targetExtension = (ITextOperationTargetExtension) textOperationTarget;
+
+				// Disable content assist and mark it to be restored later on
+				disable(memento, textOperationTarget, targetExtension, ISourceViewer.CONTENTASSIST_PROPOSALS,
+						CONTENT_ASSIST_ENABLED);
+				disable(memento, textOperationTarget, targetExtension, ISourceViewer.QUICK_ASSIST,
+						QUICK_ASSIST_ENABLED);
+			}
+		}
+	}
+
+	private void restore(IMemento memento, ITextOperationTargetExtension targetExtension, int operation,
+			String preference) {
+		Boolean contentAssistProposalsBeforMacroMode = memento.getBoolean(preference);
+		if (contentAssistProposalsBeforMacroMode != null) {
+			if ((contentAssistProposalsBeforMacroMode).booleanValue()) {
+				targetExtension.enableOperation(operation, true);
+			} else {
+				targetExtension.enableOperation(operation, false);
+			}
+		}
+	}
+
+	private void restore(IMemento memento, ITextEditor textEditor, String actionId) {
+		Boolean b = memento.getBoolean(actionId);
+		if (b != null && b) {
+			Control control = textEditor.getAdapter(Control.class);
+			if (control != null && !control.isDisposed()) {
+				// Do nothing if already disposed.
+				IAction action = textEditor.getAction(actionId);
+				if (action instanceof TextEditorAction) {
+					TextEditorAction textEditorAction = (TextEditorAction) action;
+					textEditorAction.setEditor(textEditor);
+					textEditorAction.update();
+				}
+			}
+		}
+	}
+
+	private void disable(IMemento memento, ITextOperationTarget textOperationTarget,
+			ITextOperationTargetExtension targetExtension, int operation, String preference) {
+		if (textOperationTarget.canDoOperation(operation)) {
+			memento.putBoolean(preference, true);
+			targetExtension.enableOperation(operation, false);
+		}
+	}
+
+	private void disable(IMemento memento, ITextEditor textEditor, String actionId) {
+		IAction action = textEditor.getAction(actionId);
+		if (action != null && action instanceof TextEditorAction) {
+			TextEditorAction textEditorAction = (TextEditorAction) action;
+			memento.putBoolean(actionId, true);
+			textEditorAction.setEditor(null);
+			textEditorAction.update();
+		}
+	}
+
+	@Override
+	public void onMacroPlaybackContextCreated(IMacroPlaybackContext context) {
+		EditorUtils.cacheTargetEditorPart(context);
+		EditorUtils.cacheTargetStyledText(context);
+	}
+
+	@Override
+	public void onMacroRecordContextCreated(IMacroRecordContext context) {
+		EditorUtils.cacheTargetEditorPart(context);
+		EditorUtils.cacheTargetStyledText(context);
+	}
+
+	/**
+	 * Implemented to properly deal with macro recording/playback (i.e.: the editor
+	 * may need to disable content assist during macro recording and it needs to
+	 * record keystrokes to be played back afterwards).
+	 */
+	@Override
+	public void macroStateChanged(EMacroService macroService, StateChange stateChange) {
+
+		if (stateChange == StateChange.RECORD_STARTED) {
+			enterMacroMode(macroService.getMacroRecordContext(), macroService.getMacroPlaybackContext());
+			enableRecording(macroService, macroService.getMacroRecordContext());
+
+		} else if (stateChange == StateChange.RECORD_FINISHED) {
+			leaveMacroMode(macroService.getMacroRecordContext(), macroService.getMacroPlaybackContext());
+			disableRecording(macroService.getMacroRecordContext());
+
+		} else if (stateChange == StateChange.PLAYBACK_STARTED) {
+			enterMacroMode(macroService.getMacroPlaybackContext(), macroService.getMacroRecordContext());
+
+		} else if (stateChange == StateChange.PLAYBACK_FINISHED) {
+			leaveMacroMode(macroService.getMacroPlaybackContext(), macroService.getMacroRecordContext());
+
+		}
+	}
+
+	private void enterMacroMode(IMacroContext context, IMacroContext otherContext) {
+		StyledText currentStyledText = EditorUtils.getTargetStyledText(context);
+		StyledText otherStyledText = EditorUtils.getTargetStyledText(otherContext);
+		if (currentStyledText == otherStyledText) {
+			return; // If they're the same in both it means we already entered macro mode in the
+					// other before.
+		}
+		Object object = context.get(MACRO_STYLED_TEXT_INSTALLER_MEMENTO);
+		if (object == null) {
+			XMLMemento mementoStateBeforeMacro = XMLMemento.createWriteRoot("AbstractTextEditorXmlMemento"); //$NON-NLS-1$
+			enterMacroMode(mementoStateBeforeMacro, context);
+		}
+	}
+
+	private void leaveMacroMode(IMacroContext context, IMacroContext otherContext) {
+		StyledText currentStyledText = EditorUtils.getTargetStyledText(context);
+		StyledText otherStyledText = EditorUtils.getTargetStyledText(otherContext);
+		if (currentStyledText == otherStyledText) {
+			return; // If they're the same in both it means we still can't exit macro mode.
+		}
+
+		// Restores content assist if it was disabled (based on the memento)
+		Object object = context.get(MACRO_STYLED_TEXT_INSTALLER_MEMENTO);
+		if (object instanceof XMLMemento) {
+			XMLMemento mementoStateBeforeMacro = (XMLMemento) object;
+			leaveMacroMode(mementoStateBeforeMacro, context);
+		}
+	}
+
+	private void enableRecording(EMacroService macroService, IMacroRecordContext context) {
+		// When recording install a recorder for key events (and uninstall
+		// if not recording).
+		// Note: affects only current editor
+		Object object = context.get(MACRO_STYLED_TEXT_INSTALLER_MACRO_RECORDER);
+		if (object == null) {
+			if (macroService.isRecording()) {
+				StyledText targetStyledText = EditorUtils.getTargetStyledText(context);
+				if (targetStyledText != null && !targetStyledText.isDisposed()) {
+					StyledTextMacroRecorder styledTextMacroRecorder = new StyledTextMacroRecorder(macroService);
+					styledTextMacroRecorder.install(targetStyledText);
+					context.set(MACRO_STYLED_TEXT_INSTALLER_MACRO_RECORDER, styledTextMacroRecorder);
+				}
+			}
+		}
+	}
+
+	private void disableRecording(IMacroRecordContext context) {
+		StyledText currentStyledText = EditorUtils.getTargetStyledText(context);
+		Object object = context.get(MACRO_STYLED_TEXT_INSTALLER_MACRO_RECORDER);
+		if (object instanceof StyledTextMacroRecorder) {
+			StyledTextMacroRecorder styledTextMacroRecorder = (StyledTextMacroRecorder) object;
+			if (currentStyledText != null && !currentStyledText.isDisposed()) {
+				styledTextMacroRecorder.uninstall(currentStyledText);
+			}
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/Messages.java b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/Messages.java
new file mode 100644
index 0000000..598abd1
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/Messages.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.ui.workbench.texteditor.macros.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ *
+ */
+public class Messages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.ui.workbench.texteditor.macros.internal.messages"; //$NON-NLS-1$
+	public static String NotifyMacroOnlyInCurrentEditor_NotRecording;
+	public static String NotifyMacroOnlyInCurrentEditor_Recording;
+	public static String StyledTextKeyDownMacroInstruction_KeyDown;
+	static {
+		// initialize resource bundle
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+
+	private Messages() {
+	}
+}
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/NotifyMacroOnlyInCurrentEditor.java b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/NotifyMacroOnlyInCurrentEditor.java
new file mode 100644
index 0000000..0feba10
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/NotifyMacroOnlyInCurrentEditor.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.ui.workbench.texteditor.macros.internal;
+
+import org.eclipse.e4.core.macros.CancelMacroPlaybackException;
+import org.eclipse.e4.core.macros.CancelMacroRecordingException;
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.core.macros.IMacroRecordContext;
+import org.eclipse.e4.ui.macros.internal.EditorUtils;
+import org.eclipse.e4.ui.macros.internal.UserNotifications;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.ui.IPartListener2;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbenchPartReference;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Used to notify that macro is only available in the initial editor.
+ */
+public class NotifyMacroOnlyInCurrentEditor {
+
+	/**
+	 * When a new window is opened/activated, add the needed listeners.
+	 */
+	private class WindowsListener implements IWindowListener {
+		@Override
+		public void windowOpened(IWorkbenchWindow window) {
+			addListeners(window);
+		}
+
+		@Override
+		public void windowClosed(IWorkbenchWindow window) {
+		}
+
+		@Override
+		public void windowActivated(IWorkbenchWindow window) {
+			addListeners(window);
+		}
+
+		@Override
+		public void windowDeactivated(IWorkbenchWindow window) {
+		}
+	}
+
+	/**
+	 * When a new part is made visible or is opened, check if it's the one active
+	 * when macro was activated.
+	 */
+	private class MacroPartListener implements IPartListener2 {
+
+		@Override
+		public void partVisible(IWorkbenchPartReference partRef) {
+			checkCurrentEditor();
+		}
+
+		@Override
+		public void partOpened(IWorkbenchPartReference partRef) {
+			checkCurrentEditor();
+		}
+
+		@Override
+		public void partInputChanged(IWorkbenchPartReference partRef) {
+
+		}
+
+		@Override
+		public void partHidden(IWorkbenchPartReference partRef) {
+
+		}
+
+		@Override
+		public void partDeactivated(IWorkbenchPartReference partRef) {
+
+		}
+
+		@Override
+		public void partClosed(IWorkbenchPartReference partRef) {
+
+		}
+
+		@Override
+		public void partBroughtToTop(IWorkbenchPartReference partRef) {
+
+		}
+
+		@Override
+		public void partActivated(IWorkbenchPartReference partRef) {
+			checkCurrentEditor();
+		}
+	}
+
+	private MacroPartListener fPartListener = new MacroPartListener();
+
+	private WindowsListener fWindowsListener = new WindowsListener();
+
+	/**
+	 * The macro service to be listened to.
+	 */
+	private EMacroService fMacroService;
+
+	/**
+	 * The last editor checked.
+	 */
+	private StyledText fLastEditor;
+
+	/**
+	 * @param macroService
+	 *            the macro service.
+	 */
+	public NotifyMacroOnlyInCurrentEditor(EMacroService macroService) {
+		this.fMacroService = macroService;
+	}
+
+	/**
+	 * Checks that the current editor didn't change (if it did, notify the user that
+	 * recording doesn't work in other editors).
+	 */
+	private void checkCurrentEditor() {
+		IMacroRecordContext macroRecordContext = this.fMacroService.getMacroRecordContext();
+		if (macroRecordContext != null) {
+			StyledText currentStyledText = EditorUtils.getActiveStyledText();
+			StyledText targetStyledText = EditorUtils.getTargetStyledText(macroRecordContext);
+			if (targetStyledText != currentStyledText && currentStyledText != fLastEditor) {
+				UserNotifications.setMessage(Messages.NotifyMacroOnlyInCurrentEditor_NotRecording);
+				UserNotifications.notifyCurrentEditor();
+			} else if (targetStyledText == currentStyledText && fLastEditor != null
+					&& fLastEditor != currentStyledText) {
+				UserNotifications.setMessage(Messages.NotifyMacroOnlyInCurrentEditor_Recording);
+			}
+			fLastEditor = currentStyledText;
+		}
+	}
+
+	/**
+	 * Check if there's some active editor when the macro recording starts.
+	 * 
+	 * @throws CancelMacroRecordingException
+	 */
+	public void checkEditorActiveForMacroRecording() throws CancelMacroRecordingException {
+		StyledText currentStyledText = EditorUtils.getActiveStyledText();
+		if (currentStyledText == null) {
+			UserNotifications.setMessage(Messages.NotifyMacroOnlyInCurrentEditor_NotRecording);
+			UserNotifications.notifyNoEditorOnMacroRecordStartup();
+			throw new CancelMacroRecordingException();
+		}
+	}
+
+	/**
+	 * Check if there's some active editor when the macro playback starts.
+	 *
+	 * @throws CancelMacroPlaybackException
+	 */
+	public void checkEditorActiveForMacroPlayback() throws CancelMacroPlaybackException {
+		StyledText currentStyledText = EditorUtils.getActiveStyledText();
+		if (currentStyledText == null) {
+			UserNotifications.notifyNoEditorOnMacroPlaybackStartup();
+			throw new CancelMacroPlaybackException();
+		}
+	}
+
+
+	private void addListeners(IWorkbenchWindow window) {
+		window.getPartService().addPartListener(fPartListener);
+	}
+
+	private void removeListeners(IWorkbenchWindow window) {
+		window.getPartService().removePartListener(fPartListener);
+	}
+
+	/**
+	 * Install listeners regarding macro only for current editor.
+	 */
+	public void install() {
+		PlatformUI.getWorkbench().addWindowListener(fWindowsListener);
+		for (IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows()) {
+			addListeners(window);
+		}
+	}
+
+	/**
+	 * Uninstall listeners regarding macro only for current editor.
+	 */
+	public void uninstall() {
+		fLastEditor = null;
+		for (IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows()) {
+			removeListeners(window);
+		}
+		PlatformUI.getWorkbench().removeWindowListener(fWindowsListener);
+	}
+
+
+
+}
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/StyledTextKeyDownMacroInstruction.java b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/StyledTextKeyDownMacroInstruction.java
new file mode 100644
index 0000000..d95d7b9
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/StyledTextKeyDownMacroInstruction.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.ui.workbench.texteditor.macros.internal;
+
+import java.util.Map;
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+import org.eclipse.e4.core.macros.internal.JSONHelper;
+import org.eclipse.e4.ui.macros.internal.EditorUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * A macro instruction to replay a key down (always followed by a key up).
+ */
+/* default */ class StyledTextKeyDownMacroInstruction extends AbstractSWTEventMacroInstruction {
+
+	private static final String ID = "KeyEvent"; //$NON-NLS-1$
+
+	public StyledTextKeyDownMacroInstruction(Event event) {
+		super(event);
+	}
+
+	@Override
+	public void execute(IMacroPlaybackContext macroPlaybackContext) {
+		StyledText styledText = EditorUtils.getTargetStyledText(macroPlaybackContext);
+		if (styledText != null) {
+			if (styledText.isDisposed()) {
+				return;
+			}
+			Event keyDownEvent = copyEvent(fEvent);
+			styledText.notifyListeners(SWT.KeyDown, keyDownEvent);
+
+			if (styledText.isDisposed()) {
+				return;
+			}
+
+			// Key up is also needed to update the clipboard.
+			Event keyUpEvent = copyEvent(fEvent);
+			keyUpEvent.type = SWT.KeyUp;
+			styledText.notifyListeners(SWT.KeyUp, keyUpEvent);
+		}
+	}
+
+	@Override
+	protected int getEventType() {
+		return SWT.KeyDown;
+	}
+
+	@Override
+	public String getId() {
+		return ID;
+	}
+
+	/* default */ static StyledTextKeyDownMacroInstruction fromMap(Map<String, String> map) {
+		Event event = createEventFromMap(map, SWT.KeyDown);
+		return new StyledTextKeyDownMacroInstruction(event);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		return Messages.StyledTextKeyDownMacroInstruction_KeyDown
+				+ JSONHelper.quote(Character.toString(this.fEvent.character));
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/StyledTextKeyDownMacroInstructionFactory.java b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/StyledTextKeyDownMacroInstructionFactory.java
new file mode 100644
index 0000000..64d8f8c
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/StyledTextKeyDownMacroInstructionFactory.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.ui.workbench.texteditor.macros.internal;
+
+import java.util.Map;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.e4.core.macros.IMacroInstructionFactory;
+
+/**
+ */
+public class StyledTextKeyDownMacroInstructionFactory implements IMacroInstructionFactory {
+
+	@Override
+	public IMacroInstruction create(Map<String, String> stringMap) {
+		return StyledTextKeyDownMacroInstruction.fromMap(stringMap);
+	}
+
+}
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/StyledTextMacroRecorder.java b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/StyledTextMacroRecorder.java
new file mode 100644
index 0000000..8f3684b
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/StyledTextMacroRecorder.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.ui.workbench.texteditor.macros.internal;
+
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * A listener that will record actions done in a StyledText and add them to the
+ * macro.
+ */
+public class StyledTextMacroRecorder implements Listener {
+
+	private final EMacroService fMacroService;
+
+	public StyledTextMacroRecorder(EMacroService macroService) {
+		this.fMacroService = macroService;
+	}
+
+	@Override
+	public void handleEvent(Event event) {
+		if (event.type == SWT.KeyDown && fMacroService.isRecording()) {
+			// Note: we only currently record key down actions and replay each
+			// one with KeyDown and KeyUp. In practice, having a key pressed
+			// down multiple times down and only once up gives the same result
+			// as doing a down/up at each step.
+			fMacroService.addMacroInstruction(new StyledTextKeyDownMacroInstruction(event), event,
+					EMacroService.PRIORITY_LOW);
+		}
+	}
+
+	public void uninstall(StyledText textWidget) {
+		textWidget.removeListener(SWT.KeyDown, this);
+	}
+
+	public void install(StyledText textWidget) {
+		textWidget.addListener(SWT.KeyDown, this);
+	}
+}
diff --git a/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/messages.properties b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/messages.properties
new file mode 100644
index 0000000..844b35d
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench.texteditor.macros/src/org/eclipse/ui/workbench/texteditor/macros/internal/messages.properties
@@ -0,0 +1,3 @@
+NotifyMacroOnlyInCurrentEditor_NotRecording=Not recording
+NotifyMacroOnlyInCurrentEditor_Recording=Recording
+StyledTextKeyDownMacroInstruction_KeyDown=KeyDown: 
diff --git a/bundles/pom.xml b/bundles/pom.xml
index 4e90238..a8c01ef 100644
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -26,10 +26,11 @@
     <module>org.eclipse.e4.ui.keys.common</module>
     <module>org.eclipse.e4.ui.naturist</module>
     <module>org.eclipse.e4.jdt.scope</module>
-    <module>org.eclipse.e4.ui.macros.jdt</module>
-    <module>org.eclipse.e4.ui.macros</module>
     <module>org.eclipse.ui.glance</module>
     <module>org.eclipse.ui.regex</module>
+    <module>org.eclipse.e4.core.macros</module>
+    <module>org.eclipse.e4.ui.macros</module>
+    <module>org.eclipse.ui.workbench.texteditor.macros</module>
   </modules>
 </project>
 
diff --git a/features/org.eclipse.e4.ui.macros.feature/.project b/features/org.eclipse.e4.ui.macros.feature/.project
new file mode 100644
index 0000000..b2d50ef
--- /dev/null
+++ b/features/org.eclipse.e4.ui.macros.feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.e4.ui.macros.feature</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.pde.FeatureBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.FeatureNature</nature>
+	</natures>
+</projectDescription>
diff --git a/features/org.eclipse.e4.ui.macros.feature/build.properties b/features/org.eclipse.e4.ui.macros.feature/build.properties
new file mode 100644
index 0000000..64f93a9
--- /dev/null
+++ b/features/org.eclipse.e4.ui.macros.feature/build.properties
@@ -0,0 +1 @@
+bin.includes = feature.xml
diff --git a/features/org.eclipse.e4.ui.macros.feature/feature.xml b/features/org.eclipse.e4.ui.macros.feature/feature.xml
new file mode 100644
index 0000000..774fabc
--- /dev/null
+++ b/features/org.eclipse.e4.ui.macros.feature/feature.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.eclipse.e4.ui.macros.feature"
+      label="Eclipse Macros"
+      version="0.1.0.qualifier"
+      provider-name="Eclipse.org">
+
+   <description>
+      Macro support for Eclipse
+   </description>
+
+   <copyright>
+      Copyright (c) 2017 Fabio Zadrozny and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License
+v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+   </copyright>
+
+   <license url="http://www.eclipse.org/legal/epl-v10.html">
+      Eclipse Public License
+   </license>
+
+   <plugin
+         id="org.eclipse.e4.core.macros"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.e4.ui.macros"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+   <plugin
+         id="org.eclipse.ui.workbench.texteditor.macros"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+
+</feature>
diff --git a/features/org.eclipse.e4.ui.macros.feature/pom.xml b/features/org.eclipse.e4.ui.macros.feature/pom.xml
new file mode 100644
index 0000000..f06cb5b
--- /dev/null
+++ b/features/org.eclipse.e4.ui.macros.feature/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

+  <modelVersion>4.0.0</modelVersion>

+  <parent>

+    <groupId>org.eclipse.e4.ui</groupId>

+    <artifactId>e4-ui-aggregator</artifactId>

+    <version>0.17.0-SNAPSHOT</version>

+    <relativePath>../../</relativePath>

+  </parent>

+

+  <groupId>org.eclipse.e4</groupId>

+  <artifactId>org.eclipse.e4.ui.macros.feature</artifactId>

+  <version>0.1.0-SNAPSHOT</version>

+  <packaging>eclipse-feature</packaging>

+

+  <build>

+    <plugins>

+      <plugin>

+        <groupId>org.eclipse.tycho.extras</groupId>

+        <artifactId>tycho-source-feature-plugin</artifactId>

+        <executions>

+          <execution>

+            <phase>package</phase>

+            <id>source-feature</id>

+            <goals>

+              <goal>source-feature</goal>

+            </goals>

+          </execution>

+        </executions>

+      </plugin>

+      <plugin>

+        <groupId>org.eclipse.tycho</groupId>

+        <artifactId>tycho-p2-plugin</artifactId>

+        <version>${tycho.version}</version>

+        <executions>

+          <execution>

+            <id>attached-p2-metadata</id>

+            <phase>package</phase>

+            <goals>

+              <goal>p2-metadata</goal>

+            </goals>

+          </execution>

+        </executions>

+      </plugin>

+    </plugins>

+  </build>

+</project>

diff --git a/features/pom.xml b/features/pom.xml
index 0ca970f..a48a29f 100644
--- a/features/pom.xml
+++ b/features/pom.xml
@@ -26,6 +26,7 @@
     <module>org.eclipse.e4.ui.keys.feature</module>
     <module>org.eclipse.e4.ui.naturist.feature</module>
     <module>org.eclipse.ui.glance.feature</module>
+    <module>org.eclipse.e4.ui.macros.feature</module>
   </modules>
 </project>
 
diff --git a/pom.xml b/pom.xml
index 0c52e94..8e8907e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,6 +39,7 @@
   <modules>
     <module>tests/org.eclipse.e4.naturist.tests</module>
     <module>tests/org.eclipse.e4.jdt.scope.tests</module>
+    <module>tests/org.eclipse.e4.ui.macros.tests</module>
     <module>build/org.eclipse.e4.ui.update</module>
     <module>bundles</module>
     <module>features</module>
diff --git a/tests/org.eclipse.e4.ui.macros.tests/.classpath b/tests/org.eclipse.e4.ui.macros.tests/.classpath
new file mode 100644
index 0000000..4f83b23
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.e4.ui.macros.jdt/.project b/tests/org.eclipse.e4.ui.macros.tests/.project
similarity index 92%
rename from bundles/org.eclipse.e4.ui.macros.jdt/.project
rename to tests/org.eclipse.e4.ui.macros.tests/.project
index 4babb46..f65caa5 100644
--- a/bundles/org.eclipse.e4.ui.macros.jdt/.project
+++ b/tests/org.eclipse.e4.ui.macros.tests/.project
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-	<name>org.eclipse.e4.ui.macros.jdt</name>
+	<name>org.eclipse.e4.ui.macros.tests</name>
 	<comment></comment>
 	<projects>
 	</projects>
diff --git a/tests/org.eclipse.e4.ui.macros.tests/.settings/org.eclipse.core.runtime.prefs b/tests/org.eclipse.e4.ui.macros.tests/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..5a0ad22
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/tests/org.eclipse.e4.ui.macros.tests/.settings/org.eclipse.jdt.core.prefs b/tests/org.eclipse.e4.ui.macros.tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..6d43b76
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,292 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/tests/org.eclipse.e4.ui.macros.tests/.settings/org.eclipse.jdt.ui.prefs b/tests/org.eclipse.e4.ui.macros.tests/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..d7de1c3
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,62 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
diff --git a/tests/org.eclipse.e4.ui.macros.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.e4.ui.macros.tests/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..7297136
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Macro tests
+Bundle-SymbolicName: org.eclipse.e4.ui.macros.tests;singleton:=true
+Bundle-Activator: org.eclipse.e4.ui.macros.tests.Activator
+Bundle-Version: 0.1.0.qualifier
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.junit,
+ org.eclipse.e4.core.macros,
+ org.eclipse.e4.core.contexts,
+ org.eclipse.e4.core.di,
+ org.eclipse.e4.ui.bindings,
+ org.eclipse.e4.core.commands,
+ org.eclipse.e4.ui.services,
+ org.eclipse.e4.ui.macros
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
diff --git a/bundles/org.eclipse.e4.ui.macros.jdt/build.properties b/tests/org.eclipse.e4.ui.macros.tests/build.properties
similarity index 73%
rename from bundles/org.eclipse.e4.ui.macros.jdt/build.properties
rename to tests/org.eclipse.e4.ui.macros.tests/build.properties
index e3023e1..e9863e2 100644
--- a/bundles/org.eclipse.e4.ui.macros.jdt/build.properties
+++ b/tests/org.eclipse.e4.ui.macros.tests/build.properties
@@ -2,4 +2,4 @@
 output.. = bin/
 bin.includes = META-INF/,\
                .,\
-               fragment.xml
+               plugin.xml
diff --git a/tests/org.eclipse.e4.ui.macros.tests/forceQualifierUpdate.txt b/tests/org.eclipse.e4.ui.macros.tests/forceQualifierUpdate.txt
new file mode 100644
index 0000000..8ad7a91
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/forceQualifierUpdate.txt
@@ -0,0 +1 @@
+# To force a version qualifier update add the bug here
\ No newline at end of file
diff --git a/tests/org.eclipse.e4.ui.macros.tests/pom.xml b/tests/org.eclipse.e4.ui.macros.tests/pom.xml
new file mode 100644
index 0000000..47664de
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright (c) 2017 Fabio Zadrozny, and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.eclipse.e4.ui</groupId>
+    <artifactId>e4-ui-aggregator</artifactId>
+    <version>0.17.0-SNAPSHOT</version>
+    <relativePath>../../</relativePath>
+  </parent>
+
+  <groupId>org.eclipse.e4</groupId>
+  <artifactId>org.eclipse.e4.ui.macros.tests</artifactId>
+  <version>0.1.0-SNAPSHOT</version>
+  <packaging>eclipse-test-plugin</packaging>
+
+</project>
diff --git a/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/Activator.java b/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/Activator.java
new file mode 100644
index 0000000..e9315b4
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/Activator.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.tests;
+
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "org.eclipse.e4.ui.macros.tests"; //$NON-NLS-1$
+
+	// The shared instance
+	private static Activator plugin;
+
+	private IEclipseContext appContext;
+
+	private IEclipseContext serviceContext;
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+	@Override
+	public void start(BundleContext context) throws Exception {
+		plugin = this;
+		serviceContext = EclipseContextFactory.getServiceContext(context);
+		appContext = serviceContext.createChild();
+	}
+
+	@Override
+	public void stop(BundleContext context) throws Exception {
+		serviceContext.dispose();
+		plugin = null;
+	}
+
+	public IEclipseContext getGlobalContext() {
+		return appContext;
+	}
+
+}
diff --git a/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/JSONHelperTest.java b/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/JSONHelperTest.java
new file mode 100644
index 0000000..c3da94d
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/JSONHelperTest.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.tests;
+
+import org.eclipse.e4.core.macros.internal.JSONHelper;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class JSONHelperTest {
+
+	@Test
+	public void testJSONHelper() {
+		StringBuilder builder = new StringBuilder("chars\"\\/\b\f\n\r\t");
+		builder.append(new Character((char) 5));
+		builder.append(new Character((char) 6));
+		String quoted = JSONHelper.quote(builder.toString());
+		Assert.assertEquals("\"chars\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0005\\u0006\"", quoted);
+	}
+}
diff --git a/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/KeyBindingDispatcherMacroIntegrationTest.java b/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/KeyBindingDispatcherMacroIntegrationTest.java
new file mode 100644
index 0000000..da61aa1
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/KeyBindingDispatcherMacroIntegrationTest.java
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.eclipse.core.commands.Category;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.contexts.Context;
+import org.eclipse.core.commands.contexts.ContextManager;
+import org.eclipse.e4.core.commands.CommandServiceAddon;
+import org.eclipse.e4.core.commands.ECommandService;
+import org.eclipse.e4.core.commands.EHandlerService;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.core.macros.IMacroRecordContext;
+import org.eclipse.e4.core.macros.IMacroStateListener;
+import org.eclipse.e4.core.macros.internal.MacroServiceImplementation;
+import org.eclipse.e4.ui.bindings.BindingServiceAddon;
+import org.eclipse.e4.ui.bindings.EBindingService;
+import org.eclipse.e4.ui.bindings.internal.BindingTable;
+import org.eclipse.e4.ui.bindings.internal.BindingTableManager;
+import org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher;
+import org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.KeyDownFilter;
+import org.eclipse.e4.ui.macros.internal.keybindings.CommandManagerExecutionListener;
+import org.eclipse.e4.ui.macros.internal.keybindings.CommandManagerExecutionListenerInstaller;
+import org.eclipse.e4.ui.services.ContextServiceAddon;
+import org.eclipse.e4.ui.services.EContextService;
+import org.eclipse.jface.bindings.Binding;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+@SuppressWarnings("restriction")
+public class KeyBindingDispatcherMacroIntegrationTest {
+
+	private static final String ID_DIALOG = "org.eclipse.ui.contexts.dialog";
+	private static final String ID_DIALOG_AND_WINDOW = "org.eclipse.ui.contexts.dialogAndWindow";
+	private static final String ID_WINDOW = "org.eclipse.ui.contexts.window";
+
+	final static String[] CONTEXTS = { ID_DIALOG_AND_WINDOW, "DAW", null, ID_DIALOG, "Dialog", ID_DIALOG_AND_WINDOW,
+			ID_WINDOW, "Window", ID_DIALOG_AND_WINDOW, };
+
+	private static final String TEST_CAT1 = "test.cat1";
+	private static final String TEST_ID1 = "test.id1";
+
+	static class CallHandler {
+		public boolean q1;
+		public boolean q2;
+
+		@CanExecute
+		public boolean canExecute() {
+			q1 = true;
+			return true;
+		}
+
+		@Execute
+		public Object execute() {
+			q2 = true;
+			if (q1) {
+				return Boolean.TRUE;
+			}
+			return Boolean.FALSE;
+		}
+	}
+
+	private Display display;
+	private IEclipseContext workbenchContext;
+	private CallHandler handler;
+	private File fMacrosDirectory;
+	private Shell shell;
+	private StyledText styledText;
+	private KeyDownFilter dispatcherListener;
+
+	private void defineCommands(IEclipseContext context) {
+		ECommandService cs = workbenchContext.get(ECommandService.class);
+		Category category = cs.defineCategory(TEST_CAT1, "CAT1", null);
+		cs.defineCommand(TEST_ID1, "ID1", null, category, null);
+		ParameterizedCommand cmd = cs.createCommand(TEST_ID1, null);
+		EHandlerService hs = workbenchContext.get(EHandlerService.class);
+		handler = new CallHandler();
+		hs.activateHandler(TEST_ID1, handler);
+		EBindingService bs = workbenchContext.get(EBindingService.class);
+		// As we're using the default display, we have to generate a unique sequence
+		// otherwise the default installed key filter may eat it.
+		TriggerSequence seq = bs.createSequence("CTRL+I");
+		Binding db = createDefaultBinding(bs, seq, cmd);
+		bs.activateBinding(db);
+	}
+
+	private Binding createDefaultBinding(EBindingService bs, TriggerSequence sequence, ParameterizedCommand command) {
+
+		Map<String, String> attrs = new HashMap<>();
+		attrs.put("schemeId", "org.eclipse.ui.defaultAcceleratorConfiguration");
+
+		return bs.createBinding(sequence, command, ID_WINDOW, attrs);
+	}
+
+	private void defineContexts(IEclipseContext context) {
+		ContextManager contextManager = context.get(ContextManager.class);
+		for (int i = 0; i < CONTEXTS.length; i += 3) {
+			Context c = contextManager.getContext(CONTEXTS[i]);
+			c.define(CONTEXTS[i + 1], null, CONTEXTS[i + 2]);
+		}
+
+		EContextService cs = context.get(EContextService.class);
+		cs.activateContext(ID_DIALOG_AND_WINDOW);
+		cs.activateContext(ID_WINDOW);
+	}
+
+	private void defineBindingTables(IEclipseContext context) {
+		BindingTableManager btm = context.get(BindingTableManager.class);
+		ContextManager cm = context.get(ContextManager.class);
+		btm.addTable(new BindingTable(cm.getContext(ID_DIALOG_AND_WINDOW)));
+		btm.addTable(new BindingTable(cm.getContext(ID_WINDOW)));
+		btm.addTable(new BindingTable(cm.getContext(ID_DIALOG)));
+	}
+
+	@Before
+	public void setUp() throws Exception {
+		display = Display.getDefault();
+		shell = new Shell(display, SWT.NONE);
+		styledText = new StyledText(shell, SWT.NONE);
+
+		IEclipseContext globalContext = Activator.getDefault().getGlobalContext();
+		workbenchContext = globalContext.createChild("workbenchContext");
+		ContextInjectionFactory.make(CommandServiceAddon.class, workbenchContext);
+		ContextInjectionFactory.make(ContextServiceAddon.class, workbenchContext);
+		ContextInjectionFactory.make(BindingServiceAddon.class, workbenchContext);
+		defineContexts(workbenchContext);
+		defineBindingTables(workbenchContext);
+		defineCommands(workbenchContext);
+
+		KeyBindingDispatcher dispatcher = new KeyBindingDispatcher();
+		workbenchContext.set(KeyBindingDispatcher.class, dispatcher);
+		ContextInjectionFactory.inject(dispatcher, workbenchContext);
+
+		workbenchContext.set(EMacroService.class.getName(),
+				ContextInjectionFactory.make(MacroServiceImplementation.class, workbenchContext));
+
+		dispatcherListener = dispatcher.getKeyDownFilter();
+		display.addFilter(SWT.KeyDown, dispatcherListener);
+		display.addFilter(SWT.Traverse, dispatcherListener);
+
+		assertFalse(handler.q2);
+
+		fMacrosDirectory = folder.getRoot();
+		EMacroService macroService = workbenchContext.get(EMacroService.class);
+		((MacroServiceImplementation) macroService).getMacroManager().setMacrosDirectories(fMacrosDirectory);
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		workbenchContext.dispose();
+		workbenchContext = null;
+		styledText.dispose();
+		styledText = null;
+		shell.dispose();
+		shell = null;
+	}
+
+	private void notifyCtrlI(Control control) {
+		Event event = new Event();
+		event.type = SWT.KeyDown;
+		event.keyCode = SWT.CTRL;
+		control.notifyListeners(SWT.KeyDown, event);
+
+		event = new Event();
+		event.type = SWT.KeyDown;
+		event.stateMask = SWT.CTRL;
+		event.keyCode = 'I';
+		control.notifyListeners(SWT.KeyDown, event);
+	}
+
+	private void startRecording(EMacroService macroService) throws Exception {
+		macroService.toggleMacroRecord();
+		assertTrue(macroService.isRecording());
+		IMacroRecordContext macroRecordContext = macroService.getMacroRecordContext();
+		macroRecordContext.set("target_styled_text", styledText); // org.eclipse.e4.ui.macros.Activator.TARGET_STYLED_TEXT
+
+		Assert.assertEquals(
+				Arrays.asList("org.eclipse.e4.ui.macros.internal.actions.KeepMacroUIUpdated",
+						"org.eclipse.e4.ui.macros.internal.keybindings.CommandManagerExecutionListenerInstaller"),
+				getRegisteredClasses(macroService));
+		IMacroStateListener[] macroStateListeners = ((MacroServiceImplementation) macroService)
+				.getMacroStateListeners();
+		boolean found = false;
+		for (IMacroStateListener iMacroStateListener : macroStateListeners) {
+			if (iMacroStateListener instanceof CommandManagerExecutionListenerInstaller) {
+				CommandManagerExecutionListenerInstaller commandManagerExecutionListenerInstaller = (CommandManagerExecutionListenerInstaller) iMacroStateListener;
+				// Make sure that we accept any event while testing.
+				CommandManagerExecutionListener commandManagerExecutionListener = commandManagerExecutionListenerInstaller
+						.getCommandManagerExecutionListener();
+				Field field = CommandManagerExecutionListener.class.getDeclaredField("fFilter");
+				field.setAccessible(true);
+				field.set(commandManagerExecutionListener, new CommandManagerExecutionListener.IFilter() {
+
+					@Override
+					public boolean acceptEvent(Event swtEvent) {
+						return true;
+					}
+				});
+				found = true;
+			}
+		}
+		Assert.assertTrue(found);
+	}
+
+	private void finishRecording(EMacroService macroService) {
+		macroService.toggleMacroRecord();
+		assertFalse(macroService.isRecording());
+	}
+
+	@Rule
+	public TemporaryFolder folder = new TemporaryFolder();
+
+	@Test
+	public void testMacroIntegration() throws Exception {
+		EMacroService macroService = workbenchContext.get(EMacroService.class);
+		// Before the first record, it should be empty (loaded on demand).
+		Assert.assertEquals(new ArrayList<>(), getRegisteredClasses(macroService));
+		startRecording(macroService);
+
+		notifyCtrlI(styledText);
+		assertTrue(handler.q2);
+		assertEquals(macroService.getLenOfMacroBeingRecorded(), 1);
+
+		finishRecording(macroService);
+
+		handler.q2 = false;
+		macroService.playbackLastMacro();
+		assertTrue(handler.q2);
+	}
+
+	public List<String> getRegisteredClasses(EMacroService macroService) {
+		IMacroStateListener[] macroStateListeners = ((MacroServiceImplementation) macroService)
+				.getMacroStateListeners();
+		List<String> classes = Arrays.stream(macroStateListeners).map(m -> m.getClass().getName()).sorted()
+				.collect(Collectors.toList());
+		return classes;
+	}
+
+	@Test
+	public void testMacroIntegrationSaveRestore() throws Exception {
+		FilenameFilter macrosFilter = new FilenameFilter() {
+
+			@Override
+			public boolean accept(File dir, String name) {
+				return name.endsWith(".js");
+			}
+		};
+		assertEquals(0, fMacrosDirectory.list(macrosFilter).length);
+
+		EMacroService macroService = workbenchContext.get(EMacroService.class);
+
+		assertFalse(handler.q2);
+
+		startRecording(macroService);
+		notifyCtrlI(styledText);
+		assertTrue(handler.q2);
+		assertEquals(macroService.getLenOfMacroBeingRecorded(), 1);
+		finishRecording(macroService);
+
+		// Macro was saved in the dir.
+		assertEquals(1, fMacrosDirectory.list(macrosFilter).length);
+
+		// Check if reloading from disk and playing it back works.
+		((MacroServiceImplementation) macroService).getMacroManager().reloadMacros();
+		handler.q2 = false;
+		macroService.playbackLastMacro();
+		assertTrue(handler.q2);
+	}
+
+}
diff --git a/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/MacroTest.java b/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/MacroTest.java
new file mode 100644
index 0000000..1b8a9f0
--- /dev/null
+++ b/tests/org.eclipse.e4.ui.macros.tests/src/org/eclipse/e4/ui/macros/tests/MacroTest.java
@@ -0,0 +1,343 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Fabio Zadrozny and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Fabio Zadrozny - initial API and implementation - http://eclip.se/8519
+ *******************************************************************************/
+package org.eclipse.e4.ui.macros.tests;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.e4.core.macros.CancelMacroRecordingException;
+import org.eclipse.e4.core.macros.EMacroService;
+import org.eclipse.e4.core.macros.IMacroInstruction;
+import org.eclipse.e4.core.macros.IMacroInstructionFactory;
+import org.eclipse.e4.core.macros.IMacroPlaybackContext;
+import org.eclipse.e4.core.macros.IMacroStateListener;
+import org.eclipse.e4.core.macros.internal.MacroManager;
+import org.eclipse.e4.core.macros.internal.MacroManager.PathAndTime;
+import org.eclipse.e4.core.macros.internal.MacroServiceImplementation;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class MacroTest {
+
+	@Rule
+	public TemporaryFolder folder = new TemporaryFolder();
+
+	private static class PlaybackContext implements IMacroPlaybackContext {
+
+		public StringBuffer buffer = new StringBuffer();
+
+		private Map<String, IMacroInstructionFactory> fMacroInstructionIdToFactory;
+
+		public PlaybackContext(Map<String, IMacroInstructionFactory> macroInstructionIdToFactory) {
+			this.fMacroInstructionIdToFactory = macroInstructionIdToFactory;
+		}
+
+		public void recordPlayback(String name) {
+			if (buffer.length() > 0) {
+				buffer.append("\n");
+			}
+			buffer.append(name);
+		}
+
+		@Override
+		public IMacroInstruction createMacroInstruction(String macroInstructionId, Map<String, String> stringMap)
+				throws Exception {
+			return fMacroInstructionIdToFactory.get(macroInstructionId).create(stringMap);
+		}
+
+		private final Map<Object, Object> ctx = new HashMap<>();
+
+		@Override
+		public Object get(String key) {
+			return ctx.get(key);
+		}
+
+		@Override
+		public void set(String key, Object value) {
+			ctx.put(key, value);
+		}
+	}
+
+	private static class DummyMacroInstruction implements IMacroInstruction {
+
+		private String fName;
+
+		public DummyMacroInstruction(String name) {
+			this.fName = name;
+		}
+
+		@Override
+		public void execute(IMacroPlaybackContext macroPlaybackContext) {
+			((PlaybackContext) macroPlaybackContext).recordPlayback(this.fName);
+		}
+
+		@Override
+		public String getId() {
+			return "dummy";
+		}
+
+		@Override
+		public String toString() {
+			return "Dummy macro instruction";
+		}
+
+		@Override
+		public Map<String, String> toMap() {
+			HashMap<String, String> map = new HashMap<>();
+			map.put("dummyKey", "dummyValue");
+			map.put("name", this.fName);
+			return map;
+		}
+
+	}
+
+	@Test
+	public void testRecordingState() throws Exception {
+		Map<String, IMacroInstructionFactory> macroInstructionIdToFactory = makeMacroInstructionIdToFactory();
+		MacroServiceImplementation macroService = new MacroServiceImplementation(null, null);
+		Field field = macroService.getClass().getDeclaredField("fMacroInstructionIdToFactory");
+		field.setAccessible(true);
+		field.set(macroService, macroInstructionIdToFactory);
+		File root = folder.getRoot();
+		macroService.getMacroManager().setMacrosDirectories(root);
+		final StringBuilder buf = new StringBuilder();
+		macroService.getMacroManager().addMacroStateListener(new IMacroStateListener() {
+
+			@Override
+			public void macroStateChanged(EMacroService macroService, StateChange stateChange) {
+				buf.append("rec: ").append(macroService.isRecording()).append(" play: ")
+						.append(macroService.isPlayingBack()).append("\n");
+			}
+		});
+
+		Assert.assertFalse(macroService.isRecording());
+		Assert.assertEquals("", buf.toString());
+
+		macroService.toggleMacroRecord();
+		Assert.assertEquals("rec: true play: false\n", buf.toString());
+		buf.setLength(0);
+		Assert.assertTrue(macroService.isRecording());
+
+		// Add something, otherwise no macro will be recorded
+		macroService.addMacroInstruction(new DummyMacroInstruction("test"));
+
+		macroService.toggleMacroRecord();
+		Assert.assertEquals("rec: false play: false\n", buf.toString());
+		buf.setLength(0);
+		Assert.assertFalse(macroService.isRecording());
+
+		PlaybackContext playbackContext = new PlaybackContext(macroInstructionIdToFactory);
+		macroService.getMacroManager().playbackLastMacro(macroService, playbackContext);
+		Assert.assertEquals("rec: false play: true\n"
+				+ "rec: false play: false\n", buf.toString());
+		buf.setLength(0);
+
+		macroService.toggleMacroRecord();
+		macroService.getMacroManager().playbackLastMacro(macroService, playbackContext);
+		macroService.toggleMacroRecord();
+		Assert.assertEquals(
+				"rec: true play: false\n"
+				+ "rec: true play: true\n"
+				+ "rec: true play: false\n"
+				+ "rec: false play: false\n",
+				buf.toString());
+	}
+
+	@Test
+	public void testAddMacroInstructions() throws Exception {
+		MacroManager macroManager = new MacroManager();
+		Map<String, IMacroInstructionFactory> macroInstructionIdToFactory = makeMacroInstructionIdToFactory();
+		PlaybackContext playbackContext = new PlaybackContext(macroInstructionIdToFactory);
+		macroManager.toggleMacroRecord(null, macroInstructionIdToFactory);
+		Assert.assertTrue(macroManager.isRecording());
+		macroManager.addMacroInstruction(new DummyMacroInstruction("macro1"));
+		macroManager.addMacroInstruction(new DummyMacroInstruction("macro2"));
+		macroManager.toggleMacroRecord(null, macroInstructionIdToFactory);
+		Assert.assertFalse(macroManager.isRecording());
+
+		macroManager.playbackLastMacro(null, playbackContext);
+		Assert.assertEquals("macro1\nmacro2", playbackContext.buffer.toString());
+	}
+
+	@Test
+	public void testAddMacroInstructionPriority() throws Exception {
+		MacroManager macroManager = new MacroManager();
+		Map<String, IMacroInstructionFactory> macroInstructionIdToFactory = makeMacroInstructionIdToFactory();
+		PlaybackContext playbackContext = new PlaybackContext(macroInstructionIdToFactory);
+		macroManager.toggleMacroRecord(null, macroInstructionIdToFactory);
+		Assert.assertTrue(macroManager.isRecording());
+		Object ev = new Integer(1);
+		macroManager.addMacroInstruction(new DummyMacroInstruction("macro1"), ev, 2);
+		Assert.assertEquals(1, macroManager.getLenOfMacroBeingRecorded());
+		macroManager.addMacroInstruction(new DummyMacroInstruction("macro2"), ev, 1); // will not replace it
+		Assert.assertEquals(1, macroManager.getLenOfMacroBeingRecorded());
+		macroManager.toggleMacroRecord(null, macroInstructionIdToFactory);
+		Assert.assertFalse(macroManager.isRecording());
+
+		macroManager.playbackLastMacro(null, playbackContext);
+		Assert.assertEquals("macro1", playbackContext.buffer.toString());
+	}
+
+	@Test
+	public void testAddMacroInstructionPriority1() throws Exception {
+		MacroManager macroManager = new MacroManager();
+		Map<String, IMacroInstructionFactory> macroInstructionIdToFactory = makeMacroInstructionIdToFactory();
+		PlaybackContext playbackContext = new PlaybackContext(macroInstructionIdToFactory);
+		macroManager.toggleMacroRecord(null, macroInstructionIdToFactory);
+		Assert.assertTrue(macroManager.isRecording());
+		Object ev = new Integer(1);
+		macroManager.addMacroInstruction(new DummyMacroInstruction("macro1"), ev, 1);
+		Assert.assertEquals(1, macroManager.getLenOfMacroBeingRecorded());
+		macroManager.addMacroInstruction(new DummyMacroInstruction("macro2"), ev, 2); // will replace it
+		Assert.assertEquals(1, macroManager.getLenOfMacroBeingRecorded());
+		macroManager.toggleMacroRecord(null, macroInstructionIdToFactory);
+		Assert.assertFalse(macroManager.isRecording());
+
+		macroManager.playbackLastMacro(null, playbackContext);
+		Assert.assertEquals("macro2", playbackContext.buffer.toString());
+	}
+
+	@Test
+	public void testMacroManagerSaveRestore() throws Exception {
+		File root = folder.getRoot();
+		MacroManager macroManager = new MacroManager(root);
+		Map<String, IMacroInstructionFactory> macroInstructionIdToFactory = makeMacroInstructionIdToFactory();
+		createMacroWithOneDummyMacroInstruction(macroManager, macroInstructionIdToFactory);
+		String[] macroNames = listTemporaryMacros(root);
+		Assert.assertEquals(1, macroNames.length);
+
+		// Create a new macroManager (to force getting from the disk).
+		macroManager = new MacroManager(root);
+		PlaybackContext playbackContext = new PlaybackContext(macroInstructionIdToFactory);
+		macroManager.playbackLastMacro(null, playbackContext);
+		Assert.assertEquals("macro1", playbackContext.buffer.toString());
+	}
+
+	@Test
+	public void testMacroManagerMaxNumberOfMacros() throws Exception {
+		File root = folder.getRoot();
+		MacroManager macroManager = new MacroManager(root);
+		macroManager.setMaxNumberOfTemporaryMacros(2);
+		Map<String, IMacroInstructionFactory> macroInstructionIdToFactory = makeMacroInstructionIdToFactory();
+
+		createMacroWithOneDummyMacroInstruction(macroManager, macroInstructionIdToFactory);
+
+		String[] macroNames1 = listTemporaryMacros(root);
+		Assert.assertEquals(macroNames1.length, 1);
+
+		// Sleep to make sure that the time of the file will be different
+		// (otherwise, if it runs too fast, the same time could be applied to
+		// the first, second and last file, in which case we may remove the
+		// wrong one).
+		sleepABit();
+		createMacroWithOneDummyMacroInstruction(macroManager, macroInstructionIdToFactory);
+
+		String[] macroNames2 = listTemporaryMacros(root);
+		Assert.assertEquals(2, macroNames2.length);
+		HashSet<Long> times = new HashSet<>();
+		List<PathAndTime> macrosPathAndTime = macroManager.listTemporaryMacrosPathAndTime(root);
+		for (PathAndTime pathAndTime : macrosPathAndTime) {
+			times.add(pathAndTime.fLastModified);
+		}
+		Assert.assertEquals(2, times.size());
+
+		// Now, creating a new one removes the old one
+		sleepABit();
+		createMacroWithOneDummyMacroInstruction(macroManager, macroInstructionIdToFactory);
+		macrosPathAndTime = macroManager.listTemporaryMacrosPathAndTime(root);
+
+		String[] macroNames3 = listTemporaryMacros(root);
+		Assert.assertEquals(2, macroNames3.length);
+
+		for (PathAndTime pathAndTime : macrosPathAndTime) {
+			times.add(pathAndTime.fLastModified);
+		}
+
+		Assert.assertEquals(3, times.size());
+
+		assertNotContains(Arrays.asList(macroNames3), macroNames1[0]);
+	}
+
+	private void assertNotContains(Collection<String> list, String name) {
+		if (list.contains(name)) {
+			StringBuffer stringBuffer = new StringBuffer();
+			stringBuffer.append("Did not expect: ").append(name).append("\nTo be in:\n");
+			for (String string : list) {
+				stringBuffer.append(string).append("\n");
+			}
+			Assert.fail(stringBuffer.toString());
+		}
+
+	}
+
+	private void sleepABit() {
+		synchronized (this) {
+			try {
+				this.wait(1000); // Sleep a full second to make sure that we have a new timestamp
+									// on files to make test less brittle (not all systems have
+									// a good precision).
+			} catch (InterruptedException e) {
+				// Ignore in this case
+			}
+		}
+
+	}
+
+	protected String[] listTemporaryMacros(File root) {
+		String[] files = root.list(new FilenameFilter() {
+
+			@Override
+			public boolean accept(File dir, String name) {
+				return name.endsWith(".js") && name.startsWith("temp_macro");
+			}
+		});
+		return files;
+	}
+
+	protected void createMacroWithOneDummyMacroInstruction(MacroManager macroManager,
+			Map<String, IMacroInstructionFactory> macroInstructionIdToFactory) throws CancelMacroRecordingException {
+		macroManager.toggleMacroRecord(null, macroInstructionIdToFactory);
+		macroManager.addMacroInstruction(new DummyMacroInstruction("macro1"));
+		macroManager.toggleMacroRecord(null, macroInstructionIdToFactory);
+	}
+
+	private Map<String, IMacroInstructionFactory> makeMacroInstructionIdToFactory() {
+		Map<String, IMacroInstructionFactory> macroInstructionIdToFactory = new HashMap<>();
+		macroInstructionIdToFactory.put("dummy", new IMacroInstructionFactory() {
+
+			@Override
+			public IMacroInstruction create(Map<String, String> stringMap) {
+				if (stringMap.size() != 2) {
+					throw new AssertionError("Expected map size to be 2. Found: " + stringMap.size());
+				}
+				if (!stringMap.get("dummyKey").equals("dummyValue")) {
+					throw new AssertionError("Did not find dummyKey->dummyValue mapping.");
+				}
+				if (stringMap.get("name") == null) {
+					throw new AssertionError("Expected name to be defined.");
+				}
+
+				return new DummyMacroInstruction(stringMap.get("name"));
+			}
+		});
+		return macroInstructionIdToFactory;
+	}
+
+}