Addresses issue #10846 #10850

Merged
merged 3 commits into from Apr 10, 2015

Projects

None yet

4 participants

@thehogfather
Contributor

@abose @peterflynn (apologies it isn't solely related to #10846 - it felt sensible to combine into one PR)
Fold states are now persisted using viewState (state.json)
Added copyright text into foldcode.js and foldgutter.js
Removed strings.js file
Removed latex-fold helper
Removed menu item for custom region folding
Disable custom region folding by default

@thehogfather thehogfather Addresses issue #10846 - fold states are now persisted using viewStat…
…e (state.json)

Added copyright text into foldcode.js and foldgutter.js
Removed strings.js file
Removed latex-fold helper
Removed menu item for custom region folding
Disable custom region folding by default
a66855e
@abose abose commented on an outdated diff Apr 8, 2015
src/extensions/default/CodeFolding/Prefs.js
@@ -23,7 +22,7 @@ define(function (require, exports, module) {
{name: strings.SAVE_FOLD_STATES, description: strings.SAVE_FOLD_STATES_HELP});
prefs.definePreference("alwaysUseIndentFold", "boolean", true,
{name: strings.ALWAYS_USE_INDENT_FOLD, description: strings.ALWAYS_USE_INDENT_FOLD_HELP});
- prefs.definePreference("enableRegionFolding", "boolean", true,
+ prefs.definePreference("enableRegionFolding", "boolean", false,
@abose
abose Apr 8, 2015 Contributor

If we do not expose the region fold feature by default, should we include it in the view menu?

@abose
abose Apr 8, 2015 Contributor

Ok got it. The custom region folds feature is being removed. In that case, could't we remove the preference entry altogether, along with the menu entry and the corresponding strings?

@abose
Contributor
abose commented Apr 8, 2015

Code folding is enabled in all files by default, and in some files like txt files it looks a bit odd.
Would it be a good thing to enable code folding in only HTML,XML,js Etc. and disabled in all other file types?

@thehogfather
Contributor

@abose I suspect the fold marks are appearing in a txt file due to indentations. A suggestion would be to disable the alwaysUseIndentFold option so that only files with registered mode helpers for code-folding have fold markers?

@thehogfather thehogfather Removed string for collapse custom region menu.
Set alwaysUseIndentFold preference to be false by default
Addresses #10848 - changes to preference files are now updated live in brackets without needing to restart
797ed3f
@peterflynn peterflynn and 1 other commented on an outdated diff Apr 9, 2015
src/extensions/default/CodeFolding/main.js
@@ -348,5 +422,28 @@ define(function (require, exports, module) {
}
}
- AppInit.appReady(init);
+ /**
+ * Register change listener for the preferences file.
+ */
+ function watchPrefsForChanges() {
+ prefs.prefBase.on("change", function (e, data) {
+ if (data.ids.indexOf("enabled") > -1) {
+ if (prefs.getSetting("enabled")) {
+ init();
+ } else {
+ var editor = EditorManager.getCurrentFullEditor();
+ if (editor && editor._codeMirror && CodeMirror.commands.unfoldAll) {
+ CodeMirror.commands.unfoldAll(editor._codeMirror);
+ foldGutter.remove(editor._codeMirror);
+ }
@peterflynn
peterflynn Apr 9, 2015 Member

Wouldn't you need to do this for all existing Editor instances, not just the current one?

@thehogfather
thehogfather Apr 9, 2015 Contributor

Yes we would. Currently the other editors open 'catch up' when the active editor changes. I couldn't find an api for iterating through open editors in the working set. Is there one? How would you do it?

@peterflynn
peterflynn Apr 9, 2015 Member

It will definitely look bad for split view, where two editors are visible at once even though only one is active.

The cleanest way to do it is walking the _instances array in Editor.js, which is currently inaccessible -- that's how core Editor preferences are updated. It seems fair to me to add a public API like forEveryEditor() or something -- pass a callback, and it gets invoked like a forEach.

@peterflynn
peterflynn Apr 10, 2015 Member

It might be easier for me to take care of this issue in my PR -- that ok with you?

@peterflynn peterflynn commented on an outdated diff Apr 9, 2015
...ensions/default/CodeFolding/foldhelpers/foldgutter.js
@@ -310,7 +312,15 @@ define(function (require, exports, module) {
});
}
+ function remove(cm) {
+ var gutters = cm.getOption("gutters").slice(0);
+ var index = gutters.indexOf("CodeMirror-foldgutter");
+ gutters.splice(index, 1);
+ cm.setOption("gutters", gutters);
+ CodeMirror.defineOption("foldGutter", false, null);
+ }
@peterflynn
peterflynn Apr 9, 2015 Member

Since this is basically the reverse of createGutter() in main.js, it seems like the two functions should live in the same file. Could you either move that one here or move this there?

@abose abose commented on an outdated diff Apr 9, 2015
src/nls/fi/strings.js
@@ -631,7 +631,6 @@ define({
"EXPAND_ALL" : "Laajenna kaikki",
"COLLAPSE_CURRENT" : "Pienennä nykyinen",
"EXPAND_CURRENT" : "Laajenna nykyinen",
- "COLLAPSE_CUSTOM_REGIONS" : "Pienennä mukautetut alueet",
"MIN_FOLD_SIZE" : "Pienin laskostuksen koko",
@abose
abose Apr 9, 2015 Contributor

Only strings in the UI are put in nls/lang/strings.js file; other strings could be moved into the extension as some constants. The problem with having string constants here is that the automation team would send these strings for translation or the community would translate these constants, which would be a loss of resources.

@peterflynn peterflynn commented on the diff Apr 9, 2015
src/extensions/default/CodeFolding/main.js
@@ -54,7 +45,11 @@ define(function (require, exports, module) {
EXPAND = "codefolding.expand",
EXPAND_ALL = "codefolding.expand.all",
gutterName = "CodeMirror-foldgutter",
- COLLAPSE_CUSTOM_REGIONS = "codefolding.collapse.customregions";
+ codeFoldingMenuDivider = "codefolding.divider",
+ collapseKey = "Ctrl-Alt-[",
+ expandKey = "Ctrl-Alt-]",
+ collapseAllKey = "Alt-1",
+ expandAllKey = "Shift-Alt-1";
@peterflynn
peterflynn Apr 9, 2015 Member

On master, I can't seem to override any of these shortcuts using keymap.json. I can't remember if this is some limitation of the user keybindings feature (e.g. can't override shortcuts defined by an extension? -- cc @RaymondLim)... But to users it will just feel like a bug since they don't know which things are implemented under the hood as a built-in extension.

If it's tricky to fix we should spin this off as a separate bug though.

@peterflynn
peterflynn Apr 9, 2015 Member

Ack, scratch that -- I had the syntax backwards. It does work on master. We should just make sure it still works in this PR too with the new, more dynamic way bindings are registered & unregistered.

@peterflynn peterflynn commented on the diff Apr 9, 2015
src/extensions/default/CodeFolding/main.js
+ }
+
+ if (!CommandManager.get(EXPAND_ALL)) {
+ CommandManager.register(Strings.EXPAND_ALL, EXPAND_ALL, expandAll);
+ }
+
+ if (!CommandManager.get(COLLAPSE)) {
+ CommandManager.register(Strings.COLLAPSE_CURRENT, COLLAPSE, collapseCurrent);
+ }
+
+ if (!CommandManager.get(EXPAND)) {
+ CommandManager.register(Strings.EXPAND_CURRENT, EXPAND, expandCurrent);
+ }
+
+ //create menus
+ if (!menuExists(codeFoldingMenuDivider)) {
@peterflynn
peterflynn Apr 9, 2015 Member

I'm not clear on why we need to check all these individually. If one of them exists, they all should... But also, it seems like we could just maintain an internal flag like isInitialized to prevent doing everything in init() when it's already been done. (I'm assuming the core problem here is that preferences broadcasts change events sometimes when the pref value hasn't actually changed, which could lead to trying to initialize twice and thus duplicating all the menu items).

@thehogfather
thehogfather Apr 9, 2015 Contributor

@peterflynn I couldn't get it working properly for some reason without this smelly explicit conditions. But please feel free to have a go and update it.

@peterflynn
peterflynn Apr 9, 2015 Member

Looks like the divider gets recreated every time you set the "enabled" pref to true at runtime. That's kind of an edge case -- I'll see if I can address it in my PR instead of worrying about it here.

@peterflynn
peterflynn Apr 10, 2015 Member

This part is fixed in my PR now

@peterflynn peterflynn commented on an outdated diff Apr 9, 2015
src/extensions/default/CodeFolding/Prefs.js
{name: strings.ALWAYS_USE_INDENT_FOLD, description: strings.ALWAYS_USE_INDENT_FOLD_HELP});
- prefs.definePreference("enableRegionFolding", "boolean", true,
+ prefs.definePreference("enableRegionFolding", "boolean", false,
@peterflynn
peterflynn Apr 9, 2015 Member

It seems like the 'custom regions' stuff is partially removed, but not fully -- the menu item and the command behind it is gone, but this preference (and its strings) is still there along with region-fold.js. Seems like we should remove those too (and then whatever extension re-exposes the menu item could reintroduce those elements too). Does that sound ok?

@peterflynn
Member

@thehogfather This looks great overall, thanks for posting this update so quickly! I added a few comments above.

One other note: this fixes bug #10848 for the "enabled" preference, but the other preferences still seem to need a restart or close/reopen file to take effect. Did you want to wait for another PR to fix those other prefs?

@peterflynn
Member

@thehogfather Fyi, I've opened PR #10859 with some UI changes as well as a few code tweaks. Some of it duplicates change you've made here (I started working on it before you posted this), so once your PR is merged I'll rebase mine on top of your changes. But please take a look and see if there's anything else there you'd be concerned about.

@abose
Contributor
abose commented Apr 9, 2015

@thehogfather Now that custom region fold support is removed, fold helper - region-fold.js could also be removed.

@thehogfather thehogfather Moved preference strings from nls/lang to vars in Prefs.js
Changes to all preferences are now live
Removed region-fold and custom-region fold strings
2c6a356
@thehogfather
Contributor

@abose @peterflynn I think this should be closer to ready than before. Cleaned up the strings and removed custom-region folding completely. Now over to you. Happy to help with anything else you direct my way.

@peterflynn peterflynn commented on the diff Apr 9, 2015
src/extensions/default/CodeFolding/Prefs.js
- foldsKey = "folds";
+ var PreferencesManager = brackets.getModule("preferences/PreferencesManager"),
+ prefs = PreferencesManager.getExtensionPrefs("code-folding"),
+ foldsKey = "code-folding.folds",
+ // preference key strings are here for now since they are not used in any UI
+ ENABLE_CODE_FOLDING = "Enable code folding",
+ MIN_FOLD_SIZE = "Minimum fold size",
+ MIN_FOLD_SIZE_HELP = "Minimum number of lines to allow in a foldable range",
+ SAVE_FOLD_STATES = "Save fold states",
+ SAVE_FOLD_STATES_HELP = "Save fold states to disk when editor is closed and restore the folds when reopened",
+ ALWAYS_USE_INDENT_FOLD = "Always use indent fold",
+ ALWAYS_USE_INDENT_FOLD_HELP = "Fall back to using level of indentation as a folding guideline if no range finder is found for the current mode.",
+ FADE_FOLD_BUTTONS = "Fade fold buttons",
+ FADE_FOLD_BUTTONS_HELP = "Hides the fold buttons unless the mouse is over the gutter",
+ MAX_FOLD_LEVEL = "Max fold level",
+ MAX_FOLD_LEVEL_HELP = "Used to limit the number of nested folds to find and collapse when View -> Collapse All is called or Alt is held down when collapsing. Should improve performance for large files.";
@peterflynn
peterflynn Apr 9, 2015 Member

This feels a little weird -- might be better for these to just be doc comments on the definePreference() calls for now... but not a big deal. I think this would be ok to merge as-is.

@peterflynn peterflynn commented on the diff Apr 9, 2015
src/extensions/default/CodeFolding/main.js
@@ -273,6 +264,11 @@ define(function (require, exports, module) {
if (previous) {
saveLineFolds(previous);
}
+ } else {
+ if (current && current._codeMirror) {
@peterflynn
peterflynn Apr 9, 2015 Member

Nit: can remove the & current._codeMirror here too

@peterflynn
peterflynn Apr 10, 2015 Member

Nm, this is taken care of in my PR

@peterflynn peterflynn commented on the diff Apr 9, 2015
src/extensions/default/CodeFolding/Prefs.js
prefs.definePreference("maxFoldLevel", "number", 2,
- {name: strings.MAX_FOLD_LEVEL, description: strings.MAX_FOLD_LEVEL_HELP});
+ {name: MAX_FOLD_LEVEL, description: MAX_FOLD_LEVEL_HELP});
prefs.definePreference("folds", "object", {});
@peterflynn
peterflynn Apr 9, 2015 Member

This should be turned into PreferencesManager.stateManager.definePreference(...

@peterflynn
Member

Looks like minFoldSize and alwaysUseIndentFold still require close & reopen to take effect. Do you want to spin that off as a separate bug?

@peterflynn
Member

Hmm, it also looks like folds are no longer remembered when you close & reopen a file, even with a completely clean slate of prefs. Seems like something is broken with the view-state storage changes here...

@thehogfather
Contributor

WRT minFoldSize and alwaysUseIndentFold lets file a separate bug with steps to reproduce. When I test it I get the effects immediately within the brackets.json file being edited (after saving).

@peterflynn peterflynn commented on the diff Apr 9, 2015
src/extensions/default/CodeFolding/Prefs.js
@@ -85,8 +93,9 @@ define(function (require, exports, module) {
* @param {Object} folds the fold ranges to save for the current document
*/
function setFolds(path, folds) {
- store[path] = simplify(folds);
- prefs.set(foldsKey, store);
+ var allFolds = PreferencesManager.getViewState(foldsKey);
@peterflynn
peterflynn Apr 9, 2015 Member

You need || {} here too -- that's why saving folds is broken currently.

@peterflynn
peterflynn Apr 9, 2015 Member

One other thought... rather than dumping folding state for all files together in one map, it might make sense to bucket it by project, like we do for other similar prefs like the scroll position & selection state of editors.

MainViewManager has an example of how to do that:

            context = { location : { scope: "user",
                                     layer: "project" } },
            state = PreferencesManager.getViewState(PREFS_NAME, context);

and

            context         = { location : { scope: "user",
                                         layer: "project",
                                         layerID: projectRoot.fullPath } },
        ...
        PreferencesManager.setViewState(PREFS_NAME, state, context);
@abose
abose Apr 10, 2015 Contributor

@peterflynn can you make the || {} change in your PR?
Also issues#10869 added for tracking the bucketing by project.

@abose
abose Apr 10, 2015 Contributor

brackets/issues/10870 opened to track Code Folding preference minFoldSize and alwaysUseIndentFold require close & reopen of file to take effect.

@MarcelGerber
MarcelGerber Apr 10, 2015 Member

I think using the correct PreferencesManager.stateManager.definePreference(... will fix that, won't it?

@peterflynn
peterflynn Apr 10, 2015 Member

@MarcelGerber Yep, good point -- that should remove the need for || {} both here & in getFolds().

@peterflynn peterflynn commented on the diff Apr 10, 2015
src/extensions/default/CodeFolding/main.js
@@ -317,29 +416,12 @@ define(function (require, exports, module) {
init();
@peterflynn
peterflynn Apr 10, 2015 Member

Btw, why do we need to call init() again on project open? Now that we're listening for preference changes at all times, it seems like this should be unnecessary?

@peterflynn
peterflynn Apr 10, 2015 Member

I removed this in my PR and things still seem to work ok

@peterflynn
Member

Btw, it's still a ways off but it will be interesting to think about what having the same document visible in two split panes will mean for code folding. Should collapsing a section in one pane automatically collapse it in the other? Seems like that would feel weird, but otoh if each editor has its own expand/collapse state for the same document, how will that be persisted? Which one "wins" if you close both views? Etc.

I'll add a note to that Trello story so we can think about it more when the time comes.

@peterflynn peterflynn added this to the Release 1.3 milestone Apr 10, 2015
@abose abose merged commit d36f263 into adobe:master Apr 10, 2015

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
@abose
Contributor
abose commented Apr 10, 2015

Loos good now; Merging this PR.
@peterflynn brackets/pull/10859 can now be merged.

@MarcelGerber
Member

@peterflynn It's the same issue for selections/cursors, having two states in one document is weird anyway.

@peterflynn
Member

@abose Wait, why did you merge this already? See my comments above -- #10850 (comment) and #10850 (comment) -- code folding persistence is completely broken in master now because of this PR. We should have waited before fixing that blocker before merging...

I'll file a high-priority bug to track it.

@thehogfather thehogfather deleted the thehogfather:issue10846 branch Aug 10, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment