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
impl Family
Sourcepub const QUVYTA: Family
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.
Sourcepub const fn new(id: &'static str, title: &'static str) -> Self
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.
Sourcepub fn id(&self) -> &'static str
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.
Sourcepub fn config_dir(&self) -> Option<PathBuf>
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>whenXDG_CONFIG_HOMEis 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.
The settings every application of the family shares: <config_dir>/<id>.conf, such as
quvyta.conf.
Sourcepub fn app_file(&self, app: &str) -> Option<PathBuf>
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.
Sourcepub fn app_dir(&self, app: &str) -> Option<PathBuf>
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.
Sourcepub fn state_dir(&self, app: &str) -> Option<PathBuf>
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>whenXDG_STATE_HOMEis 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.
Sourcepub fn cache_dir(&self, app: &str) -> Option<PathBuf>
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>whenXDG_CACHE_HOMEis 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.
Sourcepub fn workspace_dir(&self, app_title: &str) -> Option<PathBuf>
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.
Sourcepub fn adopt(&self, app: &str, legacy_dir: &Path) -> Migration
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.
Sourcepub fn adopt_in(
&self,
config_dir: &Path,
app: &str,
legacy_dir: &Path,
) -> Migration
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
impl Family
Sourcepub fn preferences(&self, app: &str, i18n: &I18n) -> Preferences
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.
Sourcepub fn preferences_in(
&self,
config_dir: &Path,
app: &str,
i18n: &I18n,
) -> Preferences
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.
Sourcepub fn preferences_without_saving(&self, app: &str, i18n: &I18n) -> Preferences
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.
Sourcepub fn preferences_without_saving_in(
&self,
config_dir: &Path,
app: &str,
i18n: &I18n,
) -> Preferences
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.
Sourcepub fn set(
&self,
app: &str,
key: Shared,
value: &str,
scope: Scope,
) -> Result<()>
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:
scope | shared file | application’s file |
|---|---|---|
Scope::Family | key = value | key = "<family id>" |
Scope::App | unchanged | key = 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.
Sourcepub fn set_in(
&self,
config_dir: &Path,
app: &str,
key: Shared,
value: &str,
scope: Scope,
) -> Result<()>
pub fn set_in( &self, config_dir: &Path, app: &str, key: Shared, value: &str, scope: Scope, ) -> Result<()>
Sourcepub fn follow(&self, app: &str, key: Shared) -> Result<()>
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.
Sourcepub fn follow_in(&self, config_dir: &Path, app: &str, key: Shared) -> Result<()>
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§
impl Copy for Family
impl Eq for Family
impl StructuralPartialEq for Family
Auto Trait Implementations§
impl Freeze for Family
impl RefUnwindSafe for Family
impl Send for Family
impl Sync for Family
impl Unpin for Family
impl UnsafeUnpin for Family
impl UnwindSafe for Family
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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