diff --git a/docs/user/README.md b/docs/user/README.md
index ddc6ee0485..b25e152d0a 100644
--- a/docs/user/README.md
+++ b/docs/user/README.md
@@ -1,3 +1,22 @@
+The main interface to rust-analyzer is the
+[LSP](https://microsoft.github.io/language-server-protocol/) implementation. To
+install lsp server, use `cargo install-lsp`, which is a shorthand for `cargo
+install --package ra_lsp_server`. The binary is named `ra_lsp_server`, you
+should be able to use it with any LSP-compatible editor. We use custom
+extensions to LSP, so special client-side support is required to take full
+advantage of rust-analyzer. This repository contains support code for VS Code
+and Emacs.
+
+Rust Analyzer needs sources of rust standard library to work, so you might need
+to execute
+
+```
+$ rustup component add rust-src
+```
+
+See [./features.md] document for a list of features that are available.
+
+## VS Code
Prerequisites:
@@ -15,227 +34,44 @@ following commands:
$ git clone https://github.com/rust-analyzer/rust-analyzer.git --depth 1
$ cd rust-analyzer
$ cargo install-code
-
-# for stdlib support
-$ rustup component add rust-src
```
This will run `cargo install --package ra_lsp_server` to install the server
binary into `~/.cargo/bin`, and then will build and install plugin from
`editors/code`. See
-[this](https://github.com/rust-analyzer/rust-analyzer/blob/0199572a3d06ff66eeae85a2d2c9762996f0d2d8/crates/tools/src/main.rs#L150)
+[this](https://github.com/rust-analyzer/rust-analyzer/blob/69ee5c9c5ef212f7911028c9ddf581559e6565c3/crates/tools/src/main.rs#L37-L56)
for details. The installation is expected to *just work*, if it doesn't, report
bugs!
It's better to remove existing Rust plugins to avoid interference.
-## Rust Analyzer Specific Features
+Beyond basic LSP features, there are some extension commands which you can
+invoke via Ctrl+Shift+P or bind to a shortcut. See [./features.md]
+for details.
-These features are implemented as extensions to the language server protocol.
-They are more experimental in nature and work only with VS Code.
+### Settings
-### Syntax highlighting
-
-It overrides built-in highlighting, and works only with a specific theme
-(zenburn). `rust-analyzer.highlightingOn` setting can be used to disable it.
-
-### Go to symbol in workspace ctrl+t
-
-It mostly works on top of the built-in LSP functionality, however `#` and `*`
-symbols can be used to narrow down the search. Specifically,
-
-- `#Foo` searches for `Foo` type in the current workspace
-- `#foo#` searches for `foo` function in the current workspace
-- `#Foo*` searches for `Foo` type among dependencies, excluding `stdlib`
-- `#foo#*` searches for `foo` function among dependencies.
-
-That is, `#` switches from "types" to all symbols, `*` switches from the current
-workspace to dependencies.
-
-### Commands ctrl+shift+p
-
-#### Show Rust Syntax Tree
-
-Shows the parse tree of the current file. It exists mostly for debugging
-rust-analyzer itself.
-
-#### Extend Selection
-
-Extends the current selection to the encompassing syntactic construct
-(expression, statement, item, module, etc). It works with multiple cursors. Do
-bind this command to a key, its super-useful! Expected to be upstreamed to LSP soonish:
-https://github.com/Microsoft/language-server-protocol/issues/613
-
-#### Matching Brace
-
-If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair,
-moves cursor to the matching brace. It uses the actual parser to determine
-braces, so it won't confuse generics with comparisons.
-
-#### Parent Module
-
-Navigates to the parent module of the current module.
-
-#### Join Lines
-
-Join selected lines into one, smartly fixing up whitespace and trailing commas.
-
-#### Run
-
-Shows popup suggesting to run a test/benchmark/binary **at the current cursor
-location**. Super useful for repeatedly running just a single test. Do bind this
-to a shortcut!
+* `rust-analyzer.highlightingOn`: enables experimental syntax highlighting
+* `rust-analyzer.showWorkspaceLoadedNotification`: to ease troubleshooting, a
+ notification is shown by default when a workspace is loaded
+* `rust-analyzer.enableEnhancedTyping`: by default, rust-analyzer intercepts
+ `Enter` key to make it easier to continue comments
+* `rust-analyzer.raLspServerPath`: path to `ra_lsp_server` executable
+* `rust-analyzer.enableCargoWatchOnStartup`: prompt to install & enable `cargo
+ watch` for live error highlighting (note, this **does not** use rust-analyzer)
+* `rust-analyzer.trace.server`: enables internal logging
-### On Typing Assists
+## Emacs
-Some features trigger on typing certain characters:
+Prerequisites:
-- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression.
-- Enter inside comments automatically inserts `///`
-- typing `.` in a chain method call auto-indents
+`emacs-lsp`, `dash` and `ht` packages.
+Installation:
-### Code Actions (Assists)
-
-These are triggered in a particular context via light bulb. We use custom code on
-the VS Code side to be able to position cursor.
-
-
-- Flip `,`
-
-```rust
-// before:
-fn foo(x: usize,<|> dim: (usize, usize))
-// after:
-fn foo(dim: (usize, usize), x: usize)
-```
-
-- Add `#[derive]`
-
-```rust
-// before:
-struct Foo {
- <|>x: i32
-}
-// after:
-#[derive(<|>)]
-struct Foo {
- x: i32
-}
-```
-
-- Add `impl`
-
-```rust
-// before:
-struct Foo<'a, T: Debug> {
- <|>t: T
-}
-// after:
-struct Foo<'a, T: Debug> {
- t: T
-}
-
-impl<'a, T: Debug> Foo<'a, T> {
- <|>
-}
-```
-
-- Change visibility
-
-```rust
-// before:
-fn<|> foo() {}
-
-// after
-pub(crate) fn foo() {}
-```
-
-- Introduce variable:
-
-```rust
-// before:
-fn foo() {
- foo(<|>1 + 1<|>);
-}
-
-// after:
-fn foo() {
- let var_name = 1 + 1;
- foo(var_name);
-}
-```
-
-- Replace if-let with match:
-
-```rust
-// before:
-impl VariantData {
- pub fn is_struct(&self) -> bool {
- if <|>let VariantData::Struct(..) = *self {
- true
- } else {
- false
- }
- }
-}
-
-// after:
-impl VariantData {
- pub fn is_struct(&self) -> bool {
- <|>match *self {
- VariantData::Struct(..) => true,
- _ => false,
- }
- }
-}
-```
-
-- Split import
-
-```rust
-// before:
-use algo:<|>:visitor::{Visitor, visit};
-//after:
-use algo::{<|>visitor::{Visitor, visit}};
-```
-
-## LSP features
-
-* **Go to definition**: works correctly for local variables and some paths,
- falls back to heuristic name matching for other things for the time being.
-
-* **Completion**: completes paths, including dependencies and standard library.
- Does not handle glob imports and macros. Completes fields and inherent
- methods.
-
-* **Outline** alt+shift+o
-
-* **Signature Info**
-
-* **Format document**. Formats the current file with rustfmt. Rustfmt must be
- installed separately with `rustup component add rustfmt`.
-
-* **Hover** shows types of expressions and docstings
-
-* **Rename** works for local variables
-
-* **Code Lens** for running tests
-
-* **Folding**
-
-* **Diagnostics**
- - missing module for `mod foo;` with a fix to create `foo.rs`.
- - struct field shorthand
- - unnecessary braces in use item
-
-
-## Performance
-
-Rust Analyzer is expected to be pretty fast. Specifically, the initial analysis
-of the project (i.e, when you first invoke completion or symbols) typically
-takes dozen of seconds at most. After that, everything is supposed to be more or
-less instant. However currently all analysis results are kept in memory, so
-memory usage is pretty high. Working with `rust-lang/rust` repo, for example,
-needs about 5 gigabytes of ram.
+* add
+[ra-emacs-lsp.el](https://github.com/rust-analyzer/rust-analyzer/blob/69ee5c9c5ef212f7911028c9ddf581559e6565c3/editors/emacs/ra-emacs-lsp.el)
+to load path and require it in `init.el`
+* run `lsp` in a rust buffer
+* (Optionally) bind commands like `join-lines` or `extend-selection` to keys
diff --git a/docs/user/features.md b/docs/user/features.md
new file mode 100644
index 0000000000..5df606aee0
--- /dev/null
+++ b/docs/user/features.md
@@ -0,0 +1,168 @@
+This documents is an index of features that rust-analyzer language server provides.
+
+### Go to symbol in workspace ctrl+t
+
+It mostly works on top of the built-in LSP functionality, however `#` and `*`
+symbols can be used to narrow down the search. Specifically,
+
+- `#Foo` searches for `Foo` type in the current workspace
+- `#foo#` searches for `foo` function in the current workspace
+- `#Foo*` searches for `Foo` type among dependencies, excluding `stdlib`
+- `#foo#*` searches for `foo` function among dependencies.
+
+That is, `#` switches from "types" to all symbols, `*` switches from the current
+workspace to dependencies.
+
+### Commands ctrl+shift+p
+
+#### Show Rust Syntax Tree
+
+Shows the parse tree of the current file. It exists mostly for debugging
+rust-analyzer itself.
+
+#### Extend Selection
+
+Extends the current selection to the encompassing syntactic construct
+(expression, statement, item, module, etc). It works with multiple cursors. Do
+bind this command to a key, its super-useful! Expected to be upstreamed to LSP soonish:
+https://github.com/Microsoft/language-server-protocol/issues/613
+
+#### Matching Brace
+
+If the cursor is on any brace (`<>(){}[]`) which is a part of a brace-pair,
+moves cursor to the matching brace. It uses the actual parser to determine
+braces, so it won't confuse generics with comparisons.
+
+#### Parent Module
+
+Navigates to the parent module of the current module.
+
+#### Join Lines
+
+Join selected lines into one, smartly fixing up whitespace and trailing commas.
+
+#### Run
+
+Shows popup suggesting to run a test/benchmark/binary **at the current cursor
+location**. Super useful for repeatedly running just a single test. Do bind this
+to a shortcut!
+
+
+### On Typing Assists
+
+Some features trigger on typing certain characters:
+
+- typing `let =` tries to smartly add `;` if `=` is followed by an existing expression.
+- Enter inside comments automatically inserts `///`
+- typing `.` in a chain method call auto-indents
+
+
+
+
+
+### Code Actions (Assists)
+
+These are triggered in a particular context via light bulb. We use custom code on
+the VS Code side to be able to position cursor.
+
+
+- Flip `,`
+
+```rust
+// before:
+fn foo(x: usize,<|> dim: (usize, usize))
+// after:
+fn foo(dim: (usize, usize), x: usize)
+```
+
+- Add `#[derive]`
+
+```rust
+// before:
+struct Foo {
+ <|>x: i32
+}
+// after:
+#[derive(<|>)]
+struct Foo {
+ x: i32
+}
+```
+
+- Add `impl`
+
+```rust
+// before:
+struct Foo<'a, T: Debug> {
+ <|>t: T
+}
+// after:
+struct Foo<'a, T: Debug> {
+ t: T
+}
+
+impl<'a, T: Debug> Foo<'a, T> {
+ <|>
+}
+```
+
+- Change visibility
+
+```rust
+// before:
+fn<|> foo() {}
+
+// after
+pub(crate) fn foo() {}
+```
+
+- Introduce variable:
+
+```rust
+// before:
+fn foo() {
+ foo(<|>1 + 1<|>);
+}
+
+// after:
+fn foo() {
+ let var_name = 1 + 1;
+ foo(var_name);
+}
+```
+
+- Replace if-let with match:
+
+```rust
+// before:
+impl VariantData {
+ pub fn is_struct(&self) -> bool {
+ if <|>let VariantData::Struct(..) = *self {
+ true
+ } else {
+ false
+ }
+ }
+}
+
+// after:
+impl VariantData {
+ pub fn is_struct(&self) -> bool {
+ <|>match *self {
+ VariantData::Struct(..) => true,
+ _ => false,
+ }
+ }
+}
+```
+
+- Split import
+
+```rust
+// before:
+use algo:<|>:visitor::{Visitor, visit};
+//after:
+use algo::{<|>visitor::{Visitor, visit}};
+```
+
+