Skip to main content

Family

Struct Family 

Source
pub struct Family { /* private fields */ }
Expand description

A family of applications that share one settings folder.

The id names the folder and the shared file where names are lowercase by custom, on Linux and other Unix systems; the title names the folder where a user sees it written like a name, on macOS and Windows, and always in the Documents folder. File names are always the lowercase id: quvyta.conf, code.conf.

use qframe::storage::Family;

let family = Family::QUVYTA;
if let (Some(folder), Some(file)) = (family.config_dir(), family.app_file("code")) {
    assert_eq!(file, folder.join("code.conf"));
}

Implementations§

Source§

impl Family

Source

pub const QUVYTA: Family

The Quvyta family: ~/.config/quvyta on Linux and other Unix systems, ~/Library/Application Support/Quvyta on macOS, %APPDATA%\Quvyta on Windows.

Source

pub const fn new(id: &'static str, title: &'static str) -> Self

A family with a lowercase id for folder and file names, such as quvyta, and a title for the places a user reads it as a name, such as Quvyta.

Source

pub fn id(&self) -> &'static str

The lowercase name of the family’s folder on Linux and other Unix systems and of its shared file.

Source

pub fn title(&self) -> &'static str

The family’s name as a user reads it.

Source

pub fn config_dir(&self) -> Option<PathBuf>

The folder every settings file of the family lives in:

  • Linux and other Unix systems: $XDG_CONFIG_HOME/<id> when XDG_CONFIG_HOME is an absolute path, else $HOME/.config/<id>.
  • macOS: $HOME/Library/Application Support/<title>.
  • Windows: %APPDATA%\<title>, the roaming folder.

None when there is no home folder, as for config_dir. The folder is not created.

Source

pub fn shared_file(&self) -> Option<PathBuf>

The settings every application of the family shares: <config_dir>/<id>.conf, such as quvyta.conf.

Source

pub fn app_file(&self, app: &str) -> Option<PathBuf>

The settings file of application app: <config_dir>/<app>.conf, such as code.conf. app is the application’s lowercase id. An application whose id is the family’s own would get the shared file, so give it another id.

Source

pub fn app_dir(&self, app: &str) -> Option<PathBuf>

The folder for the other configuration files of application app, next to its settings file: <config_dir>/<app>. Not created.

Source

pub fn state_dir(&self, app: &str) -> Option<PathBuf>

Where application app of the family keeps its state, such as the result of its last background check: <state folder>/<family>/<app>.

  • Linux and other Unix systems: $XDG_STATE_HOME/<id>/<app> when XDG_STATE_HOME is an absolute path, else $HOME/.local/state/<id>/<app>.
  • macOS: $HOME/Library/Application Support/<title>/<app>.
  • Windows: %LOCALAPPDATA%\<title>\<app>.

None when there is no home folder, as for state_dir. Not created.

Source

pub fn cache_dir(&self, app: &str) -> Option<PathBuf>

Where application app of the family keeps files it can rebuild at any time: <cache folder>/<family>/<app>.

  • Linux and other Unix systems: $XDG_CACHE_HOME/<id>/<app> when XDG_CACHE_HOME is an absolute path, else $HOME/.cache/<id>/<app>.
  • macOS: $HOME/Library/Caches/<title>/<app>.
  • Windows: %LOCALAPPDATA%\<title>\<app>.

None when there is no home folder, as for cache_dir. Not created.

Source

pub fn workspace_dir(&self, app_title: &str) -> Option<PathBuf>

Where the work the user makes with an application is kept by default: <documents>/<family title>/<app_title>, such as ~/Documents/Quvyta/Code, in the Documents folder under the name the user’s desktop gave it. app_title is the application’s name as the user reads it. None when there is no home folder. Not created.

Source

pub fn adopt(&self, app: &str, legacy_dir: &Path) -> Migration

Moves the settings of application app from the folder it used before it joined the family into the family’s layout, once, without losing anything.

legacy_dir/settings.toml becomes app_file; every other file under legacy_dir, at any depth, goes to the same place under app_dir. When legacy_dir already is the application’s folder, only settings.toml moves and the other files stay where they are. Call it at start, before Settings::load_member.

Every file is copied first, with its permissions, then read back and compared, and only then removed from the old place. A file whose new place is already taken stays where it is, and so do symbolic links, which are never followed; nothing is overwritten or merged. Old folders left empty are removed, from the deepest up; a folder with anything left in it is kept. A missing legacy_dir is nothing to do, so calling it again after a finished move changes nothing. Whatever stayed behind is in the report, with the reason.

A crash in the middle of a move can leave the new file empty next to the old one; the old one is still whole, and the next call reports the pair instead of choosing between them.

Source

pub fn adopt_in( &self, config_dir: &Path, app: &str, legacy_dir: &Path, ) -> Migration

adopt into config_dir as the family’s folder instead of this platform’s, for a test or a demo that must leave the user’s own settings alone: the settings become <config_dir>/<app>.conf and the other files move under <config_dir>/<app>.

Source§

impl Family

Source

pub fn preferences(&self, app: &str, i18n: &I18n) -> Preferences

Resolves the shared preferences of application app: for each of language, theme and icons, the application’s own value when its file names one other than the family’s id, else the value in the shared file, else the value detected on this machine. A key missing from the application’s file follows the family, as the family’s id does, so a file written by hand before the family shared anything follows it too.

Detection reads the environment: the language as I18n::detect finds it among the languages i18n knows (English when it knows none of the system’s), the theme always monochrome, the icons as the strongest set the terminal and the installed fonts allow (detect_glyph_mode).

When the shared file does not exist it is created with the detected values, so the next application that starts finds them. A broken line never stops anything: that key falls back to the detected value and the reason, located at file, line and column, is in Preferences::diagnostics. Without a home folder nothing is read or written and every value is detected.

The rest of the application’s settings are read as before, with Settings::load_member; this only resolves the keys Shared names.

Source

pub fn preferences_in( &self, config_dir: &Path, app: &str, i18n: &I18n, ) -> Preferences

preferences with config_dir as the family’s folder instead of this platform’s, for a test or a demo that must leave the user’s own files alone.

Source

pub fn preferences_without_saving(&self, app: &str, i18n: &I18n) -> Preferences

preferences without writing anything: a missing shared file is left missing and its keys are detected instead.

For an application whose first start shows a setup wizard: a wizard closed half-way leaves the user’s settings folder as empty as it found it, and the wizard’s Finish writes both files. An application without a wizard uses preferences, so the first application to start leaves the shared file for the next one.

Source

pub fn preferences_without_saving_in( &self, config_dir: &Path, app: &str, i18n: &I18n, ) -> Preferences

preferences_without_saving with config_dir as the family’s folder instead of this platform’s, for a test or a demo.

Source

pub fn set( &self, app: &str, key: Shared, value: &str, scope: Scope, ) -> Result<()>

Changes shared preference key of application app to value, for the whole family or for the application alone:

scopeshared fileapplication’s file
Scope::Familykey = valuekey = "<family id>"
Scope::Appunchangedkey = value

Each file is read from disk right before it is written and only key changes in it, so two applications changing preferences at the same time both keep their change instead of one writing back what it read earlier. On Unix systems the family’s folder is held with an advisory lock from the reading to the writing, so even two changes in the same instant follow one another; elsewhere the window between them is a few microseconds. Files are written with atomic_write; the other keys stay as they were, though comments do not survive, as with Settings::save. The running application is not switched; use Preferences::apply or the matching Command for that.

§Errors

Returns an error of kind io::ErrorKind::InvalidInput when value is not a valid value of key (an unknown icon mode, the family’s own id, an empty text), of kind io::ErrorKind::NotFound when there is no home folder, and any error from writing.

Source

pub fn set_in( &self, config_dir: &Path, app: &str, key: Shared, value: &str, scope: Scope, ) -> Result<()>

set with config_dir as the family’s folder instead of this platform’s.

§Errors

As set, except that there is always a folder.

Source

pub fn follow(&self, app: &str, key: Shared) -> Result<()>

Puts application app back on the family’s value of key: its own file says the family’s id and the shared file is neither read nor written, so the next resolution answers the shared value with Source::Family and no other application changes. The one way back from a value of an application’s own, for the settings screen that lists every member of the family: “follow the shared setting” on one member’s cell must not change what the whole family draws with.

The file is read from disk right before it is written and only key changes in it, as set does, with the family’s folder held by an advisory lock on Unix. A missing file is created holding that one key. A key that already follows the family is left alone, file and all. Comments do not survive a change, as with Settings::save. The running application is not switched; use Preferences::apply for that.

§Errors

Returns an error of kind io::ErrorKind::NotFound when there is no home folder, of kind io::ErrorKind::InvalidData when the application’s file cannot be read as settings, and any error from writing. A file that could not be read is left exactly as it was.

Source

pub fn follow_in(&self, config_dir: &Path, app: &str, key: Shared) -> Result<()>

follow with config_dir as the family’s folder instead of this platform’s, for a test or a demo that must leave the user’s own files alone.

use qframe::storage::{Family, Shared};

std::fs::write(folder.join("code.conf"), "theme = \"amber\"\n").expect("the file");
Family::QUVYTA.follow_in(&folder, "code", Shared::Theme).expect("follow");
assert_eq!(std::fs::read_to_string(folder.join("code.conf")).expect("read"), "theme = \"quvyta\"\n");
assert!(!folder.join("quvyta.conf").exists(), "the shared file is left alone");
§Errors

As follow, except that there is always a folder.

Trait Implementations§

Source§

impl Clone for Family

Source§

fn clone(&self) -> Family

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Family

Source§

impl Debug for Family

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for Family

Source§

impl PartialEq for Family

Source§

fn eq(&self, other: &Family) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Family

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.