Skip to content

OCaml Onboarding #1737

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
67e0195
images and gifs for onboarding
PizieDust Feb 28, 2025
402d8a3
new onboarding commands
PizieDust Feb 28, 2025
748c8fb
ocaml onboarding sequence of steps
PizieDust Feb 28, 2025
46744e6
add instructions and new images
PizieDust Mar 11, 2025
1df7df9
add link for ocaml survey
PizieDust Mar 11, 2025
d91911e
better utop screenshot
PizieDust Mar 11, 2025
e9a1808
add changelog
PizieDust Mar 11, 2025
5f65f54
Update src/extension_commands.ml
PizieDust Mar 14, 2025
e9b1d07
Update src/extension_commands.ml
PizieDust Mar 14, 2025
e69a596
Update src/extension_commands.ml
PizieDust Mar 14, 2025
2927841
Update package.json
PizieDust Mar 14, 2025
2fb7c0f
Update package.json
PizieDust Mar 14, 2025
4ab0a57
Update package.json
PizieDust Mar 14, 2025
fca0ce6
Update package.json
PizieDust Mar 14, 2025
7417e4b
Update package.json
PizieDust Mar 14, 2025
81640ff
Update package.json
PizieDust Mar 14, 2025
46959e2
Update package.json
PizieDust Mar 14, 2025
735f71e
Update CHANGELOG.md
PizieDust Mar 14, 2025
faa9682
Update package.json
PizieDust Mar 14, 2025
c7134a9
Update package.json
PizieDust Mar 14, 2025
e1da771
Update package.json
PizieDust Mar 14, 2025
f30dae6
Update package.json
PizieDust Mar 14, 2025
1ee09b4
Update package.json
PizieDust Mar 14, 2025
b8abbfc
better alt descriptions
PizieDust Mar 14, 2025
93d6358
fix lint
PizieDust Mar 27, 2025
872cedf
check each step upon completion of the event
PizieDust Mar 27, 2025
ec380da
check that opam is installed before proceeding
PizieDust Mar 28, 2025
6ef929c
remove unusued value
PizieDust Mar 28, 2025
a56a204
changes based on reviews
PizieDust Apr 2, 2025
56a6418
explain the different choices in opam init
PizieDust Apr 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

# Unreleased

- Add OCaml onboarding welcome screen. (#1737)

## 1.28.0

- Add `.re` file extension support. (#1685)
Expand Down
Binary file added assets/ocaml_survey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/opam_init.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/opam_install.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/opam_switch.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/utop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/vscode-ocaml-commands.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
110 changes: 109 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,114 @@
"test": "vscode-test"
},
"contributes": {
"walkthroughs": [
{
"id": "ocaml-onboarding",
"title": "OCaml: Setup opam dev environment (manual)",
"description": "A guided, terminal based, installation of OCaml and essential tools with the opam package manager.",
"steps": [
{
"id": "install-opam-windows",
"when": "isWindows",
"title": "Install opam",
"description": "opam is the package manager for OCaml. Installing opam also installs the OCaml compiler. On Windows 10 or 11, install it using Winget:\n\nRun `winget install Git.Git OCaml.opam` in PowerShell.\n\n[Open a terminal and run winget](command:ocaml.install-opam)",
"media": {
"image": "assets/opam_install.jpg",
"altText": "While installing opam, you'll be asked a series of questions: (1) Where should opam be installed? You can press enter and use the default location, unless you wish to install it somehwere else. (2) Sometimes it may request administrator write access, you should enter your password to authorize the installer."
},
"completionEvents": [
"onCommand:ocaml.install-opam"
]
},
{
"id": "install-opam-mac",
"when": "isMac",
"title": "Install opam",
"description": "opam is the package manager for OCaml. Installing opam also installs the OCaml compiler. Install it opam's official script installer.\n\n[Open a terminal and run the opam install script](command:ocaml.install-opam)",
"media": {
"image": "assets/opam_install.jpg",
"altText": "While installing opam, you'll be asked a series of questions: (1) Where should opam be installed? You can press enter and use the default location, unless you wish to install it somehwere else. (2) Sometimes it may request administrator write access, you should enter your password to authorize the installer."
},
"completionEvents": [
"onCommand:ocaml.install-opam"
]
},
{
"id": "install-opam-linux",
"when": "isLinux",
"title": "Install opam",
"description": "opam is the package manager for OCaml. Installing opam also installs the OCaml compiler. Install it opam's official script installer.\n\n[Open a terminal and run the opam install script](command:ocaml.install-opam)",
"media": {
"image": "assets/opam_install.jpg",
"altText": "While installing opam, you'll be asked a series of questions: (1) Where should opam be installed? You can press enter and use the default location, unless you wish to install it somehwere else. (2) Sometimes it may request administrator write access, you should enter your password to authorize the installer."
},
"completionEvents": [
"onCommand:ocaml.install-opam"
]
},
{
"id": "init-opam",
"title": "Initialize opam",
"description": "After installing opam, we initialise it so as to prepare your system to use it for managing OCaml packages and compilers.\n\n[Open a terminal and run opam init](command:ocaml.init-opam)",
"media": {
"image": "assets/opam_init.jpg",
"altText": "For the different options: (1) → Updates ~/.profile to automatically configure opam for future shell sessions. (2) → Does not update shell configs; requires manual eval $(opam env) after switching. (3) → Allows selecting a different shell (e.g., zsh, fish) for configuration. (4) → Lets you specify a custom config file instead of ~/.profile.5 → No automatic setup; you must manually run eval $(opam env) when needed."
},
"completionEvents": [
"onCommand:ocaml.init-opam"
]
},
{
"id": "activate-opam-switch",
"title": "Activate the opam switch",
"description": "An opam switch is an isolated OCaml environment (like a Python virtual environment) where you can install different OCaml versions and packages. \n\n[Select a switch and activate it](command:ocaml.select-sandbox)",
"media": {
"image": "assets/opam_switch.jpg",
"altText": "An image of tiny ocaml logos arranged in the shape of a camel"
},
"completionEvents": [
"onCommand:ocaml.select-sandbox"
]
},
{
"id": "install-platform-tools",
"title": "Install OCaml Platform Tools",
"description": "Now install essential development tools:\n\n- OCaml LSP server enables editor support for OCaml, odoc generates documentation, camlformat automatically formats OCaml code, utop is an interactive REPL for OCaml and dune is the official OCaml build system.\n\n[Install Platform Tools](command:ocaml.install-ocaml-dev)",
"media": {
"image": "assets/vscode-ocaml-commands.gif",
"altText": "A gif of how to access all commands provide by the ocaml vscode plugin which can be accessed by pressing Ctrl+Alt+P and typing ocaml"
},
"completionEvents": [
"onCommand:ocaml.install-ocaml-dev"
]
},
{
"id": "check-installation",
"title": "Check Installation",
"description": "Verify your OCaml installation by running utop. If everything is set up correctly, you should see a prompt like the image on the right. \n\n[Check Installation](command:ocaml.open-utop)",
"media": {
"image": "assets/utop.png",
"altText": "A screenshot showing the output of running utop in a command line"
},
"completionEvents": [
"onCommand:ocaml.open-utop"
]
},
{
"id": "finish-onboarding",
"title": "Congratulations",
"description": "You now have OCaml installed and setup on your computer. Please take a few minutes to answer this short survey.\n\n[OCaml Survey](https://docs.google.com/forms/d/e/1FAIpQLSfGGFZBiw4PF7L0yt2DBX8443G5_7aFL5v6wvo6p5MwL-DW8Q/viewform?usp=pp_url&entry.454013858=Link+in+the+VSCode+plugin)",
"media": {
"image": "assets/ocaml_survey.png",
"altText": "A screenshot of some of the various companies that use OCaml including JaneStreet, Bloomberg, ahrefs, Tezos, Facebook, Microsoft, Docker"
},
"completionEvents": [
"onLink:https://docs.google.com/forms/d/e/1FAIpQLSfGGFZBiw4PF7L0yt2DBX8443G5_7aFL5v6wvo6p5MwL-DW8Q/viewform?usp=pp_url&entry.454013858=Link+in+the+VSCode+plugin"
]
}
]
}
],
"breakpoints": [
{
"language": "ocaml"
Expand Down Expand Up @@ -1334,4 +1442,4 @@
"color": "#f29100",
"theme": "light"
}
}
}
Comment on lines -1337 to +1445
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff should not exist.

171 changes: 171 additions & 0 deletions src/extension_commands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,177 @@ let _switch_impl_intf =
command Extension_consts.Commands.switch_impl_intf handler
;;

let _install_opam =
let handler (instance : Extension_instance.t) ~args:_ =
let process_installation () =
let open Promise.Syntax in
let* opam = Opam.make () in
match opam with
| None ->
let options =
ProgressOptions.create
~location:(`ProgressLocation Notification)
~title:"Installing opam package manager"
~cancellable:false
()
in
let task ~progress:_ ~token:_ =
let+ result =
match Platform.t with
| Win32 ->
let _ =
let terminal =
Extension_instance.sandbox instance |> Terminal_sandbox.create
in
let _ = Terminal_sandbox.show ~preserveFocus:true terminal in
Terminal_sandbox.send terminal "winget install Git.Git OCaml.opam"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know if this works?

in
Ok () |> Promise.return
| Darwin | Linux | Other ->
let open Promise.Result.Syntax in
let+ _ =
let _ =
let terminal =
Extension_instance.sandbox instance |> Terminal_sandbox.create
in
let _ = Terminal_sandbox.show ~preserveFocus:true terminal in
Terminal_sandbox.send
terminal
"bash -c \"sh <(curl -fsSL https://opam.ocaml.org/install.sh)\""
in
Ok () |> Promise.return
in
()
in
match result with
| Ok () -> Ojs.null
| Error err ->
show_message `Error "An error occured while installing opam %s" err;
Ojs.null
in
let+ _ = Vscode.Window.withProgress (module Ojs) ~options ~task in
()
| Some _ -> show_message `Info "Opam is already installed!" |> Promise.return
in
let (_ : unit Promise.t) = process_installation () in
()
in
command Extension_consts.Commands.install_opam handler
;;

let _init_opam =
let handler (instance : Extension_instance.t) ~args:_ =
let options =
ProgressOptions.create
~location:(`ProgressLocation Notification)
~title:"Initialising opam"
~cancellable:false
()
in
let task ~progress:_ ~token:_ =
let open Promise.Syntax in
let+ result =
let open Promise.Result.Syntax in
let+ _ =
let _ =
let terminal =
Extension_instance.sandbox instance |> Terminal_sandbox.create
in
let _ = Terminal_sandbox.show ~preserveFocus:true terminal in
Terminal_sandbox.send terminal "opam init"
in
Ok () |> Promise.return
in
()
in
match result with
| Ok () -> Ojs.null
| Error err ->
show_message `Error "An error occured while initializing opam %s" err;
Ojs.null
in
let _ = Vscode.Window.withProgress (module Ojs) ~options ~task in
()
in
command Extension_consts.Commands.init_opam handler
;;

let _install_ocaml_dev =
let handler (instance : Extension_instance.t) ~args:_ =
let options =
ProgressOptions.create
~location:(`ProgressLocation Notification)
~title:"Installing development packages"
~cancellable:false
()
in
let task ~progress:_ ~token:_ =
let open Promise.Syntax in
let+ result =
let open Promise.Result.Syntax in
let+ _ =
let _ =
let terminal =
Extension_instance.sandbox instance |> Terminal_sandbox.create
in
let _ = Terminal_sandbox.show ~preserveFocus:true terminal in
Terminal_sandbox.send
terminal
"opam install ocaml-lsp-server odoc ocamlformat utop"
in
Ok () |> Promise.return
in
()
in
match result with
| Ok () -> Ojs.null
| Error err ->
show_message `Error "An error occured while installing packages %s" err;
Ojs.null
in
let _ = Vscode.Window.withProgress (module Ojs) ~options ~task in
()
in
command Extension_consts.Commands.install_ocaml_dev handler
;;

let _open_utop =
let handler (instance : Extension_instance.t) ~args:_ =
let options =
ProgressOptions.create
~location:(`ProgressLocation Notification)
~title:"Launching utop"
~cancellable:false
()
in
let task ~progress:_ ~token:_ =
let open Promise.Syntax in
let+ result =
let open Promise.Result.Syntax in
let+ _ =
let _ =
let terminal =
Extension_instance.sandbox instance |> Terminal_sandbox.create
in
let _ = Terminal_sandbox.show ~preserveFocus:true terminal in
Terminal_sandbox.send terminal "utop"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Terminal_sandbox.send terminal "utop"
Terminal_sandbox.send terminal "opam exec -- utop"

in
Ok () |> Promise.return
in
()
in
match result with
| Ok () -> Ojs.null
| Error err ->
show_message `Error "An error occured while opening utop %s" err;
Ojs.null
in
let _ = Vscode.Window.withProgress (module Ojs) ~options ~task in
()
in
command Extension_consts.Commands.open_utop handler
;;

let _open_current_dune_file =
let handler (_instance : Extension_instance.t) ~args:_ =
match Vscode.Window.activeTextEditor () with
Expand Down
4 changes: 4 additions & 0 deletions src/extension_consts.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
let ocaml_prefixed key = "ocaml." ^ key

module Commands = struct
let install_opam = ocaml_prefixed "install-opam"
let init_opam = ocaml_prefixed "init-opam"
let install_ocaml_dev = ocaml_prefixed "install-ocaml-dev"
let open_utop = ocaml_prefixed "open-utop"
let select_sandbox = ocaml_prefixed "select-sandbox"
let restart_language_server = ocaml_prefixed "server.restart"
let select_sandbox_and_open_terminal = ocaml_prefixed "open-terminal-select"
Expand Down