1. Project Overview & Quickstart (pulsar-edit/pulsar)
File: README.md
ββ
ββ
ββ
ββ
ββ
Pulsar
A Community-led Hyper-Hackable Text Editor,
Forked from Atom, built on Electron.
Designed to be deeply customizable, but still
approachable using the default configuration.
File: docs/architecture/overview.md
Pulsar's High Level Startup Overview
It's no secret that Pulsar since inherited from Atom, is a big and complex application.
With many discrete, moving aspects, that not all developers have a concrete grasp on.
The goal of this document is to make the architecture of Pulsar, as well as the logical flow
more understandable and approachable.
This will be accomplished through a series of illustrations detailing the functional decomposition and detailed logical flow of Pulsar and it's parts, as well as lists of what's accomplished in each part.
This document is aimed at those roughly familiar with the large scale goals and features of Pulsar, as well as those with a basic understanding of the package model used to power much of Pulsar's functionality.
MermaidJS to create image above
flowchart TD
id1("`Initialization
*./src/main-process/main.js*`") --> id2("`Startup
*./src/main-process/start.js*`")
id2 --> id3("`Main Process Tests`")
id2 --> id4("`Application Startup
*./src/main-process/atom-application.js*`")
id2 --> id5("`Startup w/ Squirrel
*./src/main-process/squirrel-update.js*`")
id4 --> id6("`Test Runner
*./src/initialize-test-window.js*`")
id4 --> id7("`Initialize Application Window
*./src/initialize-application-window.js*`")
id7 --> id9("`'The World'
*./src/atom-environment.js*`")
id7 --> id10("`ApplicationDelegate
*./src/application-delegate.js*`")
id7 --> id8("`Clipboard
*./src/clipboard.js*`")
id8 --> id9
id10 --> id9To further outline what occurs in the steps above:
Initialization
Startup of Pulsar occurs within ./src/main-process/main.js.
Which Determines:
resourcePathdevResourcePathstableResourcePathdefaultRepositoryPath
Which Sets:
- Application Start Time
Which Does:
- Initializes Startup of
./src/main-process/start.js
Startup
The more general startup handling of Pulsar occurs within ./src/main-process/start.js.
Which Sets:
- Shell Start Time
app.allowRendererProcessReuse:falseapp.commandLine.appendSwitch('enable-experimental-web-platform-features')app.commandLine.appendSwitch('force-color-profile', config.get('core.colorProfile'))app.setAppUserModelId()app.on('open-file', $)app.on('open-url', $)
Which Does:
- Normalizes the
resourcePathanddevResourcePath - Uses
Configto locate and read the config file atomPaths.setAtomHome()atomPaths.setUserData()- May defer to
./src/main-process/squirrel-update.jsto startup if on Windows - May defer to
./spec/main-process/mocha-test-runner.jsto startup main process tests - May call
.open()on./src/main-process/atom-application.js
Application Startup
The proper startup of the Pulsar Application occurs within ./src/main-process/atom-application.js.
Which Sets:
APPLICATION_STATE_VERSION- Global
atomApplication
Which Does:
- Does setup of the application socket
- Handles deprecated benchmark startup
- Ensures to return a new instance of
AtomApplication - Registers basic application commands
- Initializes:
ApplicationMenuAtomProtocolHandlerWindowStackFileRecoveryServiceConfigStorageFolderAutoUpdateManager
- May startup the package test runner
- May quit if asked to startup in benchmark mode
- May open previously opened files/folders
- May open new instance of Pulsar
Initialize Application Window
Begins initialization of an individual Pulsar window, occurs within ./src/initialize-application-window.js.
Which Determines:
Which Sets:
- Sets the
global.atomto a new instance ofAtomEnvironment
Which Does:
- triggers
.preloadPackages() - Initializes:
- Clipboard
- AtomEnvironment
- ApplicationDelegate
'The World'
'The World' refers to being within the Pulsar application, most of the application occurs within here.
This code lives within ./src/atom-environment.js.
An important note about being initialized within the world, there is no access to the atom
global, until the initial constructor completes processing. Meaning great care must be taken
to ensure if atom is available within the initialized modules.
Which Sets:
AtomEnvironment.version:1| Possibly a reference toAPPLICATION_STATE_VERSION?AtomEnvironment.saveStateDebounceInterval:1000
Which Does:
- Initializes:
- Clipboard | Inherited from 'Initialize Application Window'
- ApplicationDelegate | Inherited from 'Initialize Application Window'
- DeserializerManager
- ViewRegistry
- NotificationManager
- StateStore
- Config
- KeymapManager
- TooltipManager
- CommandRegistry
- URIHandlerRegistry
- GrammarRegistry
- StyleManager
- PackageManager
- ThemeManager
- MenuManager
- ContextMenuManager
- Project
- CommandInstaller
- ProtocolHandlerInstaller
- TextEditorRegistry
- Workspace
- AutoUpdateManager
- WindowEventHandler
- HistoryManager
File: docs/architecture/package-preload.md
Package Preload
Pulsar's packages are preloaded, very early on within the startup cycle of Pulsar.
As it's called immediatly after the atom global is initialized, it's important to understand what steps occur during preloading, and what package's are affected.
MermaidJS to create image above
flowchart TD
iaw["`
initialize-application-window.js
Called right after global 'atom' is set
`"] -->
ae["`
AtomEnvironment
.preloadPackages()
`"] -->
pl1["preloadPackages()"] -->|if in packageCache| sg1
subgraph sg1
direction LR
pl2["preloadPackage()"]
pl2 -->|"call .preload()"| tp1["new ThemePackage"]
pl2 -->|"call .preload()"| p1["new Package"]
p1 --> p1Pre["`
this.preload() call:
Does more than advertised here
`"]
p1Pre --> lk1[".loadKeymaps()"]
lk1 --> pcRead1["`Read from packagesCache:
If bundled package && in packagesCache`"]
lk1 --> fileRead1["`Read from file:
If !bundled || !in packagesCache`"]
p1Pre --> lm1[".loadMenus()"]
lm1 --> pcRead1
lm1 --> fileRead1
p1Pre --> acss[".activateCoreStartupServices()"]
p1Pre --> rmm[".requireMainModule()"]
acss --> rmm
p1Pre --> ls1[".loadSettings()"]
ls1 --> pcRead1
ls1 --> fileRead1
p1Pre --> ak1[".activateKeymaps()"]
p1Pre --> am1[".activateMenus()"]
tp1 --> tp1Pre[".preload()"]
tp1Pre --> csrol1[".reigsterConfigSchemaFromMetadata()"]
endFile: docs/architecture/README.md
Pulsar Architecture
This directory contains a collection of files and diagrams, that aim to easily explain some of the core components or behaviors of Pulsar.
Remember that keeping this charts up to date is best effort, and the age of these files should be taken into consideration.
Contents
File: docs/architecture/the-world.md
'The World'
While it's difficult to convey the full scope of how Pulsar works internally, just like the previous page overview.md detailed the general gist of how Pulsar starts up, this document provides a quick reference to how all the interal parts of Pulsar are connected.
This document is not at all comprehensive, and must ensure to be continually updated. Additionally, this image does not track outside dependency usage, nor dependence on every single internal module. Focusing mostly on modules that are either required during initialization, or are referenced during the constructor of their respective class.
Details on the creation of this image
This image has been created with Plant UML. A Live editor is available here.
The code used to create this image:
@startwbs
* Initialization
** Startup
***< Main Process Tests
*** Startup w/ Squirrel
***< Application Startup
****< Test Runner
**** Initialize Application Window
***** 'The World'
******< Config
******* ScopeDescriptor
****** KemapManager
****** TolltipManager
******* Tooltip
******< CommandRegistry
******< URIHandlerRegistry
****** StyleManager
******* createStylesElement
******* DEPRECATED_SYNTAX_SELECTORS
******< MenuManager
******* MenuHelpers
****** ContextMenuManager
******* MenuHelpers
******* sortMenuItems
******< TextEditorRegistry
******* TextEditor
******* ScopeDescriptor
****** HistoryManager
******< DeserializerManager
******< ViewRegistry
****** NotificationManager
******* Notification
****** StateStore
******< PackageManager
******* Package
******* ThemePackage
******* ModuleCache
****** ThemeManager
******* LessCompileCache
****** Project
******* watchPath
******* DefaultDirectoryProvider
******* Model
******* GitRepositoryProvider
******< CommandInstaller
******< ProtocolHandlerInstaller
******< AutoUpdateManager
******< WindowEventHandler
******* listen
******< GrammarRegistry
*******< NodeTreeSitterLanguageMode
******** TreeIndenter
********< TextMateLanguageMode
******** TokenizedLine
********< ScopeDescriptor
******** matcherForSelector
********< Token
******* WASMTreeSitterLanguageNode
******** Parser
******* TextMateLanguageMode
******** TokenizedLine
********< TokenIterator
******** ScopeDescriptor
********< NullGrammar
*******< ScopeDescriptor
******* Token
****** Workspace
******* DefaultDirectorySearcher
*******< RipgrepDirectorySearcher
******* WorkspaceCenter
*******< createWorkspaceElement
******* PanelContainer
*******< StateStore
******* TextEditor
*******< Panel
******* Task
*******< Dock
@endwbsFile: docs/decisions/000-adr-template.md
These are optional elements. Feel free to remove any of them.
status: {proposed | rejected | accepted | deprecated | β¦ | superseded by ADR-0005 <0005-example.md>} date: {YYYY-MM-DD when the decision was last updated} deciders: {list everyone involved in the decision} consulted: {list everyone whose opinions are sought (typically subject-matter experts); and with whom there is a two-way communication} informed: {list everyone who is kept up-to-date on progress; and with whom there is a one-way communication}
{short title of solved problem and solution}
Context and Problem Statement
{Describe the context and problem statement, e.g., in free form using two to three sentences or in the form of an illustrative story.
You may want to articulate the problem in form of a question and add links to collaboration boards or issue management systems.}
Decision Drivers
- {decision driver 1, e.g., a force, facing concern, β¦}
- {decision driver 2, e.g., a force, facing concern, β¦}
- β¦
Considered Options
- {title of option 1}
- {title of option 2}
- {title of option 3}
- β¦
Decision Outcome
Chosen option: "{title of option 1}", because
{justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force {force} | β¦ | comes out best (see below)}.
Consequences
- Good, because {positive consequence, e.g., improvement of one or more desired qualities, β¦}
- Bad, because {negative consequence, e.g., compromising one or more desired qualities, β¦}
- β¦
Validation
{describe how the implementation of/compliance with the ADR is validated. E.g., by a review or an ArchUnit test}
Pros and Cons of the Options
{title of option 1}
{example | description | pointer to more information | β¦}
Good, because {argument a}
Good, because {argument b}
Neutral, because {argument c}
Bad, because {argument d}
β¦
{title of other option}
{example | description | pointer to more information | β¦}
- Good, because {argument a}
- Good, because {argument b}
- Neutral, because {argument c}
- Bad, because {argument d}
- β¦
More Information
{You might want to provide additional evidence/confidence for the decision outcome here and/or
document the team agreement on the decision and/or
define when and how this decision should be realized and if/when it should be re-visited and/or
how the decision is validated.
Links to other decisions and resources might appear here as well.}
2. Official Technical Reference & Guides (pulsar-edit/docs)
File: README.md
Pulsar Documentation Eleventy
This new Pulsar Documentation website utilizes eleventy.
This project superseedes previous efforts utilizing sloth as it's been determined that eleventy is the more mature implementation of the same exact goals of sloth and it makes the most sense to utilize a framework that's more mature, and requires significantly less maintenance.
Installation
npm install
git submodule init
git submodule updateRunning
npm run build: Builds the sitenpm run serve: Creates a live version of the site at:8080npm run build:debug: Builds the site with debug flags setnpm run serve:debug: Creates a live server with debug flags set
Tool Translations from current Pulsar site to this one
While obviously nearly all text should be redone, there are also some technical changes that should occur:
KDB
Switch uses of <kdb>Ctrl</kdb> to [[Ctrl]]
Images
Switch links with @images to /img
TODO's
The biggest aspects of this that still have to be completed:
- Finalize CSS implementations
- Create all EJS templates needed
- Create collections and automatically create collection views on summary pages
- Implement Dark Mode
- Implement Light Mode
- Implement Theme Switcher
- Add all original Launch Manual Docs
- Add all relevant documentation
- Implement Pulsar API Docs
- Implement Hovercards
- Update ALL Links!
- Ensure all sidebar descriptions are filled in
- Add support for syntax highlighting
- Design CSS to account for indented returns in the API view
- Find a way to generate API docs from most recent Pulsar versions
- GHA to generate new Pulsar Docs once above is done
- Wait for
pulsardocto support Coffee and enable coffee based repos to document
Style Guide
Here will be the very short, non-complete style guide:
Links to GitHub
If linking to a resource on GitHub, such as the language-git package, ensure to never include the branch.
By default if you copy paste the link to the language-git package it will look like:
https://github.com/pulsar-edit/pulsar/tree/master/packages/language-git
But in the rare event the branch name never changes, we can make simple changes now to avoid stress later, by replacing the master here with HEAD, such as:
https://github.com/pulsar-edit/pulsar/tree/HEAD/packages/language-git
Heading Levels
Within each page of markdown you should never include an <h1> heading level (#) always start on <h2> (##) as the title of the page is extracted and used as a level one heading in all cases.
Links between pages
For simplicity, and ability to find and replace links in the future, all links between pages should be from the root of the website.
Meaning start all links with / and direct to the page you are attempting to link to.
A safe exception to this rule is for anchor links on the same page, as those can just be the anchor itself.
But for all other links, please do follow this rule and do not use relative links.
Examples: When linking to /example/sub/page from /example/sub/hello
- Do:
/example/sub/page - Do NOT:
../page
Update Source Code Documentation
Auto
Create an issue against this repository, with the title formatted strictly as the new Pulsar version number.
Such as 1.124.0
Then once the issue is created, afterwards add the label update-docs
After a short time a PR will be created against the repository with the changes to go ahead and review.
Manual
- Update the JSON file
./pulsar-api/latest.jsonwith the newest Pulsar version. - Update all submodules to their latest commit, such as
git submodule update --remote --merge - Run
npm run generate:docsto trigger the documentation to be updated.
File: docs/index.md
layout: home.ejs title: Pulsar Documentation
Pulsar is an editor thatβs easy to use out of the box, but just as easy to shape to your needs.
Here youβll find everything you need to know about Pulsar: how to install it, how to use it, how to make it better, and how to make it your own.
