diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
 # Dhall language support in VSCode/ium
 
 The Dhall language integration consists of the following parts:
-- The VSCode/ium plugin "Dhall Language Support" *([vscode-language-dhall](https://github.com/PanAeon/vscode-language-dhall))* adds syntax highlighting for Dhall files.
-- The VSCode/ium plugin "Dhall LSP Server" *([vscode-dhall-lsp-server](https://github.com/PanAeon/vscode-dhall-lsp-server))* implements the LSP client &ndash; yes, there is a naming issue here &ndash; that communicates with the backend via the [LSP protocol](https://microsoft.github.io/language-server-protocol/specification) to provide advanced language features like error diagnostics or type information, etc.
+- The VSCode/ium plugin "Dhall Language Support" *([vscode-language-dhall](https://github.com/dhall-lang/vscode-language-dhall))* adds syntax highlighting for Dhall files.
+- The VSCode/ium plugin "Dhall LSP Server" *([vscode-dhall-lsp-server](https://github.com/dhall-lang/vscode-dhall-lsp-server))* implements the LSP client &ndash; yes, there is a naming issue here &ndash; that communicates with the backend via the [LSP protocol](https://microsoft.github.io/language-server-protocol/specification) to provide advanced language features like error diagnostics or type information, etc.
 - [*dhall-lsp-server*](https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-lsp-server), which is part of the [*dhall-haskell*](https://github.com/dhall-lang/dhall-haskell) project, implements the actual LSP server (i.e. the backend) that implements those language features in an editor agnostic way, though at the moment only a VSCode/ium frontend exists.
 
 # Installation
@@ -23,7 +23,7 @@
 2. Install the *typescript* compiler with `npm install -g typescript`. I recommend running `npm config set prefix '~/.local'` first to have npm install the executable in `~/.local/bin`; this avoids having to use *sudo* and polluting the rest of the system.
 2. Check out a copy of the vscode-dhall-lsp-server repository into the VSCode/ium extensions folder
    ```
-   git clone git@github.com:PanAeon/vscode-dhall-lsp-server.git ~/.vscode-oss/extensions/vscode-dhall-lsp-server
+   git clone git@github.com:dhall-lang/vscode-dhall-lsp-server.git ~/.vscode-oss/extensions/vscode-dhall-lsp-server
    ```
    (replace `~/.vscode-oss/` with `~/.vscode/` if you use VSCode instead of VSCodium).
 3. Run the remaining commands in the checked-out directory
@@ -63,6 +63,11 @@
 
 - **Formatting and Linting&nbsp;**
 Right click and select "Format Document" to run the file through the Dhall formatter. The command "Lint and Format" can be selected via the *Command Palette* (Ctrl+Shift+P); this will run the linter over the file, removing unused let bindings and formatting the result.
+
+The default formatting behavior is to infer the character set used in the file (Unicode/ASCII operators).
+This can be overriden by using the Dhall LSP settings. For example in VS Code's `settings.json`:
+  - `"vscode-dhall-lsp-server.character-set": "ascii"` to always format using the ASCII character set
+  - `"vscode-dhall-lsp-server.character-set": "unicode"` to always format using the Unicode character set
 
 - **Annotate lets&nbsp;**
 Right-click the bound identifier in a `let` binding and select "Annotate Let binding with its type" to do exactly that.
diff --git a/dhall-lsp-server.cabal b/dhall-lsp-server.cabal
--- a/dhall-lsp-server.cabal
+++ b/dhall-lsp-server.cabal
@@ -1,5 +1,5 @@
 name:           dhall-lsp-server
-Version:        1.0.12
+Version:        1.0.13
 cabal-version:  1.12
 synopsis:       Language Server Protocol (LSP) server for Dhall
 homepage:       https://github.com/dhall-lang/dhall-haskell/tree/master/dhall-lsp-server#readme
@@ -50,10 +50,10 @@
     , containers           >= 0.5.11.0 && < 0.7
     , data-default         >= 0.7.1.1  && < 0.8
     , directory            >= 1.2.2.0  && < 1.4
-    , dhall                >= 1.35.0   && < 1.38
+    , dhall                >= 1.35.0   && < 1.39
     , dhall-json           >= 1.4      && < 1.8
     , filepath             >= 1.4.2    && < 1.5
-    , haskell-lsp          >= 0.19.0.0 && < 0.24
+    , haskell-lsp          >= 0.19.0.0 && < 0.25
     , rope-utf16-splay     >= 0.3.1.0  && < 0.4
     , hslogger             >= 1.2.10   && < 1.4
     , lens                 >= 4.16.1   && < 4.20
@@ -105,9 +105,9 @@
     GHC-Options: -Wall
     Build-Depends:
         base                                   ,
-        haskell-lsp-types >= 0.19.0  && < 0.24 ,
-        lsp-test          >= 0.9     && < 0.12  ,
-        tasty             >= 0.11.2  && < 1.4  ,
+        haskell-lsp-types >= 0.19.0  && < 0.25 ,
+        lsp-test          >= 0.9     && < 0.13 ,
+        tasty             >= 0.11.2  && < 1.5  ,
         tasty-hspec       >= 1.1     && < 1.2  ,
         text              >= 0.11    && < 1.3
     Build-Tool-Depends: dhall-lsp-server:dhall-lsp-server
diff --git a/src/Dhall/LSP/Backend/Completion.hs b/src/Dhall/LSP/Backend/Completion.hs
--- a/src/Dhall/LSP/Backend/Completion.hs
+++ b/src/Dhall/LSP/Backend/Completion.hs
@@ -124,7 +124,7 @@
 
     in buildCompletionContext' context' values' e
 
-buildCompletionContext' context values (Lam (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A}) b) =
+buildCompletionContext' context values (Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A}) b) =
   let _A' | Right _ <- typeWithA absurd context _A = normalize _A
           | otherwise = holeExpr
 
@@ -133,7 +133,7 @@
 
     in buildCompletionContext' context' values' b
 
-buildCompletionContext' context values (Pi x _A b) =
+buildCompletionContext' context values (Pi _ x _A b) =
   let _A' | Right _ <- typeWithA absurd context _A = normalize _A
           | otherwise = holeExpr
 
@@ -188,7 +188,7 @@
     let constructor (k, Nothing) =
             Completion (Dhall.Pretty.escapeLabel True k) (Just _A)
         constructor (k, Just v) =
-            Completion (Dhall.Pretty.escapeLabel True k) (Just (Pi k v _A))
+            Completion (Dhall.Pretty.escapeLabel True k) (Just (Pi mempty k v _A))
      in map constructor (Dhall.Map.toList m)
   completeUnion _ _ = []
 
diff --git a/src/Dhall/LSP/Backend/Formatting.hs b/src/Dhall/LSP/Backend/Formatting.hs
--- a/src/Dhall/LSP/Backend/Formatting.hs
+++ b/src/Dhall/LSP/Backend/Formatting.hs
@@ -1,5 +1,6 @@
 module Dhall.LSP.Backend.Formatting (formatExpr, formatExprWithHeader) where
 
+import Data.Maybe   (fromMaybe)
 import Data.Text    (Text)
 import Dhall.Core   (Expr)
 import Dhall.Parser (Header (..))
@@ -11,20 +12,23 @@
 import qualified Dhall.Pretty
 
 -- | Pretty-print the given Dhall expression.
-formatExpr :: Pretty.Pretty b => CharacterSet -> Expr Src b -> Text
-formatExpr charSet expr =
+formatExpr :: Pretty.Pretty b => Maybe CharacterSet -> Expr Src b -> Text
+formatExpr chosenCharacterSet expr =
       Pretty.renderStrict
     . Dhall.Pretty.layout
     $ Dhall.Pretty.prettyCharacterSet charSet expr
+  where
+    charSet = fromMaybe (Dhall.Pretty.detectCharacterSet expr) chosenCharacterSet
 
 -- | Pretty-print the given Dhall expression, prepending the given a "header"
 --   (usually consisting of comments and whitespace).
-formatExprWithHeader :: Pretty.Pretty b => CharacterSet -> Expr Src b -> Header -> Text
-formatExprWithHeader charSet expr (Header header) = Pretty.renderStrict
+formatExprWithHeader :: Pretty.Pretty b => Maybe CharacterSet -> Expr Src b -> Header -> Text
+formatExprWithHeader chosenCharacterSet expr (Header header) = Pretty.renderStrict
   (Dhall.Pretty.layout doc)
   where
+    charSet = fromMaybe (Dhall.Pretty.detectCharacterSet expr) chosenCharacterSet
+
     doc =
       Pretty.pretty header
         <> Dhall.Pretty.prettyCharacterSet charSet expr
         <> "\n"
-
diff --git a/src/Dhall/LSP/Backend/Parsing.hs b/src/Dhall/LSP/Backend/Parsing.hs
--- a/src/Dhall/LSP/Backend/Parsing.hs
+++ b/src/Dhall/LSP/Backend/Parsing.hs
@@ -12,6 +12,7 @@
 where
 
 import Control.Applicative     (optional, (<|>))
+import Data.Functor            (void)
 import Data.Text               (Text)
 import Dhall.Core
     ( Binding (..)
@@ -112,7 +113,7 @@
   Megaparsec.parseMaybe (unParser parseLetIdentifier) text
   where parseLetIdentifier = do
           setSourcePos left
-          _lambda
+          _ <- _lambda
           whitespace
           _openParens
           whitespace
@@ -128,7 +129,7 @@
   Megaparsec.parseMaybe (unParser parseLetIdentifier) text
   where parseLetIdentifier = do
           setSourcePos left
-          _forall
+          _ <- _forall
           whitespace
           _openParens
           whitespace
@@ -191,7 +192,7 @@
     Just s -> s
   where
     -- marks the beginning of the next binder
-    boundary = _let <|> _forall <|> _lambda
+    boundary = _let <|> void _forall <|> void _lambda
 
     -- A binder that is out of scope at the end of the input. Discarded in the
     -- resulting 'binder expression'.
@@ -218,7 +219,7 @@
         <|> closedLet
 
     closedLambda = do
-      _lambda
+      _ <- _lambda
       whitespace
       _openParens
       whitespace
@@ -230,13 +231,13 @@
       whitespace
       _closeParens
       whitespace
-      _arrow
+      _ <- _arrow
       whitespace
       _ <- expr
       return ()
 
     closedPi = do
-      _forall
+      _ <- _forall
       whitespace
       _openParens
       whitespace
@@ -248,7 +249,7 @@
       whitespace
       _closeParens
       whitespace
-      _arrow
+      _ <- _arrow
       whitespace
       _ <- expr
       return ()
@@ -284,7 +285,7 @@
       return (Let (Binding Nothing name Nothing mType Nothing value) inner)
 
     forallBinder = do
-      _forall
+      cs <- _forall
       whitespace
       _openParens
       whitespace
@@ -293,14 +294,15 @@
       _colon
       nonemptyWhitespace
       -- if the bound type does not parse, skip and replace with 'hole'
-      typ <- try (do e <- expr; whitespace; _closeParens; whitespace; _arrow; return e)
-          <|> (do skipManyTill anySingle _arrow; return holeExpr)
+      (cs', typ) <-
+          try (do e <- expr; whitespace; _closeParens; whitespace; cs' <- _arrow; return (cs', e))
+          <|> (do cs' <- skipManyTill anySingle _arrow; return (cs', holeExpr))
       whitespace
       inner <- parseBinderExpr
-      return (Pi name typ inner)
+      return (Pi (Just (cs <> cs')) name typ inner)
 
     lambdaBinder = do
-      _lambda
+      cs <- _lambda
       whitespace
       _openParens
       whitespace
@@ -309,8 +311,9 @@
       _colon
       nonemptyWhitespace
       -- if the bound type does not parse, skip and replace with 'hole'
-      typ <- try (do e <- expr; whitespace; _closeParens; whitespace; _arrow; return e)
-          <|> (do skipManyTill anySingle _arrow; return holeExpr)
+      (cs', typ) <-
+          try (do e <- expr; whitespace; _closeParens; whitespace; cs' <- _arrow; return (cs', e))
+          <|> (do cs' <- skipManyTill anySingle _arrow; return (cs', holeExpr))
       whitespace
       inner <- parseBinderExpr
-      return (Lam (makeFunctionBinding name typ) inner)
+      return (Lam (Just (cs <> cs')) (makeFunctionBinding name typ) inner)
diff --git a/src/Dhall/LSP/Backend/Typing.hs b/src/Dhall/LSP/Backend/Typing.hs
--- a/src/Dhall/LSP/Backend/Typing.hs
+++ b/src/Dhall/LSP/Backend/Typing.hs
@@ -50,13 +50,13 @@
   return (Just $ getLetIdentifier src, typ)
 
 -- "..." in a lambda expression
-typeAt' pos _ctx (Note src (Lam FunctionBinding { functionBindingAnnotation = _A} _))
+typeAt' pos _ctx (Note src (Lam _ FunctionBinding { functionBindingAnnotation = _A} _))
   | Just src' <- getLamIdentifier src
   , pos `inside` src' =
   return (Just src', _A)
 
 -- "..." in a forall expression
-typeAt' pos _ctx (Note src (Pi _ _A _)) | Just src' <- getForallIdentifier src
+typeAt' pos _ctx (Note src (Pi _ _ _A _)) | Just src' <- getForallIdentifier src
                                         , pos `inside` src' =
   return (Just src', _A)
 
@@ -65,13 +65,13 @@
   let a' = shift 1 (V x 0) (normalize a)
   typeAt' pos ctx (shift (-1) (V x 0) (subst (V x 0) a' e))
 
-typeAt' pos ctx (Lam FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A} b@(Note src _))
+typeAt' pos ctx (Lam _ FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A} b@(Note src _))
   | pos `inside` src = do
       let _A' = Dhall.Core.normalize _A
           ctx' = fmap (shift 1 (V x 0)) (insert x _A' ctx)
       typeAt' pos ctx' b
 
-typeAt' pos ctx (Pi x _A  _B@(Note src _)) | pos `inside` src = do
+typeAt' pos ctx (Pi _ x _A  _B@(Note src _)) | pos `inside` src = do
   let _A' = Dhall.Core.normalize _A
       ctx' = fmap (shift 1 (V x 0)) (insert x _A' ctx)
   typeAt' pos ctx' _B
@@ -139,12 +139,12 @@
   let a' = shift 1 (V x 0) (normalize a)
   annotateLet' pos ctx (shift (-1) (V x 0) (subst (V x 0) a' e))
 
-annotateLet' pos ctx (Lam FunctionBinding{ functionBindingVariable = x, functionBindingAnnotation = _A } b@(Note src _)) | pos `inside` src = do
+annotateLet' pos ctx (Lam _ FunctionBinding{ functionBindingVariable = x, functionBindingAnnotation = _A } b@(Note src _)) | pos `inside` src = do
   let _A' = Dhall.Core.normalize _A
       ctx' = fmap (shift 1 (V x 0)) (insert x _A' ctx)
   annotateLet' pos ctx' b
 
-annotateLet' pos ctx (Pi x _A _B@(Note src _)) | pos `inside` src = do
+annotateLet' pos ctx (Pi _ x _A _B@(Note src _)) | pos `inside` src = do
   let _A' = Dhall.Core.normalize _A
       ctx' = fmap (shift 1 (V x 0)) (insert x _A' ctx)
   annotateLet' pos ctx' _B
diff --git a/src/Dhall/LSP/Handlers.hs b/src/Dhall/LSP/Handlers.hs
--- a/src/Dhall/LSP/Handlers.hs
+++ b/src/Dhall/LSP/Handlers.hs
@@ -14,7 +14,6 @@
     )
 import Dhall.Import (localToPath)
 import Dhall.Parser (Src (..))
-import Dhall.Pretty (CharacterSet (..))
 
 import Dhall.LSP.Backend.Completion
     ( Completion (..)
@@ -337,10 +336,8 @@
     _ -> throwE (Warning, "Failed to format dhall code; parse error.")
 
   ServerConfig {..} <- getServerConfig
-  let charSet | asciiOnly = ASCII
-              | otherwise = Unicode
 
-  let formatted = formatExprWithHeader charSet expr header
+  let formatted = formatExprWithHeader chosenCharacterSet expr header
       numLines = Text.length txt
       range = J.Range (J.Position 0 0) (J.Position numLines 0)
       edits = J.List [J.TextEdit range formatted]
@@ -379,10 +376,8 @@
     _ -> throwE (Warning, "Failed to lint dhall code; parse error.")
 
   ServerConfig {..} <- getServerConfig
-  let charSet | asciiOnly = ASCII
-              | otherwise = Unicode
 
-  let linted = formatExprWithHeader charSet (lint expr) header
+  let linted = formatExprWithHeader chosenCharacterSet (lint expr) header
       numLines = Text.length txt
       range = J.Range (J.Position 0 0) (J.Position numLines 0)
       edit = J.WorkspaceEdit
@@ -406,8 +401,6 @@
     Right e -> return e
 
   ServerConfig {..} <- getServerConfig
-  let charSet | asciiOnly = ASCII
-              | otherwise = Unicode
 
   (Src (SourcePos _ x1 y1) (SourcePos _ x2 y2) _, annotExpr)
     <- case annotateLet (line, col) welltyped of
@@ -416,7 +409,7 @@
 
   let range = J.Range (J.Position (unPos x1 - 1) (unPos y1 - 1))
                       (J.Position (unPos x2 - 1) (unPos y2 - 1))
-      txt = formatExpr charSet annotExpr
+      txt = formatExpr chosenCharacterSet annotExpr
       edit = J.WorkspaceEdit
         (Just (HashMap.singleton uri (J.List [J.TextEdit range txt]))) Nothing
 
diff --git a/src/Dhall/LSP/State.hs b/src/Dhall/LSP/State.hs
--- a/src/Dhall/LSP/State.hs
+++ b/src/Dhall/LSP/State.hs
@@ -13,11 +13,12 @@
     , (.:)
     , (.:?)
     )
-import Data.Default                     (Default (def))
+import Data.Default                     (Default(def))
 import Data.Dynamic                     (Dynamic)
 import Data.Map.Strict                  (Map, empty)
 import Data.Text                        (Text)
 import Dhall.LSP.Backend.Dhall          (Cache, DhallError, emptyCache)
+import Dhall.Pretty                     (CharacterSet)
 import Lens.Family                      (LensLike')
 
 import qualified Language.Haskell.LSP.Core     as LSP
@@ -40,13 +41,11 @@
               -- ^ Log message, not displayed by default.
 
 data ServerConfig = ServerConfig
-  { asciiOnly :: Bool
-  -- ^ Use ASCII symbols rather than fancy unicode when formatting and linting
-  -- code.
+  { chosenCharacterSet :: Maybe CharacterSet
   } deriving Show
 
 instance Default ServerConfig where
-  def = ServerConfig { asciiOnly = False }
+  def = ServerConfig { chosenCharacterSet = Nothing }
 
 -- We need to derive the FromJSON instance manually in order to provide defaults
 -- for absent fields.
@@ -54,7 +53,7 @@
   parseJSON = withObject "settings" $ \v -> do
     s <- v .: "vscode-dhall-lsp-server"
     flip (withObject "vscode-dhall-lsp-server") s $ \o -> ServerConfig
-      <$> o .:? "asciiOnly" .!= asciiOnly def
+      <$> o .:? "character-set" .!= Nothing
 
 data ServerState = ServerState
   { _importCache :: Cache  -- ^ The dhall import cache
