SidenotesExternalize and keep organized your comments. FeaturesThis extension provides you an inobtrusive way to annotate your code with external notes, that are stored separately from your document and are shown in pop-ups on hover.
MotivationMany times we all heard a saying that good code documents itself. To a certain extent it's true, but sometimes you need to make some extended notes regarding to particular part of your code, that the code just can't say for itself. A common case is describing why your wrote your code in such a way to remember later and don't make the same mistake twice. There also could be some ideas, detailed 'todos', issue analysis, conclusions, alternative code variants or something alike that you what to recall later when revising your code. How should you manage this information? Comments are usually the poor tool for this job. Too many / too large comments clutter your code and make it hard to concentrate on the code itself. But delete them - and you may miss some important point later. Unfortunately, VSCode has no way to hide/fold all comments. The other consideration is privacy. There may be notes that are private in nature and are not intended to be seen for other people, who might happen to read / edit your code. With usual comments there's no usual way to help it, if your code is commited under VCS other than delete them altogether. The solution is to 'externalize' your notes, but keep them anchored to certain lines of your code, so that you can easily peek/edit them at any time. How it worksSidenotes content are stored in separate files ('content files'), that are linked to the source document via the special comments in your code(anchor comments). 'Content' side and 'source' document side are linked via the common unique id that is stored in anchor comment and is used to fetch associated content from content file. Supported extensions and languagesSource documentThe extension uses VSCode 'toggle comment' action to generate anchors, that allows it to be agnostic about language the document is written in. Therefore, you can annotate any file format that allows comments inside it. You can even annotate sidenotes themselves with another sidenotes! Nevertheless, it is recommended to set some restrictions as to what kind of files can be annotated, to speed up workspace-wide scan (which is performed by 'housekeeping' commands perform, for example) by excluding certain extensions and directories. You can do it with appropriate glob (see Files filter). Content filesUsually Markdown is the best choice for a simple sidenote, since it allows for simple editing and useful features such as code fences and syntax highlighting. So ImagesPlacing imagesIf you want to display an image or some other html-supported content, you can do this by stuffing it inside Markdown file. For the local files, you should place the files you are attaching into '${filename}.assets' subdirectory in your notes subfolder. Doing so will prevent these files from appearing as 'stray' during your content directory clean-up. You can do it manually, or there is also an option to do exactly that in Typora. Take care though, that if you happen to just move image link from one sidenote to another without changing Simple absolute paths do not work for markdown images in VScode. You have several options:
Linking online images with URL works fine. CommandsAnnotateThe main command that is used for both creating new and opening existing sidenotes (depending on whether you use it on the line that already contains sidenote), so you can use just one convenient key binding for both. If called while hovering over existing sidenote anchor, it opens associated content file for editing. When creating new sidenote, if no text is selected, a new line is created above current cursor position and anchor marker is placed there. In selection is made, it is transferred to created file, and all selected lines are replaced with sidenote marker line. If resource is not found, running this command displays a dialog window, where you can choose from several options:
Annotate (Code)Same as annotate, but if used with selection made, this command automatically wraps current selection in code fence (see Externalizing content(#Externalizing content)). Annotate (Input Extension)Same as annotate, but when creating a new note, this command presents you with an input field where you can type in custom extension for your content file. Annotate (Input Extension)Same as annotate, but when creating a new note, this command presents you with a dropdown list of extensions so you can select the one you need. List options can be edited in configuration DeleteDeletes both content file and all associated anchors from current document. (See Deleting sidenotes). Wipe anchorDeletes comment anchor (without deleting content file). Can be useful if you have several anchors for one note and want to delete one of them. RefreshResets decorations for document, rescans and rebuilds them (in case something has gone awry). Switch Active SignatureSwitches the signature that is used for the new sidenotes. Change SignatureChanges the signature of the existing sidenote Switches signature that is used for the new sidenotes. Toggle markersToggles visibility of markers. If you set full markers visisble by default in configuration, this command will hide them instead. Prune brokenCommand is used to delete all broken notes in current document. Prune emptyCommand is used to delete all empty notes in current document. Clean UpSearches for extraneous (orphan) and stray (accidental) content records in your storage and prompts you to delete them. (See housekeeping) MigrateSearches for 'broken' comment anchors and performs global lookup for missing content files. (See migrating notes) Configuration optionsAll configuration settings must be prepended with 'sidenotes.' in your settings.json, ex. 'sidenotes.hoverToolbar'. App settingshoverToolbardefault: true The extension uses vscode.hoverProvider to show convenience button links at the bottom of the tooltip. This (probably) can slow things down a little so if you don't need it you can turn this off. Note that due to the lack of negation support in VSCode glob patterns (and, namely, document selectors), your filter settings will not have effect here, so hover buttons toolbar will be working in all files. defaultMarkdownEditordefault: "vscode" The default editor that will be used to open your sidenotes that use markdown file formats. The available options are: vscodeBy default, sidenote will open in vscode's rightmost panel for editing. system defaultThe sidenote will open in whatever program is specified in your OS as default for the content file extension. Uses 'Open' npm module for cross-platform compatibility. typoraTo use this option, you must have Typora installed in your system and 'typora' executable in the system PATH. Typora is a special case due to some problems that don't allow to open it from VScode as system default editor (at least on Windows). So I wrote special extension to let you do this. Generally, I recommend to leave VScode as default and resort to Typora when you need extensive editing, using open-in-typora extension. Workspace FilterVscode GlobPattern (relative to your workspace folder) to specify files and directories which your want to be available for annotation. Files excluded by filter are not scanned for anchors and cannot be annotated. See vscode.GlobPattern for syntax details. filter.includedefault: "**/*" vscode GlobPattern to specify files and directories which your want to be available for annotation. filter.excludedefault: "**/{node_modules,.git,.idea,target,out,build,vendor}/**/*" vscode GlobPattern to exclude files and directories which your don't want to be annotated. Glob is inverted automatically so you don't have to prepend it with ! here. StoragenotesSubfolderdefault: ".sidenotes" if the File Storage is used (which is by default) defines a subfolder inside your workspace, where content files will be stored. Note that inside this directory another subdirectory is created, named after your signature setting. This is done to separate notes by different authors. defaultContentFileExtensiondefault: ".md" Default extension for content files. You can change it to whatever you like, but Markdown is recommended. extensionsQuickPickdefault: [] List of extensions available for quick pick when using Annotate (Pick) command. anchor configurationThe extension uses certain Regex, based on unique id, to identify sidenote anchors in your source document and operate on them. SignaturesIf you collaborate with your colleague, who also uses Sidenotes, your files may contain sidenotes markers from both you and your colleague ('foreign' markers). Without signature setting, they all will be handled by extension. This has disadvantages:
It is usually sensible to use as your signature you Github login to prevent possible conflicts. If you and your colleague want to share sidenotes, no problem: you can either use some common signature when authoring, for example, 'Shared', or none at all. Or each can add his colleague's signature to his If you want to change signature, you can manually edit the signature of marker in the document. You can have several signatures specified under signatureFilterdefault: false This is an array of signatures that you want to be processed when looking for sidenote markers in document. If this setting is not set, all signatures are processed. Youtr own signature is automatically added to filter so that it is always corresponds to signature setting and always proccesed. readUnsigneddefault: true Whether to process markers that have no signature. signaturedefault: your username (defined in OS) This will be your signature that will be written down in every comment. Specified string is added at the beginning of the marker, that will be included in search RegExp. Signature helps in understanding to whom the sidenote belongs to, even when extension is inactive.
Your signature, if specified, is automatically added to the riggedSignaturesdefault: [] A list of signatures you can switch between. prefixdefault: undefined Adds the string that you specify here at the beginning of the inserted marker and removes it on sidenote deletion. Note that in constrast to 'before' setting this is the actual text that will be added, i.e. it is a part of the document and it will be visible when extension is deactivated. It will be written in your document but will not affect Regex search. Useful if you want to hook your sidenotes to some comment-styling extension (see styling). design.beforedefault: undefined Adds the string that you specify as a pseudo-element at the start of all of your markers. So it's plainly decorative and you cannot hook-up any external extensions on it. design.afterdefault: "🕮" Is shown at the end of the marker, and stays in place of it when the marker is compressed. You can change the default Unicode symbol to your own string or Unicode symbol here. Changes color to visualize sidenote's state. You can use some funky Unicode emoji here, but note that they cannot change color, so to track sidenote status you'll need gutter icons. If you aim for true minimalism, you can use simple Unicode symbol and turn off gutter icons. design.gutterIconWhether to show icons in gutter. If you don't like them or use other extension which shows gutter icons (see styling) you can turn this off. design.rulerWhether sidenotes will be shown in Overview ruler design.hideMarkersEffectively hides the uuid part of markers to reduce cluttering by applying a negative letter-spacing to marker decoration. See [Hiding ids](#Hiding ids) design.colorIndicationArray of strings that defines what elements will change color, indicating sidenote status. Available values are "after", "text", "ruler". Deleting sidenotes
There may be times that you don't want to delete the content file (for example, you have another associated anchors that point to it) and want to delete only anchor. Technically in this case you can manually delete it (easily done with Ctrl-Shift-K shortcut - delete line action), but in this way decorations will not be updated and you may end up with residual artefacts. For this reason Hiding ids (markers folding)Uuids in anchor comments are necessary, but not the most pleasant thing to see in your code. By default extension hides them (in fact, compresses) so they are not visible and 'after' pseudoelement is displayed in place of an anchor. This has a one downside, that is precise selecting marker by dragging the mouse becomes a non-trivial task. To overcome this, use Ctrl-C - Ctrl-X commands to copy / cut the whole line containing anchor marker, since in VSCode you don't have to select the whole line in order to cut/copy/delete it. You can use Externalizing contentFor you convenience, when you create new sidenote, if you have some text selected, this text is removed from your document and placed inside sidenote, so you don't have to cut and paste it by hand. Special Prefixing and additional styling your sidenotesManual commentingYou can manually type in some short charasteristic description for your note (before or after it). It will look like this:
This can be used to make certain sidenotes stand out, if your prefix sidenote with !, ? etc. special characters and use one of comment-styling vscode extensions. I recommend Better comments or Deco comments for this purpose. Prefixing all sidenotesYou can use prefix option to prepend some text to all of your sidenotes. It is essentially the same as above, but automatically made for all your sidenotes. This option can be useful in conjunction with Comment anchors extension to make all your sidenotes show up in comment anchors' navigation pane, if you set your prefix to one of predefined comment anchor types, such as 'NOTE '. You can also do this, making use of integrated unicode uuid prefix. To do so, you'll have to create create custom anchor type in comment anchor settings.json like this:
Multiple anchors for the same sidenoteYou can can have more than one anchor for content file, if you manually copy anchor comment. Repeating anchors in the same document will be highlighted with colored dotted border for easier discerning (its color is randomly generated for each group). When you delete sidenote with To delete only one of anchors use HousekeepingBy default, local directory inside your workspace folder is used to store notes. This lets you put your sidenotes under VCS control and commit them with the rest of your project (see VCS). However, because storage is workspace-bound, this imposes some difficulties, one of them is the need to migrate your notes, if you want to move/copy your source document to another project/workspace. Note that in order for extension with file storage used to work, you need to have workspace open in VSCode. You cannot annotate documents that are outside of (one of) currently opened workspace folder(s) - if you try, the extension will warn you. Broken notesBroken sidenote is defined as note, for which there's a leftover comment anchor in your source document, but associated content file is missing. Extension automatically detects such notes and highlights them in red. When you are trying to open 'broken' sidenote. There' s a couple of options opened for you. You can:
In latter case you have to specify the directory when the sidenote is stored through 'open file' dialog. Make sure you select the directory that immideately contains the file (nested files are not detected). You also can use Empty sidenotesEmpty sidenote is defined as note, which content file is empty. Those are automatically detected and highlighted in orange. You can use Migrating notes to new projectThere will be times you'll want to move your files to another project. If you just do it without copying sidenotes directory with them, you will left up with broken notes. To manage this,
So, the proposed order of actions when migrating annotated files to new project is as follows:
Cleaning extraneous and stray filesIf there are content files left in your sidenotes subfolder that are not associated with any anchors in your project folder files, those are defined as extraneous. You can run There's also a stray files category which is also covered by Other storage types (to be implemented)Potentially, note's contents can be stored in centralized database or cloud service (such as Evernote). This has some benefits, (no need to migrate your files between projects) but makes sidenotes independent of VCS control (see VCS considerations). VCS considerationsIt's up to you whether you want to commit your sidenotes to VCS or leave them off. Commiting has the benefit that any repositiory version you checkout with VCS will have sidenotes in accordance to this version state. It is useful if sidenote is coupled tightly with the code and you want to keep ot 'in sync' with annotated document. Therefore, it is generally recommended. But, your notes won't be private that way (one way to help it is to use something like git-encrypt) to encrypt your notes folder. You can also exclude your sidenotes folder from VCS. In that case, you get notes privacy (they won't be commited and therefore shared with other collaborators through VCS), but you are at risk of getting 'extraneous' or 'broken' notes if you check out the version where sidenote anchor still doesn't exist, or, otherwise, still exists though you could have deleted note and content file in one of later versions. However, if you really want the sidenote to be independent of VCS, it's the way to go. However, if you want to exclude, it is recommended that you do it via global git exclude rather than .gitignore. Removing anchors during buildIf your workflow involves some kind of biuld process, usually you'll want to delete sidenote comments during build process. If you do it on 'delete-all-comments' basis, using your minifier, for example, sidenote comments will be deleted together with all others (since they are just simple comments). If you want to delete sidenote comments only, you'll probably match them with Regexp. RequirementsFor 'typora' setting to work, you need Typora installed on your system and typora.exe in your system PATH. Known Issues / GotchasAnchor comments will be present in your code.The only way all this can work is comment anchors must be persisted in your code, there's no help for it. It's not really big problem, since Sidenotes are intended to use in development only and if your code undergoes some sort of build process or minification, when comments are usually deleted from your code (see Removing anchors during build(#Removing anchors during build)). But, if you collaborate on code with other people who aren't acquainted with sidenite comments, in order to not scare them too much with uuids in tyou code, it can be a good idea to place some explanation/warning in your repository README so that your collaborators ignore these comments and won't delete them (but if they do, though, you can restore it via VCS). You need language supportComment toggling won't work if you don't have language support installed and enabled for this kind of files (because otherwise it will not know what syntax of comments to use). Manually moving / cutting / copying markersWhen you manually move / copy / paste your anchor markers, the decorations need to be updated to account for the new marker position, until then they will be rendered at their old position. Sadly, VSCode currently has no way of detecting cut events, so the closest event you can get after moving your marker is the document change event, which happens after you paste your text. On this event extension will scan changes and update decorations if any markers are involved. So, when you cut fragment of code that contains sidenote markers, the decorations will stay in their old place until you paste your code / switch editors. Also, 'undo' in vscode doesn't trigger 'editor change' event, so after undoing adding new sidenote, you may have to manually Moving sidenote to the document with another syntaxObviously, if you want to move your sidenote to other file, that uses different comment syntax (according to language used), you'll have to manually edit comment to match (tip: untoggle comment before moving, then toggle back after); Since sidenotes scanning is done lazily, you have to make editor active to initialize it. This can be seen on application start if you have several editors visible simultaneosly in different panes. Anyway, in case of unpredictable rendering artifacts you can use Multiline commentsFor the languages, that support only multiline, notably HTML / XML / Markdown / CSS, comments folding doesn't play well in latest versions of VS Code in the way that you will have trouble seeing hover tooltip preview on such comments, if folded. The reason is the tooltip is not displayed over 'after" pseusdoelement for such comments. To do so, you'll need either to place your cursor at the beginning of the icon and take a good aim with your mouse, or - a bit easier - to drag-select comment (or even a whole document with Ctrl-A), and than aim at the icon with your mouse. Anyway, the only alternative I can think of currently is to introduce a two decorations for each sidenote (one to show tooltip and another to fold the anchor), which I don't find feasible. AlternativesHow is it different from Codestream
CreditsThough extension concept idea occured to me independently, some initial implementation ideas came from marginalia by James Norton Icon made by Kiranshastry from www.flaticon.com
## By me a beer:
|