# \[ANN\] PreferenceTools.jl - interactive preference setting

**URL:** <https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076>\
**Category:** Package Announcements\
**Created:** [March 14, 2023, 6:28pm UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076 "2023-03-14T18:28:52Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [March 14, 2023, 6:28pm UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076/1 "2023-03-14T18:28:52Z")

</div>

# PreferenceTools.jl

> **[GitHub - cjdoris/PreferenceTools.jl: Julia preferences for humans](https://github.com/cjdoris/PreferenceTools.jl)**
>
> Julia preferences for humans

I made a little package to make it easier to set and get preferences (in the sense of [Preferences.jl](https://github.com/JuliaPackaging/Preferences.jl)) interactively. It hooks into the Pkg REPL so you can do this:

```julia-auto
pkg> preference add Plots default_backend=unicodeplots

pkg> preference add Cthulhu enable_highlighter=true type_annotations=true

pkg> preference add SnoopPrecompile skip_precompile+=DataFrames

pkg> preference status
Cthulhu
  enable_highlighter: true
  type_annotations: true
Plots
  default_backend: "unicodeplots"
SnoopPrecompile
  skip_precompile: ["DataFrames"]

```

Why use this?

- It provides a single consistent interface for modifying preferences. Many packages have functions to set their preferences, but with varying interfaces and levels of functionality. Package authors could instead instruct their users to set preferences with this package.
- The commands (`add`, `remove`, `status`) are consistent with the rest of the Pkg REPL so easy to remember.
- It allows you to set preferences before first loading the package - which may be important to avoid downloading a large unwanted default binary, or to avoid unnecessary precompilation. You can only do this with Preferences.jl if you know the UUID of the package.
- You can conveniently set global preferences with the `-g` flag, and export them with the `-x` flag.
- Fewer keystrokes - installed packages and existing preference names can be tab-completed.
- List-valued preferences can be modified with `+=` and `-=`, which is particularly useful for `SnoopPrecompile.skip_precompile`.

Why not use it?

- Preferences are not validated at all - this does not check that the package name exists, or that a given preference name or value is valid for the package.
- Packages which consume preferences should still use Preferences.jl directly. This package is for interactive use.

Personally, I’m going to migrate some of my own packages (PythonCall, CondaPkg, Bokeh) to use preferences, instructing users to set preferences with this package.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 14, 2023, 6:33pm UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076/2 "2023-03-14T18:33:21Z")

</div>

Have you considered a PR to Preferences.jl instead of having a separate package? This seems like the sort of thing that we want standardized in the long run (at least for simple set/get operations).

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [March 14, 2023, 7:16pm UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076/3 "2023-03-14T19:16:31Z")

</div>

Sure, there are certainly some things that could be immediately “upstreamed” to Preferences.jl, like the ability to specify the package by name.

The REPL mode is sufficiently new and different though (and relies on undocumented internals) that I was expecting some push-back on that. Having a separate package makes it easier to iterate and get to an acceptable implementation. It’s also possible the REPL mode might make the package load time a lot worse for people not using that functionality - though I imagine it can be avoided by only enabling it in interactive sessions.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [March 16, 2023, 8:59am UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076/4 "2023-03-16T08:59:55Z")

</div>

PreferencesTools.jl has extra dependencies besides Preferences.jl itself, which I don’t think would be accepted in Preferences.jl.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [March 16, 2023, 9:12am UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076/5 "2023-03-16T09:12:14Z")

</div>

Does it? Only for testing, no? (`Markdown` and `Pkg` are stdlibs.)

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [March 16, 2023, 9:21am UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076/6 "2023-03-16T09:21:41Z")

</div>

> [@carstenbauer](#):
>
> (`Markdown` and `Pkg` are stdlibs.)

I was referring to them. I don’t think anyone will be happy about loading `Pkg` in all jlls 🙂 With [[AutoBuild] Do not add `Pkg` as dependency if we require Julia v1.6 by giordano · Pull Request #1261 · JuliaPackaging/BinaryBuilder.jl · GitHub](https://github.com/JuliaPackaging/BinaryBuilder.jl/pull/1261) I removed it completely from the environment, even if it wasn’t actually loaded most of the time. Pkg is large.

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [March 16, 2023, 9:48am UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076/7 "2023-03-16T09:48:44Z")

</div>

Why does Preferences.jl have a comparatively long load time, actually? It indirectly affects the load time of SnoopPrecompile, which I imagine will be used by a lot of packages in the future. Preferences.jl should have a lot of invalidations, etc., right?

```julia
julia> @time_imports import Pkg, SnoopPrecompile
     42.5 ms Preferences
      0.6 ms SnoopPrecompile

```

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [September 2, 2023, 5:53pm UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076/8 "2023-09-02T17:53:28Z")

</div>

If the problem is adding `Pkg` as a dependency for BinaryBuilder.jl, maybe we can upstream all of this to Preferences.jl, then spin off a PreferencesLite.jl for BinaryBuilder?

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [September 2, 2023, 6:02pm UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076/9 "2023-09-02T18:02:04Z")

</div>

> [@ParadaCarleton](#):
>
> If the problem is adding `Pkg` as a dependency for BinaryBuilder.jl

No, it’s not. The problem is that people don’t want Pkg as a dependency needlessly.

> [@ParadaCarleton](#):
>
> maybe we can upstream all of this to Preferences.jl, then spin off a PreferencesLite.jl for BinaryBuilder?

I don’t think this helps with the problem stated above, it just aggravates it.

---

<div class="post-metadata">

**Author:** ![ParadaCarleton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paradacarleton/32/20005_2.png) [@ParadaCarleton](https://discourse.julialang.org/u/ParadaCarleton)\
**Post date:** [September 8, 2023, 12:14am UTC](https://discourse.julialang.org/t/ann-preferencetools-jl-interactive-preference-setting/96076/10 "2023-09-08T00:14:14Z")

</div>

> [@giordano](#):
>
> No, it’s not. The problem is that people don’t want Pkg as a dependency needlessly.

Right, so what I’m saying is you can carve out the parts of Preferences.jl and PreferenceTools.jl that don’t require Pkg.jl and put them in a PreferencesCore.jl, which people who don’t want to use Pkg can use instead.

Mostly I’m trying to make this easy on the user end, by having one package for normal users with a simple name (Preferences.jl).

Separately, for the kinds of people who care a lot about minimizing dependencies, we can have a package that includes any preference-related features that don’t require Pkg.
