8 |
--------------------------------------------------------------------------------
/.brackets.json:
--------------------------------------------------------------------------------
1 | {
2 | "jslint.options": {
3 | "vars": true,
4 | "plusplus": true,
5 | "devel": true,
6 | "nomen": true,
7 | "maxerr": 50,
8 | "es5": true
9 | },
10 | "defaultExtension": "js",
11 | "language": {
12 | "javascript": {
13 | "linting.prefer": ["JSLint", "JSHint"],
14 | "linting.usePreferredOnly": true
15 | }
16 | },
17 | "spaceUnits": 4,
18 | "useTabChar": false
19 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jeffbooher.bookmarks",
3 | "title": "Brackets Editor Bookmarks",
4 | "description": "Bookmark lines in the editor as you work so you can quickly jump back to them later. Open the \"Bookmarks\" Panel to see all of the bookmarks and open them in the editor.",
5 | "homepage": "https://github.com/JeffryBooher/brackets-bookmarks-extension",
6 | "version": "0.10.6",
7 | "author": "Jeffry Booher|jsbooher@adobe.com (http://www.facebook.com/JeffryBooher)|@JeffryBooher",
8 | "license": "MIT",
9 | "i18n": [
10 | "en",
11 | "de",
12 | "es",
13 | "fr",
14 | "it",
15 | "pl",
16 | "ru"
17 | ],
18 | "engines": {
19 | "brackets": ">=0.24.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/images/bookmark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/styles.css:
--------------------------------------------------------------------------------
1 | .bookmark .CodeMirror-gutter-elt {
2 | background-color: lightskyblue;
3 | }
4 |
5 | .bookmark .CodeMirror-linenumber {
6 | background-image: url('../images/bookmark.svg');
7 | background-size: 16px;
8 | background-repeat: no-repeat;
9 | color: white !important;
10 | }
11 |
12 | .active-pane .bookmark .CodeMirror-gutter-elt {
13 | background-color: dodgerblue;
14 | display: table;
15 | }
16 |
17 | .active-pane .bookmark.live-preview-sync-error .CodeMirror-linenumber {
18 | background-color: mediumorchid !important;
19 | }
20 |
21 | .bookmark-notify {
22 | background-color: dodgerblue;
23 | }
24 |
25 | .bookmark-notify .CodeMirror-activeline-background {
26 | background-color: darkslateblue!important;
27 | }
28 |
29 | .bookmark.CodeMirror-activeline .CodeMirror-gutter-elt {
30 | background-color: rebeccapurple !important;
31 | }
32 |
33 | .active-pane .bookmark.CodeMirror-activeline .CodeMirror-gutter-elt {
34 | background-color: darkslateblue!important;
35 | }
36 |
37 | .bookmark.CodeMirror-activeline .CodeMirror-linenumber {
38 | background-image: url('../images/bookmark.svg') !important;
39 | background-size: 16px !important;
40 | background-repeat: no-repeat !important;
41 | color: white !important;
42 | }
43 |
--------------------------------------------------------------------------------
/nls/ru/strings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | // Russian Translation
25 |
26 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
27 | /*global define */
28 |
29 | define({
30 | "TOGGLE_BOOKMARK" : "Вкл./выкл. закладку",
31 | "GOTO_NEXT_BOOKMARK" : "Следующая закладка",
32 | "GOTO_PREV_BOOKMARK" : "Предыдущая закладка",
33 | "TOGGLE_BOOKMARKS_PANEL" : "Показать панель закладок",
34 | "BOOKMARKS_PANEL_TITLE" : "Закладки"
35 | });
36 |
--------------------------------------------------------------------------------
/nls/root/strings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | // English - root strings
25 |
26 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
27 | /*global define */
28 |
29 | define({
30 | "TOGGLE_BOOKMARK" : "Toggle Bookmark",
31 | "GOTO_NEXT_BOOKMARK" : "Next Bookmark",
32 | "GOTO_PREV_BOOKMARK" : "Previous Bookmark",
33 | "TOGGLE_BOOKMARKS_PANEL" : "Show Bookmarks Panel",
34 | "BOOKMARKS_PANEL_TITLE" : "Bookmarks"
35 | });
36 |
--------------------------------------------------------------------------------
/nls/pl/strings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | // Polish Translation
25 |
26 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
27 | /*global define */
28 |
29 | define({
30 | "TOGGLE_BOOKMARK" : "Włącz/Wyłącz Zakładki",
31 | "GOTO_NEXT_BOOKMARK" : "Następna Zakładka",
32 | "GOTO_PREV_BOOKMARK" : "Poprzednia Zakładka",
33 | "TOGGLE_BOOKMARKS_PANEL" : "Pokaż Panel Zakładek",
34 | "BOOKMARKS_PANEL_TITLE" : "Zakładki"
35 | });
36 |
--------------------------------------------------------------------------------
/nls/es/strings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | // English - root strings
25 |
26 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
27 | /*global define */
28 |
29 | define({
30 | "TOGGLE_BOOKMARK" : "Des/Activar Marcador",
31 | "GOTO_NEXT_BOOKMARK" : "Marcador Siguiente",
32 | "GOTO_PREV_BOOKMARK" : "Marcador Anterior",
33 | "TOGGLE_BOOKMARKS_PANEL" : "Mostrar Panel de Marcadores",
34 | "BOOKMARKS_PANEL_TITLE" : "Marcadores"
35 | });
36 |
--------------------------------------------------------------------------------
/nls/fr/strings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | // French Translation
25 |
26 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
27 | /*global define */
28 |
29 | define({
30 | "TOGGLE_BOOKMARK" : "Créer/supprimer le marque-page",
31 | "GOTO_NEXT_BOOKMARK" : "Marque-page suivant",
32 | "GOTO_PREV_BOOKMARK" : "Marque-page précédent",
33 | "TOGGLE_BOOKMARKS_PANEL" : "Afficher panneau des marque-pages",
34 | "BOOKMARKS_PANEL_TITLE" : "Marque-pages"
35 | });
36 |
--------------------------------------------------------------------------------
/nls/it/strings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | // Italian - root strings
25 |
26 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
27 | /*global define */
28 |
29 | define({
30 | "TOGGLE_BOOKMARK" : "Toggle Bookmark",
31 | "GOTO_NEXT_BOOKMARK" : "Segnalibro successivo",
32 | "GOTO_PREV_BOOKMARK" : "Segnalibro precedente",
33 | "TOGGLE_BOOKMARKS_PANEL" : "Mostra pannello segnalibri",
34 | "BOOKMARKS_PANEL_TITLE" : "Segnalibri"
35 | });
36 |
--------------------------------------------------------------------------------
/nls/de/strings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | // German strings
25 |
26 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
27 | /*global define */
28 |
29 | define({
30 | "TOGGLE_BOOKMARK" : "Lesezeichen setzen/entfernen",
31 | "GOTO_NEXT_BOOKMARK" : "Gehe zum nächsten Lesezeichen",
32 | "GOTO_PREV_BOOKMARK" : "Gehe zum vorherigen Lesezeichen",
33 | "TOGGLE_BOOKMARKS_PANEL" : "Lesezeichen anzeigen...",
34 | "BOOKMARKS_PANEL_TITLE" : "Lesezeichen"
35 | });
36 |
--------------------------------------------------------------------------------
/strings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
25 | /*global define */
26 |
27 | /**
28 | * This file provides the interface to user visible strings in Brackets. Code that needs
29 | * to display strings should should load this module by calling var Strings = require("strings").
30 | * The i18n plugin will dynamically load the strings for the right locale and populate
31 | * the exports variable. See src\nls\strings.js for the master file of English strings.
32 | */
33 | define(function (require, exports, module) {
34 | "use strict";
35 |
36 | module.exports = require("i18n!nls/strings");
37 |
38 | });
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "bitwise" : true,
3 | "curly" : true,
4 | "eqeqeq" : true,
5 | "forin" : true,
6 | "immed" : true,
7 | "latedef" : true,
8 | "newcap" : true,
9 | "noarg" : true,
10 | "noempty" : true,
11 | "nonew" : true,
12 | "plusplus" : false,
13 | "regexp" : true,
14 | "undef" : true,
15 | "strict" : true,
16 | "unused" : "vars",
17 |
18 | "asi" : false,
19 | "boss" : false,
20 | "debug" : false,
21 | "eqnull" : false,
22 | "es5" : false,
23 | "esnext" : false,
24 | "evil" : false,
25 | "expr" : false,
26 | "funcscope" : false,
27 | "globalstrict" : false,
28 | "iterator" : false,
29 | "lastsemic" : false,
30 | "laxbreak" : false,
31 | "laxcomma" : false,
32 | "loopfunc" : false,
33 | "multistr" : false,
34 | "onecase" : false,
35 | "proto" : false,
36 | "regexdash" : false,
37 | "scripturl" : false,
38 | "shadow" : false,
39 | "sub" : false,
40 | "supernew" : false,
41 | "validthis" : false,
42 |
43 | "browser" : false,
44 | "couch" : false,
45 | "devel" : true,
46 | "dojo" : false,
47 | "jquery" : false,
48 | "mootools" : false,
49 | "node" : false,
50 | "nonstandard" : false,
51 | "prototypejs" : false,
52 | "rhino" : false,
53 | "wsh" : false,
54 |
55 | "maxerr" : 100,
56 | "indent" : 4,
57 | "globals" : {
58 | "window": false,
59 | "document": false,
60 | "setTimeout": false,
61 | "require": false,
62 | "define": false,
63 | "brackets": false,
64 | "$": false,
65 | "PathUtils": false,
66 | "window": false,
67 | "navigator": false,
68 | "Mustache": false
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/nls/strings.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
25 | /*global define */
26 |
27 | define(function (require, exports, module) {
28 |
29 | 'use strict';
30 |
31 | // Code that needs to display user strings should call require("strings") to load
32 | // strings.js. This file will dynamically load strings.js for the specified by bracketes.locale.
33 | //
34 | // Translations for other locales should be placed in nls/>/strings.js
35 | // Localization is provided via the i18n plugin.
36 | // All other bundles for languages need to add a prefix to the exports below so i18n can find them.
37 | // TODO: dynamically populate the local prefix list below?
38 | module.exports = {
39 | root: true,
40 | "de": true,
41 | "es": true,
42 | "fr": true,
43 | "it": true,
44 | "pl": true,
45 | "ru": true
46 | };
47 | });
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Brackets Bookmarks Extension
2 | ============================
3 |
4 | This Extension provides functionality to bookmark lines in [Brackets](https://github.com/adobe/brackets).
5 |
6 | `Navigate > Toggle Bookmark` or press ⇧⌘K (`Ctrl+Shift+K` on Windows)
7 |
8 | And recall those bookmarks later
9 |
10 | `Navigate > Next Bookmark` or press ⌘P (`Ctrl+P` on Windows)
11 |
12 | `Navigate > Previous Bookmark` or press ⇧⌘P (`Ctrl+Shift+P` on Windows)
13 |
14 | Bookmarks are serialized and remembered globally. Add bookmarks to a file, close the file, reopen the file. Brackets will restore the bookmarks. Bookmarks are represented with a color and a bookmark icon.
15 |
16 | Bookmarked lines with Live Editing Syntax Errors will show using a different color
17 |
18 | `View > Show Bookmarks Panel` To see all bookmarks of open files (open, temporary views and views of files in the working set which may not have been open yet)
19 |
20 | The default mode for the Bookmarks panel is to show bookmarks of only "open" files. This can be confusing when bookmarking files that Brackets has created a temporary view for then switching to another view. The result would cause the bookmark to disappear from the bookmarks view with the only way to get back to it is by reopening the file.
21 |
22 | Add the following to your Brackets preferences file to show all bookmarks within a "project"
23 |
24 | "bracketsEditorBookmarks.viewOptions": {
25 | "show": "project"
26 | }
27 |
28 |
29 | Add the following to your Brackets preferences file to show all bookmarks
30 |
31 | "bracketsEditorBookmarks.viewOptions": {
32 | "show": "all"
33 | }
34 |
35 | the default for the "show" preference is "opened".
36 |
37 | **ProTip**: Setting the show preference "all" will enable you to quickly jump between files in other projects.
38 |
39 | ##TODO
40 | 1. Localize. I've set this extension up for localization so please contribute pull requests to translate this extension
41 | 1. Sync bookmarks if files are changed externally... Use a hash of the line maybe?
42 | 1. Better Bookmark Affordance (@larz0) especially when bookmarking lines in files with more than 999 lines since the bookmark UI encroaches on the line number
43 | 1. Bookmark UI when line numbers are turned off
44 | 1. Bookmark filtering (show bookmarks with xxx in the file's name, annotation, etc..)
45 | 1. Bookmark groups (allow bookmarks to belong to a task like "refactoring functionXXX")
46 | 1. Bookmark annotation (why was the bookmark added -- a quick glance at the context of the bookmark)
47 |
--------------------------------------------------------------------------------
/view/BookmarksView.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | /*eslint-rules no-underscore-dangle: false*/
25 |
26 | /*global define, brackets, window, $, Mustache, navigator */
27 |
28 | /*
29 | * Panel showing search results for a Find/Replace in Files operation.
30 | */
31 | define(function (require, exports, module) {
32 | "use strict";
33 |
34 | var CommandManager = brackets.getModule("command/CommandManager"),
35 | Commands = brackets.getModule("command/Commands"),
36 | DocumentManager = brackets.getModule("document/DocumentManager"),
37 | EditorManager = brackets.getModule("editor/EditorManager"),
38 | ProjectManager = brackets.getModule("project/ProjectManager"),
39 | FileViewController = brackets.getModule("project/FileViewController"),
40 | FileUtils = brackets.getModule("file/FileUtils"),
41 | FindUtils = brackets.getModule("search/FindUtils"),
42 | WorkspaceManager = brackets.getModule("view/WorkspaceManager"),
43 | MainViewManger = brackets.getModule("view/MainViewManager"),
44 | _ = brackets.getModule("thirdparty/lodash"),
45 |
46 | StringUtils = brackets.getModule("utils/StringUtils"),
47 | Strings = require("strings"),
48 |
49 | bookmarksPanelTemplate = require("text!htmlContent/bookmarks-panel.html"),
50 | bookmarksListTemplate = require("text!htmlContent/bookmarks-list.html");
51 |
52 |
53 | /**
54 | * @const
55 | * Debounce time for document changes updating the search results view.
56 | * @type {number}
57 | */
58 | var UPDATE_TIMEOUT = 400;
59 |
60 | /**
61 | * @const
62 | * MainViewManager events
63 | * @type {string}
64 | */
65 | var MVM_EVENTS = "workingSetAdd workingSetAddList workingSetMove workingSetRemove workingSetRemoveList workingSetUpdate currentFileChange activePaneChange";
66 | /**
67 | * @constructor
68 | * Creates a bookmarks panel
69 | * Dispatches the following events:
70 | * close - when the panel is closed.
71 | *
72 | * @typedef {Object.>} BookmarksModel
73 | * @param {BookmarksModel} model - bookmarks model
74 | * @param {function=} beforeRender - function to call before rendering the view
75 | */
76 | function BookmarksView(model, beforeRender) {
77 | var panelHtml = Mustache.render(bookmarksPanelTemplate, {
78 | Strings: Strings
79 | });
80 |
81 | this._panel = WorkspaceManager.createBottomPanel("bookmarks", $(panelHtml), 100);
82 | this._$panel = this._panel.$panel;
83 | this._$table = this._$panel.find(".table-container");
84 | this._model = model;
85 | this._beforeRender = beforeRender;
86 | }
87 |
88 | /** @type {BookmarksModel} bookmarks model */
89 | BookmarksView.prototype._model = null;
90 |
91 | /** @type {Panel} Bottom panel holding the bookmarks */
92 | BookmarksView.prototype._panel = null;
93 |
94 | /** @type {$.Element} The table that holds the results */
95 | BookmarksView.prototype._$table = null;
96 |
97 | /** @type {number} The ID we use for timeouts when handling model changes. */
98 | BookmarksView.prototype._timeoutID = null;
99 |
100 | /** @type {function=} function that is called before refreshing the view */
101 | BookmarksView.prototype._beforeRender = null;
102 |
103 | /**
104 | * @private
105 | * Handles when model changes. Updates the view, buffering changes if necessary so as not to churn too much.
106 | */
107 | BookmarksView.prototype._handleModelChange = function () {
108 | var self = this;
109 | if (self._ignoreModelChangeEvents) {
110 | return;
111 | }
112 | if (this._timeoutID) {
113 | window.clearTimeout(this._timeoutID);
114 | }
115 | this._timeoutID = window.setTimeout(function () {
116 | // _updateResults causes the model to be recomputed
117 | // which triggers another model change event which
118 | // we need to ignore or we endup in a race condition
119 | // which may lead to data loss
120 | self._ignoreModelChangeEvents = true;
121 | self._updateResults();
122 | self._timeoutID = null;
123 | delete self._ignoreModelChangeEvents;
124 | }, UPDATE_TIMEOUT);
125 | };
126 |
127 | /**
128 | * @private
129 | * Adds the listeners for close and clicking on a bookmark in the list
130 | */
131 | BookmarksView.prototype._addPanelListeners = function () {
132 | var self = this;
133 | this._$panel
134 | .off(".bookmarks") // Remove the old events
135 | .on("click.bookmarks", ".close", function () {
136 | self.close();
137 | })
138 | // Add the click event listener directly on the table parent
139 | .on("click.bookmarks .table-container", function (e) {
140 | var $row = $(e.target).closest("tr");
141 |
142 | if ($row.length) {
143 | if (self._$selectedRow) {
144 | self._$selectedRow.removeClass("selected");
145 | }
146 | $row.addClass("selected");
147 | self._$selectedRow = $row;
148 |
149 | var fullPathAndLineNo = $row.find(".bookmark-result").text();
150 |
151 | CommandManager.execute(Commands.FILE_OPEN, {fullPath: fullPathAndLineNo});
152 | }
153 | });
154 | MainViewManger.on(MVM_EVENTS, this._updateResults.bind(this));
155 | };
156 |
157 | /**
158 | * @private
159 | * @param {!String} fullpath - path of the file to show
160 | */
161 | BookmarksView.prototype._shouldShow = function (fullpath) {
162 | if (!this._options || !this._options.show || this._options.show === "opened") {
163 | return Boolean(MainViewManger._getPaneIdForPath(fullpath));
164 | } else if (this._options.show === "all") {
165 | return true;
166 |
167 | } else if (this._options.show === "project" && ProjectManager.getProjectRoot()) {
168 | // show open files and any file bookmarked in the current project
169 | return (Boolean(MainViewManger._getPaneIdForPath(fullpath)) ||
170 | fullpath.toLowerCase().indexOf(ProjectManager.getProjectRoot().fullPath.toLowerCase()) === 0);
171 | }
172 |
173 | // unknown option
174 | return false;
175 | };
176 |
177 | /**
178 | * @private
179 | * Shows the current set of results.
180 | */
181 | BookmarksView.prototype._render = function () {
182 | var self = this,
183 | bookmarks = [];
184 |
185 | if (this._beforeRender) {
186 | this._beforeRender();
187 | }
188 |
189 | // Iterates throuh the files to display the results sorted by filenamess. The loop ends as soon as
190 | // we filled the results for one page
191 | Object.keys(this._model)
192 | .filter(function (fullPath) {
193 | return self._shouldShow(fullPath);
194 | })
195 | .sort(function (a, b) {
196 | return a > b;
197 | })
198 | .forEach(function (fullPath) {
199 | self._model[fullPath].forEach(function (lineNo) {
200 | bookmarks.push({
201 | fullPath: fullPath,
202 | lineNo: lineNo + 1
203 | });
204 | });
205 | });
206 |
207 | // Insert the search results
208 | this._$table
209 | .empty()
210 | .append(Mustache.render(bookmarksListTemplate, {
211 | bookmarks: bookmarks,
212 | Strings: Strings
213 | }));
214 |
215 | if (this._$selectedRow) {
216 | this._$selectedRow.removeClass("selected");
217 | this._$selectedRow = null;
218 | }
219 |
220 | this._panel.show();
221 | this._$table.scrollTop(0); // Otherwise scroll pos from previous contents is remembered
222 | };
223 |
224 | /**
225 | * Updates the results view after a model change, preserving scroll position and selection.
226 | */
227 | BookmarksView.prototype._updateResults = function () {
228 | // In general this shouldn't get called if the panel is closed, but in case some
229 | // asynchronous process kicks this (e.g. a debounced model change), we double-check.
230 | if (this._panel.isVisible()) {
231 | var scrollTop = this._$table.scrollTop(),
232 | index = this._$selectedRow ? this._$selectedRow.index() : null;
233 | this._render();
234 | this._$table.scrollTop(scrollTop);
235 | if (index) {
236 | this._$selectedRow = this._$table.find("tr:eq(" + index + ")");
237 | this._$selectedRow.addClass("selected");
238 | }
239 | }
240 | };
241 |
242 |
243 |
244 |
245 | /**
246 | * Opens the results panel and displays the current set of results from the model.
247 | */
248 | BookmarksView.prototype.open = function (options) {
249 | this._options = options;
250 | this._render();
251 | this._addPanelListeners();
252 | $(this._model).on("change.BookmarksView", this._handleModelChange.bind(this));
253 | };
254 |
255 | /**
256 | * Hides the Search Results Panel and unregisters listeners.
257 | */
258 | BookmarksView.prototype.close = function () {
259 | if (this._panel && this._panel.isVisible()) {
260 | this._$table.empty();
261 | this._panel.hide();
262 | this._panel.$panel.off(".bookmarks");
263 | $(this._model).off("change.BookmarksView");
264 | $(this).triggerHandler("close");
265 | }
266 | };
267 |
268 | /**
269 | * Hides the Search Results Panel and unregisters listeners.
270 | */
271 | BookmarksView.prototype.isOpen = function () {
272 | return (this._panel && this._panel.isVisible());
273 | };
274 |
275 | // Public API
276 | exports.BookmarksView = BookmarksView;
277 | });
278 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2012 Jeffry Booher. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
25 | /*global define, brackets, $ */
26 |
27 | define(function (require, exports, module) {
28 | "use strict";
29 |
30 | // Brackets modules
31 | var PreferencesManager = brackets.getModule("preferences/PreferencesManager"),
32 | CommandManager = brackets.getModule("command/CommandManager"),
33 | ExtensionUtils = brackets.getModule("utils/ExtensionUtils"),
34 | Menus = brackets.getModule("command/Menus"),
35 | DocumentManager = brackets.getModule("document/DocumentManager"),
36 | EditorManager = brackets.getModule("editor/EditorManager"),
37 | _ = brackets.getModule("thirdparty/lodash");
38 |
39 | // my modules
40 | var BookmarksView = require("view/BookmarksView").BookmarksView,
41 | ExtensionStrings = require("strings");
42 |
43 |
44 | /** @const {string} Extension Command ID */
45 | var MY_MODULENAME = "bracketsEditorBookmarks";
46 | var CMD_TOGGLE_BOOKMARK = "bracketsEditorBookmarks.toggleBookmark",
47 | CMD_GOTO_NEXT_BOOKMARK = "bracketsEditorBookmarks.gotoNextBookmark",
48 | CMD_GOTO_PREV_BOOKMARK = "bracketsEditorBookmarks.gotoPrevBookmark",
49 | CMD_TOGGLE_BOOKKMARK_VIEW = "bracketsEditorBookmarks.toggleBookmarksPanel";
50 |
51 | /* Our extension's preferences */
52 | var prefs = PreferencesManager.getExtensionPrefs(MY_MODULENAME);
53 |
54 | // Bookmarks Data Model
55 | var _bookmarks = {};
56 |
57 | // Bookmarks Panel
58 | var _bookmarksPanel = null;
59 |
60 | /**
61 | * Saves bookmarks to the data model for the specified editor instance
62 | * @param {Editor=} editor - brackets editor instance. current editor if null
63 | * @return {?Array.} array of cached bookmarked line numbers
64 | */
65 | function saveBookmarks(editor) {
66 | if (!editor) {
67 | editor = EditorManager.getCurrentFullEditor();
68 | }
69 | if (editor) {
70 | var i,
71 | fullPath = editor.document.file.fullPath,
72 | cm = editor._codeMirror,
73 | lineCount = cm.doc.lineCount(),
74 | bookmarkedLines = [];
75 |
76 | for (i = 0; i < lineCount; i++) {
77 | var lineInfo = cm.lineInfo(i);
78 |
79 | if (lineInfo.wrapClass && lineInfo.wrapClass.indexOf("bookmark") >= 0) {
80 | bookmarkedLines.push(i);
81 | }
82 | }
83 |
84 | // we need to sort so that go to next bookmark works
85 | bookmarkedLines.sort(function (a, b) {
86 | return a > b;
87 | });
88 |
89 | _bookmarks[fullPath] = bookmarkedLines;
90 | prefs.set("bookmarks", _bookmarks);
91 |
92 | $(_bookmarks).triggerHandler("change");
93 |
94 | // return the bookmarks for the editor
95 | return bookmarkedLines;
96 | }
97 | return null;
98 | }
99 |
100 | /**
101 | * Updates bookmarks for the current editor if necessary
102 | * @param {Editor=} editor - brackets editor instance. current editor if null
103 | * @return {Boolean} true if there are bookmarks for the current editor, false if not
104 | */
105 | function updateBookmarksForCurrentEditor() {
106 | var result = false,
107 | editor = EditorManager.getCurrentFullEditor();
108 | if (editor) {
109 | var fullPath = editor.document.file.fullPath,
110 | bm = _bookmarks[fullPath];
111 |
112 | // if there was already data then we
113 | // don't need to rebuild it
114 | result = (bm && bm.length);
115 |
116 | if (!result) {
117 | // there was no deta for this file so
118 | // rebuild the model just for this file
119 | // from what is in the editor currently
120 | result = Boolean(saveBookmarks(editor));
121 | }
122 | }
123 |
124 | return result;
125 | }
126 |
127 | /**
128 | * Resets the bookmarks for the file opened in the specified editor
129 | * NOTE: When the bookmarks for the current editor are needed
130 | * (for traversal or to update the bookmarks panel),
131 | * updateBookmarksForCurrentEditor is called which updates
132 | * incrementally the bookmarks for the current file
133 | * @param {!Editor} editor - brackets editor instance
134 | */
135 | function resetBookmarks(editor) {
136 | if (editor) {
137 | delete _bookmarks[editor.document.file.fullPath];
138 | $(_bookmarks).triggerHandler("change");
139 | }
140 | }
141 |
142 | /**
143 | * Loads the cached bookmarks into the specified editor instance
144 | * @param {Editor=} editor - brackets editor instance. current editor if null
145 | */
146 | function loadBookmarks(editor) {
147 | if (!editor) {
148 | editor = EditorManager.getCurrentFullEditor();
149 | }
150 | if (editor) {
151 | var cm = editor._codeMirror,
152 | bm = _bookmarks[editor.document.file.fullPath];
153 |
154 | if (bm) {
155 | bm.forEach(function (lineNo) {
156 | if (lineNo < cm.doc.lineCount()) {
157 | cm.addLineClass(lineNo, "wrap", "bookmark");
158 | }
159 | });
160 | }
161 | }
162 | }
163 |
164 |
165 | /**
166 | * Removes all bookmarks from the editor
167 | * @param {!Editor} editor - brackets editor instance.
168 | */
169 | function clearBookmarks(editor) {
170 | var i,
171 | cm = editor._codeMirror,
172 | lineCount = cm.doc.lineCount();
173 |
174 | for (i = 0; i < lineCount; i++) {
175 | cm.removeLineClass(i, "wrap", "bookmark");
176 | }
177 | }
178 |
179 | /**
180 | * Resets all bookmark model data so it can be re-read from prefs
181 | */
182 | function resetModel() {
183 | Object.keys(_bookmarks).forEach(function (prop) {
184 | delete _bookmarks[prop];
185 | });
186 | }
187 |
188 | /**
189 | * Loads bookmark model from prefs
190 | */
191 | function loadModel() {
192 | resetModel();
193 | _.assign(_bookmarks, prefs.get("bookmarks"));
194 | }
195 |
196 | /**
197 | * Reloads the bookmark model, clearing the current bookmarks
198 | * @param {!Editor} editor - brackets editor instance.
199 | */
200 | function reloadModel() {
201 | DocumentManager.getAllOpenDocuments().forEach(function (doc) {
202 | if (doc._masterEditor) {
203 | clearBookmarks(doc._masterEditor);
204 | }
205 | });
206 |
207 | loadModel();
208 |
209 | DocumentManager.getAllOpenDocuments().forEach(function (doc) {
210 | if (doc._masterEditor) {
211 | loadBookmarks(doc._masterEditor);
212 | }
213 | });
214 |
215 | // update the panel
216 | $(_bookmarks).triggerHandler("change");
217 | }
218 |
219 | /**
220 | * Moves the cursor position of the current editor to the next bookmark
221 | * @param {!Editor} editor - brackets editor instance
222 | */
223 | function gotoNextBookmark(forward) {
224 | if (updateBookmarksForCurrentEditor()) {
225 | var editor = EditorManager.getCurrentFullEditor(),
226 | cursor = editor.getCursorPos(),
227 | bm = _bookmarks[editor.document.file.fullPath];
228 |
229 | var doJump = function (lineNo) {
230 | editor.setCursorPos(lineNo, 0);
231 |
232 | var cm = editor._codeMirror;
233 | cm.addLineClass(lineNo, "wrap", "bookmark-notify");
234 | setTimeout(function () {
235 | cm.removeLineClass(lineNo, "wrap", "bookmark-notify");
236 | }, 100);
237 | };
238 |
239 | // find next bookmark
240 | var index;
241 | for (index = (forward ? 0 : bm.length - 1); forward ? (index < bm.length) : (index >= 0); forward ? (index++) : (index--)) {
242 | if (forward) {
243 | if (bm[index] > cursor.line) {
244 | doJump(bm[index]);
245 | return;
246 | }
247 | if (index === bm.length - 1) {
248 | // wrap around just pick the first one in the list
249 | if (bm[0] !== cursor.line) {
250 | doJump(bm[0]);
251 | }
252 | return;
253 | }
254 | } else {
255 | if (bm[index] < cursor.line) {
256 | doJump(bm[index]);
257 | return;
258 | }
259 | if (index === 0) {
260 | // wrap around just pick the last one in the list
261 | if (bm[bm.length - 1] !== cursor.line) {
262 | doJump(bm[bm.length - 1]);
263 | }
264 | return;
265 | }
266 | }
267 | }
268 | }
269 | }
270 |
271 | /**
272 | * Toogles the bookmarked state of the current line of the current editor
273 | */
274 | function toggleBookmark() {
275 | var editor = EditorManager.getCurrentFullEditor();
276 | if (editor) {
277 | var cursor = editor.getCursorPos(),
278 | lineNo = cursor.line,
279 | cm = editor._codeMirror,
280 | lineInfo = cm.lineInfo(cursor.line);
281 |
282 | if (!lineInfo.wrapClass || lineInfo.wrapClass.indexOf("bookmark") === -1) {
283 | cm.addLineClass(lineNo, "wrap", "bookmark");
284 | } else {
285 | cm.removeLineClass(lineNo, "wrap", "bookmark");
286 | }
287 | resetBookmarks(editor);
288 | }
289 | }
290 |
291 | /**
292 | * Creates the bookmarks panel if it's truly needed
293 | * @param {Boolean} panelRequired - true if panel is required. False if not
294 | */
295 | function createBookmarksPanelIfNecessary(panelRequired) {
296 | if (!_bookmarksPanel && panelRequired) {
297 | _bookmarksPanel = new BookmarksView(_bookmarks, updateBookmarksForCurrentEditor);
298 |
299 | $(_bookmarksPanel).on("close", function () {
300 | CommandManager.get(CMD_TOGGLE_BOOKKMARK_VIEW).setChecked(_bookmarksPanel.isOpen());
301 | });
302 | }
303 | }
304 |
305 | /**
306 | * Shows the bookmarks panel
307 | * @param {Boolean} show - true to show the panel, false to hide it
308 | * @param {{show:string=}=} options - undefined, {show: undefined|"opened"|"project"|"all"}, defaults to "opened"
309 | */
310 | function showBookmarksPanel(show, options) {
311 | // we only need to create it if we're showing it
312 | createBookmarksPanelIfNecessary(show);
313 | if (!_bookmarksPanel) {
314 | // nothing to do, panel wasn't created
315 | return;
316 | }
317 |
318 | // show/hide the panel
319 | if (show) {
320 | _bookmarksPanel.open(options);
321 | } else {
322 | _bookmarksPanel.close();
323 | }
324 |
325 | // update the command state
326 | CommandManager.get(CMD_TOGGLE_BOOKKMARK_VIEW).setChecked(_bookmarksPanel.isOpen());
327 | }
328 |
329 | /**
330 | * Creates and/or Shows or Hides the bookmarks panel
331 | */
332 | function toggleBookmarksPanel() {
333 | // always create it
334 | createBookmarksPanelIfNecessary(true);
335 | showBookmarksPanel(!_bookmarksPanel.isOpen(), prefs.get("viewOptions"));
336 | // Since this is the only user-facing command then
337 | // we can safely update the prefs here...
338 | // Updating it in showBookmarksPanel could result in
339 | // a race condition so we would need a way to
340 | // indicate whether we were initializing from prefs
341 | // or some other method in showBookmarksPanel.
342 | // For now, we can just assume that showBookmarksPanel
343 | // is not a consumable API, just a helper
344 | prefs.set("panelVisible", _bookmarksPanel.isOpen());
345 | }
346 |
347 | /**
348 | * Updates the state from prefs
349 | */
350 | function updateFromPrefs() {
351 | reloadModel();
352 | showBookmarksPanel(prefs.get("panelVisible"), prefs.get("viewOptions"));
353 | }
354 |
355 |
356 | // load our styles
357 | ExtensionUtils.loadStyleSheet(module, "styles/styles.css");
358 |
359 | // register our commands
360 | CommandManager.register(ExtensionStrings.TOGGLE_BOOKMARK, CMD_TOGGLE_BOOKMARK, toggleBookmark);
361 | CommandManager.register(ExtensionStrings.GOTO_PREV_BOOKMARK, CMD_GOTO_PREV_BOOKMARK, _.partial(gotoNextBookmark, false));
362 | CommandManager.register(ExtensionStrings.GOTO_NEXT_BOOKMARK, CMD_GOTO_NEXT_BOOKMARK, _.partial(gotoNextBookmark, true));
363 |
364 | // add our menu items
365 | var menu = Menus.getMenu(Menus.AppMenuBar.NAVIGATE_MENU);
366 |
367 | menu.addMenuDivider();
368 | menu.addMenuItem(CMD_TOGGLE_BOOKMARK, "Ctrl-Shift-K");
369 | menu.addMenuItem(CMD_GOTO_NEXT_BOOKMARK, "Ctrl-P");
370 | menu.addMenuItem(CMD_GOTO_PREV_BOOKMARK, "Ctrl-Shift-P");
371 |
372 | menu = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU);
373 | CommandManager.register(ExtensionStrings.TOGGLE_BOOKMARKS_PANEL, CMD_TOGGLE_BOOKKMARK_VIEW, toggleBookmarksPanel);
374 | menu.addMenuDivider();
375 | menu.addMenuItem(CMD_TOGGLE_BOOKKMARK_VIEW);
376 |
377 | // define prefs
378 | prefs.definePreference("bookmarks", "object", {});
379 | prefs.definePreference("panelVisible", "boolean", false);
380 | prefs.definePreference("viewOptions", "object", {});
381 |
382 | // Initialize
383 | loadModel();
384 | showBookmarksPanel(prefs.get("panelVisible"), prefs.get("viewOptions"));
385 |
386 | // event handlers
387 | // NOTE: this is an undocumented, unsupported event fired when an editor is created
388 | // @TODO: invent a standard event
389 | EditorManager.on("_fullEditorCreatedForDocument", function (e, document, editor) {
390 | editor.on("beforeDestroy.bookmarks", function () {
391 | saveBookmarks(editor);
392 | editor.off(".bookmarks");
393 | document.off(".bookmarks");
394 | });
395 | document.on("change.bookmarks", function () {
396 | resetBookmarks(editor);
397 | });
398 | loadBookmarks(editor);
399 | });
400 |
401 | // prefs change handler, dump everything and reload from prefs
402 | prefs.on("change", updateFromPrefs);
403 |
404 | });
405 |
--------------------------------------------------------------------------------