From 85d07c240348e3a2ff85cedfc7aaef8126222a69 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sun, 2 Jul 2023 15:24:02 -0500 Subject: Create roadmap for v1.0.0 --- docs/roadmap.org | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/roadmap.org (limited to 'docs/roadmap.org') diff --git a/docs/roadmap.org b/docs/roadmap.org new file mode 100644 index 0000000..2ff5ab5 --- /dev/null +++ b/docs/roadmap.org @@ -0,0 +1,27 @@ +* Version 1.0.0 Roadmap +Here is a list of the unfinished requirements for version 1.0.0. When everything here is met, I intend to release version 1.0.0 and consider 7Units complete (for the most part). + +These requirements are subject to change. I intend to finish version 1.0.0 by [2025-04-27 Sun]. + +Feature Requirements: +- 7Units should be able to parse unit files from [[https://www.gnu.org/software/units/][GNU Units]], the program that inspired it. + (It should not be required to handle features that aren't in 7Units; those definitions should be ignored with a warning) +- 7Units's expression converter should support most or all of the conversion features supported by GNU Units: + - Converting to sums of units (it should also be possible to do this in the unit converter with preset combinations) + - Non-integer exponents + - Fractions in unit expressions (like ~1|6~) + - (/Optional/) Inverse nonlinear conversion with the tilde prefix + - (/Optional/) Nonlinear units should be specifiable in unit files. + - /Any other feature not listed should be considered optional./ +- (/Optional/) It should be possible to add, edit and remove units and prefixes from the GUI unit and prefix viewers. + +Data/Configuration Requirements: +- All of the data formats (e.g. unit files) should be standardized. +- 7Units should put its configuration files in a standard place for the operating system ([[https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html][XDG Base Directory Specification]] compliant on Unix). The settings file should be able to specify the location of the data files. + +Documentation/Testing Requirements: +- 7Units should be fully documented. +- 7Units should have automated testing with a code coverage of at least 2/3 (ideally at least 5/6). + +Other Requirements +- The public API of 7Units should be finalized and well-designed. -- cgit v1.2.3 From c8ac31e271afe78f6127de737c616c6f6fab05cf Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 16 Sep 2023 12:58:48 -0500 Subject: Move config file to standard location The user's config directory is taken as ~\AppData\Local\ on Windows and is XDG-compliant elsewhere. The config file's location is /SevenUnits/config.txt. The SevenUnits directory is created if nonexistent. The previous location inside the git directory would not work for someone actually installing and using 7Units, so this change was made. --- .gitignore | 1 - .settings/org.eclipse.core.resources.prefs | 2 -- docs/roadmap.org | 2 +- src/main/java/sevenUnitsGUI/Presenter.java | 48 ++++++++++++++++++++++++++---- 4 files changed, 43 insertions(+), 10 deletions(-) delete mode 100644 .settings/org.eclipse.core.resources.prefs (limited to 'docs/roadmap.org') diff --git a/.gitignore b/.gitignore index bbda9ac..45bd4fb 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,5 @@ build # 7Units gitignore files *.class *~ -settings.txt /src/test/resources/test-settings.txt /bin/ diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 9bca13f..0000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/settings.txt=UTF-8 diff --git a/docs/roadmap.org b/docs/roadmap.org index 2ff5ab5..a68dae5 100644 --- a/docs/roadmap.org +++ b/docs/roadmap.org @@ -17,7 +17,7 @@ Feature Requirements: Data/Configuration Requirements: - All of the data formats (e.g. unit files) should be standardized. -- 7Units should put its configuration files in a standard place for the operating system ([[https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html][XDG Base Directory Specification]] compliant on Unix). The settings file should be able to specify the location of the data files. +- The config file should be able to specify the location of the data files. Documentation/Testing Requirements: - 7Units should be fully documented. diff --git a/src/main/java/sevenUnitsGUI/Presenter.java b/src/main/java/sevenUnitsGUI/Presenter.java index abdd1f6..3ecfba6 100644 --- a/src/main/java/sevenUnitsGUI/Presenter.java +++ b/src/main/java/sevenUnitsGUI/Presenter.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -57,9 +58,8 @@ import sevenUnits.utils.UncertainDouble; * @since 2021-12-15 */ public final class Presenter { - /** The default place where settings are stored. */ - private static final Path DEFAULT_SETTINGS_FILEPATH = Path - .of("settings.txt"); + /** The place where settings are stored. */ + private static final Optional CONFIG_FILE = getConfigPath(); /** The default place where units are stored. */ private static final String DEFAULT_UNITS_FILEPATH = "/unitsfile.txt"; /** The default place where dimensions are stored. */ @@ -67,6 +67,38 @@ public final class Presenter { /** The default place where exceptions are stored. */ private static final String DEFAULT_EXCEPTIONS_FILEPATH = "/metric_exceptions.txt"; + /** Gets the configuration file, creating the directory if needed. */ + private static final Optional getConfigPath() { + final Path configDir; + if (System.getProperty("os.name").startsWith("Windows")) { + final String envFolder = System.getenv("LOCALAPPDATA"); + if (envFolder == null || "".equals(envFolder)) { + configDir = Paths.get(System.getenv("USERPROFILE"), "AppData", "Local", "SevenUnits"); + } else { + configDir = Paths.get(envFolder, "SevenUnits"); + } + } else { + final String envFolder = System.getenv("XDG_CONFIG_HOME"); + if (envFolder == null || "".equals(envFolder)) { + configDir = Paths.get(System.getenv("HOME"), ".config", "SevenUnits"); + } else { + configDir = Paths.get(envFolder, "SevenUnits"); + } + } + + // try to create config directory + if (!Files.exists(configDir)) { + try { + Files.createDirectory(configDir); + } catch (IOException e) { + e.printStackTrace(); + return Optional.empty(); + } + } + + return Optional.of(configDir.resolve("config.txt")); + } + /** * Adds default units and dimensions to a database. * @@ -267,7 +299,9 @@ public final class Presenter { } // set default settings temporarily - this.loadSettings(DEFAULT_SETTINGS_FILEPATH); + CONFIG_FILE.ifPresentOrElse(this::loadSettings, () -> { + this.view.showErrorMessage("Config Loading Error", "Could not load config file - using default settings."); + }); // a Predicate that returns true iff the argument is a full base unit final Predicate isFullBase = unit -> unit instanceof LinearUnit @@ -661,10 +695,12 @@ public final class Presenter { /** * Saves the presenter's current settings to its default filepath. * + * @return true iff this operation succeeded * @since 2022-04-19 */ - public void saveSettings() { - this.saveSettings(DEFAULT_SETTINGS_FILEPATH); + public boolean saveSettings() { + CONFIG_FILE.ifPresent(this::saveSettings); + return CONFIG_FILE.isPresent(); } /** -- cgit v1.2.3 From 370fbe971379d4f833158d41f2c95cb669fb6dbf Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 16 Sep 2023 13:58:52 -0500 Subject: Allow config file to load custom data files The parameters "custom_unit_file", "custom_dimension_file" and "custom_exception_file" can now be used to load custom unit, dimension and exception files. Specify them more than once to load multiple files. I haven't yet added this to the GUI, and I probably won't, because you already need to be able to edit text files to create this, so having a GUI won't make it any more intuitive. --- docs/roadmap.org | 1 - src/main/java/sevenUnitsGUI/Presenter.java | 27 ++++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'docs/roadmap.org') diff --git a/docs/roadmap.org b/docs/roadmap.org index a68dae5..c57fb2a 100644 --- a/docs/roadmap.org +++ b/docs/roadmap.org @@ -17,7 +17,6 @@ Feature Requirements: Data/Configuration Requirements: - All of the data formats (e.g. unit files) should be standardized. -- The config file should be able to specify the location of the data files. Documentation/Testing Requirements: - 7Units should be fully documented. diff --git a/src/main/java/sevenUnitsGUI/Presenter.java b/src/main/java/sevenUnitsGUI/Presenter.java index 3ecfba6..e471b01 100644 --- a/src/main/java/sevenUnitsGUI/Presenter.java +++ b/src/main/java/sevenUnitsGUI/Presenter.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -73,16 +72,16 @@ public final class Presenter { if (System.getProperty("os.name").startsWith("Windows")) { final String envFolder = System.getenv("LOCALAPPDATA"); if (envFolder == null || "".equals(envFolder)) { - configDir = Paths.get(System.getenv("USERPROFILE"), "AppData", "Local", "SevenUnits"); + configDir = Path.of(System.getenv("USERPROFILE"), "AppData", "Local", "SevenUnits"); } else { - configDir = Paths.get(envFolder, "SevenUnits"); + configDir = Path.of(envFolder, "SevenUnits"); } } else { final String envFolder = System.getenv("XDG_CONFIG_HOME"); if (envFolder == null || "".equals(envFolder)) { - configDir = Paths.get(System.getenv("HOME"), ".config", "SevenUnits"); + configDir = Path.of(System.getenv("HOME"), ".config", "SevenUnits"); } else { - configDir = Paths.get(envFolder, "SevenUnits"); + configDir = Path.of(envFolder, "SevenUnits"); } } @@ -99,6 +98,13 @@ public final class Presenter { return Optional.of(configDir.resolve("config.txt")); } + /** Gets a Path from a pathname in the config file. */ + private static Path pathFromConfig(String pathname) { + return CONFIG_FILE.map(configFile -> + configFile.getParent().resolve(pathname) + ).orElse(Path.of(pathname)); + } + /** * Adds default units and dimensions to a database. * @@ -615,6 +621,17 @@ public final class Presenter { switch (param) { // set manually to avoid the unnecessary saving of the non-manual // methods + case "custom_dimension_file": + this.database.loadDimensionFile(pathFromConfig(value)); + break; + case "custom_exception_file": + Files.lines(pathFromConfig(value)) + .map(Presenter::withoutComments) + .forEach(this.metricExceptions::add); + break; + case "custom_unit_file": + this.database.loadUnitsFile(pathFromConfig(value)); + break; case "number_display_rule": this.numberDisplayRule = StandardDisplayRules .getStandardRule(value); -- cgit v1.2.3 From 044b1b6cd5189d0738f9c1382d5971eff717bae1 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 24 Feb 2024 20:22:03 -0500 Subject: Add specification for data files I will have to change a few things to fit this specification; all the better that I made it instead of leaving behaviour unspecified! --- docs/data_spec.org | 39 ++++++++++++++++++++++++++++ docs/data_spec.pdf | Bin 0 -> 89903 bytes docs/data_spec.tex | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++ docs/roadmap.org | 3 --- 4 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 docs/data_spec.org create mode 100644 docs/data_spec.pdf create mode 100644 docs/data_spec.tex (limited to 'docs/roadmap.org') diff --git a/docs/data_spec.org b/docs/data_spec.org new file mode 100644 index 0000000..6cf8712 --- /dev/null +++ b/docs/data_spec.org @@ -0,0 +1,39 @@ +#+TITLE: 7Units Datafile Specification +#+SUBTITLE: For Version 0.5.0 +#+DATE: 2024 February 24 +#+LaTeX_HEADER: \usepackage[a4paper, lmargin=25mm, rmargin=25mm, tmargin=25mm, bmargin=25mm]{geometry} + +#+LaTeX: \newpage +* Unit and Prefix Files +Unit and prefix files specify the units and prefixes that are available to 7Units. Their format is intended to be compatible with 7Units's inspiration, [[https://www.gnu.org/software/units/][GNU Units]]. + +Each unit or prefix is specified by a line in the following format: +#+BEGIN_SRC + +#+END_SRC + +The name may not contain whitespace, but the definition can and often will. Lines can be separated by either a line feed (0x0A) or a carriage return followed by a line feed (0x0D 0x0A). +** Ignored Lines & Comments +All of the following should be ignored: +- Any line containing only whitespace +- Any trailing whitespace +- Any characters between a ~#~ (0x23) character and the end of the line. + +This allows unit and prefix files to be easily organized and divided. +** Unit Expressions +The definition part of a unit's line is a unit expression - the same sort of expression you would use in the complex unit converter. + +Expressions should be a standard mathematical expression, which can operate on either numbers or units. The following operators are supported: addition (+), subtraction (-), multiplication (~*~ or no operator), division (~/~), exponentation (~^~; exponent must be a number). Brackets (~(~ and ~)~) may be used to change order of operations, but otherwise standard BEDMAS order is followed (exponentation first, then multiplication and division, then addition and subtraction), with one exception: if a number is multiplied by a unit using spaces, the multiplication will have precedence over division. For example, "2 m / 1 m" is equal to the dimensionless value 2, not 2 m^2. An example of a line defining a unit is: +#+BEGIN_SRC +yard 9 dm + 1.4 cm + 4 mm^2 / 10 mm +#+END_SRC + +If the definition is an exclamation mark (~!~), this defines a base unit, which is expected to already be stored in the system. +** Prefixes & Prefix Expressions +If a line's name part ends in the ASCII dash (~-~, 0x2D), it defines a prefix instead of a unit (this dash is not included in the prefix's name). Prefix expressions are like unit expressions, but the operands are prefixes and numbers, not units and numbers. Because prefixes do not have a dimension, there are no base prefixes - the exclamation mark is forbidden in prefix expressions. +* Dimension Files +Dimension files give names to unit dimensions, so they can be selected in the unit converter to determine which units are shown. Dimension files are similar to unit and prefix files, except that they use a different set of base /dimensions/ (defined with ! as usual), and that addition and subtraction are not supported in dimension expressions. +* Metric Exception Files +Metric exception files list exceptions to the One-Way Conversion rule. Units included in these files are always shown on both sides of the unit converter, even if One Way Conversion is enabled. They are just a list of units, one per line. Ignored lines and comments work the same way as in other data files. +* Configuration Files +A configuration file contains one line for each configuration setting, in the format ~key=value~. Check the user manual for the list of configurable setting keys. Ignored lines and comments work the same way as in other data files. diff --git a/docs/data_spec.pdf b/docs/data_spec.pdf new file mode 100644 index 0000000..5b3752d Binary files /dev/null and b/docs/data_spec.pdf differ diff --git a/docs/data_spec.tex b/docs/data_spec.tex new file mode 100644 index 0000000..9bcbe14 --- /dev/null +++ b/docs/data_spec.tex @@ -0,0 +1,74 @@ +% Created 2024-03-03 Sun 10:48 +% Intended LaTeX compiler: pdflatex +\documentclass[11pt]{article} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{graphicx} +\usepackage{longtable} +\usepackage{wrapfig} +\usepackage{rotating} +\usepackage[normalem]{ulem} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{capt-of} +\usepackage{hyperref} +\usepackage[a4paper, lmargin=25mm, rmargin=25mm, tmargin=25mm, bmargin=25mm]{geometry} +\date{2024 February 24} +\title{7Units Datafile Specification\\\medskip +\large For Version 0.5.0} +\hypersetup{ + pdfauthor={}, + pdftitle={7Units Datafile Specification}, + pdfkeywords={}, + pdfsubject={}, + pdfcreator={Emacs 29.2 (Org mode 9.6.15)}, + pdflang={English}} +\begin{document} + +\maketitle +\tableofcontents + +\newpage +\section{Unit and Prefix Files} +\label{sec:org2a50c60} +Unit and prefix files specify the units and prefixes that are available to 7Units. Their format is intended to be compatible with 7Units's inspiration, \href{https://www.gnu.org/software/units/}{GNU Units}. + +Each unit or prefix is specified by a line in the following format: +\begin{verbatim} + +\end{verbatim} + +The name may not contain whitespace, but the definition can and often will. Lines can be separated by either a line feed (0x0A) or a carriage return followed by a line feed (0x0D 0x0A). +\subsection{Ignored Lines \& Comments} +\label{sec:orgf5f4195} +All of the following should be ignored: +\begin{itemize} +\item Any line containing only whitespace +\item Any trailing whitespace +\item Any characters between a \texttt{\#} (0x23) character and the end of the line. +\end{itemize} + +This allows unit and prefix files to be easily organized and divided. +\subsection{Unit Expressions} +\label{sec:org7ab7828} +The definition part of a unit's line is a unit expression - the same sort of expression you would use in the complex unit converter. + +Expressions should be a standard mathematical expression, which can operate on either numbers or units. The following operators are supported: addition (+), subtraction (-), multiplication (\texttt{*} or no operator), division (\texttt{/}), exponentation (\texttt{\textasciicircum{}}; exponent must be a number). Brackets (\texttt{(} and \texttt{)}) may be used to change order of operations, but otherwise standard BEDMAS order is followed (exponentation first, then multiplication and division, then addition and subtraction), with one exception: if a number is multiplied by a unit using spaces, the multiplication will have precedence over division. For example, "2 m / 1 m" is equal to the dimensionless value 2, not 2 m\textsuperscript{2}. An example of a line defining a unit is: +\begin{verbatim} +yard 9 dm + 1.4 cm + 4 mm^2 / 10 mm +\end{verbatim} + +If the definition is an exclamation mark (\texttt{!}), this defines a base unit, which is expected to already be stored in the system. +\subsection{Prefixes \& Prefix Expressions} +\label{sec:orgf36901d} +If a line's name part ends in the ASCII dash (\texttt{-}, 0x2D), it defines a prefix instead of a unit (this dash is not included in the prefix's name). Prefix expressions are like unit expressions, but the operands are prefixes and numbers, not units and numbers. Because prefixes do not have a dimension, there are no base prefixes - the exclamation mark is forbidden in prefix expressions. +\section{Dimension Files} +\label{sec:org42d746d} +Dimension files give names to unit dimensions, so they can be selected in the unit converter to determine which units are shown. Dimension files are similar to unit and prefix files, except that they use a different set of base \emph{dimensions} (defined with ! as usual), and that addition and subtraction are not supported in dimension expressions. +\section{Metric Exception Files} +\label{sec:org2390d67} +Metric exception files list exceptions to the One-Way Conversion rule. Units included in these files are always shown on both sides of the unit converter, even if One Way Conversion is enabled. They are just a list of units, one per line. Ignored lines and comments work the same way as in other data files. +\section{Configuration Files} +\label{sec:orgef3d7a7} +A configuration file contains one line for each configuration setting, in the format \texttt{key=value}. Check the user manual for the list of configurable setting keys. Ignored lines and comments work the same way as in other data files. +\end{document} diff --git a/docs/roadmap.org b/docs/roadmap.org index c57fb2a..2eed941 100644 --- a/docs/roadmap.org +++ b/docs/roadmap.org @@ -15,9 +15,6 @@ Feature Requirements: - /Any other feature not listed should be considered optional./ - (/Optional/) It should be possible to add, edit and remove units and prefixes from the GUI unit and prefix viewers. -Data/Configuration Requirements: -- All of the data formats (e.g. unit files) should be standardized. - Documentation/Testing Requirements: - 7Units should be fully documented. - 7Units should have automated testing with a code coverage of at least 2/3 (ideally at least 5/6). -- cgit v1.2.3 From cc45a65c78c578eb404d8773b22e5b046917621f Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 23 Mar 2024 16:02:51 -0500 Subject: Add fractions using | to expressions | is like /, but with higher precedence. This feature is a part of GNU Units, and was included in 7Units for compatibility. --- docs/data_spec.org | 2 +- docs/data_spec.pdf | Bin 89903 -> 90256 bytes docs/data_spec.tex | 18 ++++++------ docs/manual.org | 1 + docs/manual.pdf | Bin 184134 -> 185191 bytes docs/manual.tex | 37 ++++++++++++------------ docs/roadmap.org | 1 - src/main/java/sevenUnits/unit/UnitDatabase.java | 10 +++++-- 8 files changed, 37 insertions(+), 32 deletions(-) (limited to 'docs/roadmap.org') diff --git a/docs/data_spec.org b/docs/data_spec.org index 6cf8712..54780e3 100644 --- a/docs/data_spec.org +++ b/docs/data_spec.org @@ -23,7 +23,7 @@ This allows unit and prefix files to be easily organized and divided. ** Unit Expressions The definition part of a unit's line is a unit expression - the same sort of expression you would use in the complex unit converter. -Expressions should be a standard mathematical expression, which can operate on either numbers or units. The following operators are supported: addition (+), subtraction (-), multiplication (~*~ or no operator), division (~/~), exponentation (~^~; exponent must be a number). Brackets (~(~ and ~)~) may be used to change order of operations, but otherwise standard BEDMAS order is followed (exponentation first, then multiplication and division, then addition and subtraction), with one exception: if a number is multiplied by a unit using spaces, the multiplication will have precedence over division. For example, "2 m / 1 m" is equal to the dimensionless value 2, not 2 m^2. An example of a line defining a unit is: +Expressions should be a standard mathematical expression, which can operate on either numbers or units. The following operators are supported: addition (+), subtraction (-), multiplication (~*~ or no operator), division (~/~ or ~|~), exponentation (~^~; exponent must be a number). Brackets (~(~ and ~)~) may be used to change order of operations, but otherwise standard BEDMAS order is followed (exponentation first, then multiplication and division, then addition and subtraction), with two exceptions: if a number is multiplied by a unit using spaces, the multiplication will have precedence over division, and division with ~|~ has higher precedence than any other operator. For example, "2 m / 1 m" is equal to the dimensionless value 2, not 2 m^2. An example of a line defining a unit is: #+BEGIN_SRC yard 9 dm + 1.4 cm + 4 mm^2 / 10 mm #+END_SRC diff --git a/docs/data_spec.pdf b/docs/data_spec.pdf index 5b3752d..b192e51 100644 Binary files a/docs/data_spec.pdf and b/docs/data_spec.pdf differ diff --git a/docs/data_spec.tex b/docs/data_spec.tex index 9bcbe14..82494c9 100644 --- a/docs/data_spec.tex +++ b/docs/data_spec.tex @@ -1,4 +1,4 @@ -% Created 2024-03-03 Sun 10:48 +% Created 2024-03-23 Sat 16:01 % Intended LaTeX compiler: pdflatex \documentclass[11pt]{article} \usepackage[utf8]{inputenc} @@ -30,7 +30,7 @@ \newpage \section{Unit and Prefix Files} -\label{sec:org2a50c60} +\label{sec:org12eca56} Unit and prefix files specify the units and prefixes that are available to 7Units. Their format is intended to be compatible with 7Units's inspiration, \href{https://www.gnu.org/software/units/}{GNU Units}. Each unit or prefix is specified by a line in the following format: @@ -40,7 +40,7 @@ Each unit or prefix is specified by a line in the following format: The name may not contain whitespace, but the definition can and often will. Lines can be separated by either a line feed (0x0A) or a carriage return followed by a line feed (0x0D 0x0A). \subsection{Ignored Lines \& Comments} -\label{sec:orgf5f4195} +\label{sec:org2f8286a} All of the following should be ignored: \begin{itemize} \item Any line containing only whitespace @@ -50,25 +50,25 @@ All of the following should be ignored: This allows unit and prefix files to be easily organized and divided. \subsection{Unit Expressions} -\label{sec:org7ab7828} +\label{sec:orga5cb10a} The definition part of a unit's line is a unit expression - the same sort of expression you would use in the complex unit converter. -Expressions should be a standard mathematical expression, which can operate on either numbers or units. The following operators are supported: addition (+), subtraction (-), multiplication (\texttt{*} or no operator), division (\texttt{/}), exponentation (\texttt{\textasciicircum{}}; exponent must be a number). Brackets (\texttt{(} and \texttt{)}) may be used to change order of operations, but otherwise standard BEDMAS order is followed (exponentation first, then multiplication and division, then addition and subtraction), with one exception: if a number is multiplied by a unit using spaces, the multiplication will have precedence over division. For example, "2 m / 1 m" is equal to the dimensionless value 2, not 2 m\textsuperscript{2}. An example of a line defining a unit is: +Expressions should be a standard mathematical expression, which can operate on either numbers or units. The following operators are supported: addition (+), subtraction (-), multiplication (\texttt{*} or no operator), division (\texttt{/} or \texttt{|}), exponentation (\texttt{\textasciicircum{}}; exponent must be a number). Brackets (\texttt{(} and \texttt{)}) may be used to change order of operations, but otherwise standard BEDMAS order is followed (exponentation first, then multiplication and division, then addition and subtraction), with two exceptions: if a number is multiplied by a unit using spaces, the multiplication will have precedence over division, and division with \texttt{|} has higher precedence than any other operator. For example, "2 m / 1 m" is equal to the dimensionless value 2, not 2 m\textsuperscript{2}. An example of a line defining a unit is: \begin{verbatim} yard 9 dm + 1.4 cm + 4 mm^2 / 10 mm \end{verbatim} If the definition is an exclamation mark (\texttt{!}), this defines a base unit, which is expected to already be stored in the system. \subsection{Prefixes \& Prefix Expressions} -\label{sec:orgf36901d} +\label{sec:orgac34dfb} If a line's name part ends in the ASCII dash (\texttt{-}, 0x2D), it defines a prefix instead of a unit (this dash is not included in the prefix's name). Prefix expressions are like unit expressions, but the operands are prefixes and numbers, not units and numbers. Because prefixes do not have a dimension, there are no base prefixes - the exclamation mark is forbidden in prefix expressions. \section{Dimension Files} -\label{sec:org42d746d} +\label{sec:orgb96440f} Dimension files give names to unit dimensions, so they can be selected in the unit converter to determine which units are shown. Dimension files are similar to unit and prefix files, except that they use a different set of base \emph{dimensions} (defined with ! as usual), and that addition and subtraction are not supported in dimension expressions. \section{Metric Exception Files} -\label{sec:org2390d67} +\label{sec:org727336c} Metric exception files list exceptions to the One-Way Conversion rule. Units included in these files are always shown on both sides of the unit converter, even if One Way Conversion is enabled. They are just a list of units, one per line. Ignored lines and comments work the same way as in other data files. \section{Configuration Files} -\label{sec:orgef3d7a7} +\label{sec:orge440794} A configuration file contains one line for each configuration setting, in the format \texttt{key=value}. Check the user manual for the list of configurable setting keys. Ignored lines and comments work the same way as in other data files. \end{document} diff --git a/docs/manual.org b/docs/manual.org index 7e343aa..5b36ba7 100644 --- a/docs/manual.org +++ b/docs/manual.org @@ -94,6 +94,7 @@ You can also use the special setting names ~custom_unit_file~, ~custom_dimension A unit expression is simply a math expression where the values being operated on are units or numbers. The operations that can be used are (in order of precedence): - Exponentiation (^); the exponent must be an integer. Both units and numbers can be raised to an exponent - Multiplication (*) and division (/). Multiplication can also be done with a space (so "15 meter" is the same thing as "15 * meter"). + You can also divide with ~|~ to create fractions. Using ~|~ instead of ~/~ gives the division a higher precedence than any other operator. For example, "2|5^2" evaluates to 4/25, not 2/25. - Addition (+) and subtraction (-). They can only be done between units of the same dimension (measuring the same thing). So you can add metres, inches and feet together, and you can add joules and calories together, but you can't add metres to seconds, or feet to calories, or watts to pounds. Brackets can be used to manipulate the order of operations, and nonlinear units like Celsius and Fahrenheit cannot be used in expressions. You can use a value in a nonlinear unit by putting brackets after it - for example, degC(12) represents the value 12 \deg C diff --git a/docs/manual.pdf b/docs/manual.pdf index 66b65b1..22ce98d 100644 Binary files a/docs/manual.pdf and b/docs/manual.pdf differ diff --git a/docs/manual.tex b/docs/manual.tex index 3ed9b35..d5ca426 100644 --- a/docs/manual.tex +++ b/docs/manual.tex @@ -1,4 +1,4 @@ -% Created 2023-09-16 Sat 16:05 +% Created 2024-03-23 Sat 16:00 % Intended LaTeX compiler: pdflatex \documentclass[11pt]{article} \usepackage[utf8]{inputenc} @@ -21,7 +21,7 @@ pdftitle={7Units User Manual}, pdfkeywords={}, pdfsubject={}, - pdfcreator={Emacs 28.1 (Org mode 9.6.7)}, + pdfcreator={Emacs 29.2 (Org mode 9.6.15)}, pdflang={English}} \begin{document} @@ -30,10 +30,10 @@ \newpage \section{Introduction and Purpose} -\label{sec:orgc38fb26} +\label{sec:org0dbe72d} 7Units is a program that can be used to convert units. This document outlines how to use the program. \section{System Requirements} -\label{sec:org0d264f4} +\label{sec:org2bf9298} \begin{itemize} \item Works on all major operating systems \\[0pt] \textbf{NOTE:} All screenshots in this document were taken on Windows 10. If you use a different operating system, the program will probably look different than what is shown. @@ -42,9 +42,9 @@ \newpage \section{How to Use 7Units} -\label{sec:orgdf5e3e6} +\label{sec:orgf02f7d8} \subsection{Simple Unit Conversion} -\label{sec:orga203874} +\label{sec:org527dcdb} \begin{enumerate} \item Select the "Convert Units" tab if it is not already selected. You should see a screen like in figure \ref{main-interface-dimension}: \begin{figure}[htbp] @@ -69,7 +69,7 @@ \end{figure} \end{enumerate} \subsection{Complex Unit Conversion} -\label{sec:org488accc} +\label{sec:org99aaa43} \begin{enumerate} \item Select the "Convert Unit Expressions" if it is not already selected. You should see a screen like in figure \ref{main-interface-expression}: \begin{figure}[htbp] @@ -77,7 +77,7 @@ \includegraphics[height=250px]{../screenshots/main-interface-expression-converter.png} \caption{\label{main-interface-expression}Taken in version 0.3.0} \end{figure} -\item Enter a \hyperref[sec:org0d36b62]{unit expression} in the From box. This can be something like "\texttt{7 km}" or "\texttt{6 ft - 2 in}" or "\texttt{3 kg m + 9 lb ft + (35 mm)\textasciicircum{}2 * (85 oz) / (20 in)}". +\item Enter a \hyperref[sec:orgc3e5dc3]{unit expression} in the From box. This can be something like "\texttt{7 km}" or "\texttt{6 ft - 2 in}" or "\texttt{3 kg m + 9 lb ft + (35 mm)\textasciicircum{}2 * (85 oz) / (20 in)}". \item Enter a unit name (or another unit expression) in the To box. \item Press the Convert button. This will calculate the value of the first expression, and convert it to a multiple of the second unit (or expression). \begin{figure}[htbp] @@ -87,7 +87,7 @@ \end{figure} \end{enumerate} \section{7Units Settings} -\label{sec:org24852a4} +\label{sec:org73b708e} All settings can be accessed in the tab with the gear icon. \begin{figure}[htbp] \centering @@ -95,7 +95,7 @@ All settings can be accessed in the tab with the gear icon. \caption{The settings menu, as of version 0.4.0} \end{figure} \subsection{Rounding Settings} -\label{sec:org49cb400} +\label{sec:orgbf8cfcd} These settings control how the output of a unit conversion is rounded. \begin{description} \item[{Fixed Precision}] Round to a fixed number of \href{https://en.wikipedia.org/wiki/Significant\_figures}{significant digits}. The number of significant digits is controlled by the precision slider below. @@ -103,7 +103,7 @@ These settings control how the output of a unit conversion is rounded. \item[{Scientific Precision}] Intelligent rounding which uses the precision of the input value(s) to determine the output precision. Not affected by the precision slider. \end{description} \subsection{Prefix Repetition Settings} -\label{sec:orgdad3f6a} +\label{sec:org7936321} These settings control when you are allowed to repeat unit prefixes (e.g. kilokilometre) \begin{description} \item[{No Repetition}] Units may only have one prefix. @@ -118,7 +118,7 @@ These settings control when you are allowed to repeat unit prefixes (e.g. kiloki \end{itemize} \end{description} \subsection{Search Settings} -\label{sec:orge892f5f} +\label{sec:orgc26929c} These settings control which prefixes are shown in the "Convert Units" tab. Only coherent SI units (e.g. metre, second, newton, joule) will get prefixes. Some prefixed units are created in the unitfile, and will stay regardless of this setting (though they can be removed from the unitfile). \begin{description} \item[{Never Include Prefixed Units}] Prefixed units will only be shown if they are explicitly added to the unitfile. @@ -126,13 +126,13 @@ These settings control which prefixes are shown in the "Convert Units" tab. Onl \item[{Include All Single Prefixes}] Every coherent unit will have every prefixed version of it included in the list. \end{description} \subsection{Miscellaneous Settings} -\label{sec:orgf983011} +\label{sec:orgf44fa1a} \begin{description} \item[{Convert One Way Only}] In the simple conversion tab, only imperial/customary units will be shown on the left, and only metric units\footnote{7Units's definition of "metric" is stricter than the SI, but all of the common units that are commonly considered metric but not included in 7Units's definition are included in the exceptions file.} will be shown on the right. Units listed in the exceptions file (\texttt{src/main/resources/metric\_exceptions.txt}) will be shown on both sides. This is a way to reduce the number of options you must search through if you only convert one way. The expressions tab is unaffected. \item[{Show Duplicates in "Convert Units"}] If unchecked, any unit that has multiple names will only have one included in the Convert Units lists. The selected name will be the longest; if there are multiple longest names one is selected arbitrarily. You will still be able to use these alternate names in the expressions tab. \end{description} \subsection{Configuration File} -\label{sec:orgf29eb6d} +\label{sec:org9810db1} The settings are saved in a configuration file. On Windows, this is located at \\[0pt] \texttt{\%USERPROFILE\%/AppData/Local/SevenUnits/config.txt}. On other operating systems, this is located at \texttt{\$HOME/.config/SevenUnits/config.txt}. The directory containing the \texttt{SevenUnits} directory can be overridden with the environment variables \texttt{\$LOCALAPPDATA} on Windows or \texttt{\$XDG\_CONFIG\_HOME} elsewhere. @@ -151,18 +151,19 @@ or \texttt{ALL\_METRIC\_PREFIXES}. You can also use the special setting names \texttt{custom\_unit\_file}, \texttt{custom\_dimension\_file} and \texttt{custom\_exception\_file} to add custom units, dimensions and metric exceptions to the system. These files use the same format as the standard files. These setting names can be used more than once to include multiple unit, dimension or exception files. \section{Appendices} -\label{sec:org613821e} +\label{sec:orgaed9ee0} \subsection{Unit Expressions} -\label{sec:org0d36b62} +\label{sec:orgc3e5dc3} A unit expression is simply a math expression where the values being operated on are units or numbers. The operations that can be used are (in order of precedence): \begin{itemize} \item Exponentiation (\^{}); the exponent must be an integer. Both units and numbers can be raised to an exponent \item Multiplication (*) and division (/). Multiplication can also be done with a space (so "15 meter" is the same thing as "15 * meter"). +You can also divide with \texttt{|} to create fractions. Using \texttt{|} instead of \texttt{/} gives the division a higher precedence than any other operator. For example, "2|5\textsuperscript{2}" evaluates to 4/25, not 2/25. \item Addition (+) and subtraction (-). They can only be done between units of the same dimension (measuring the same thing). So you can add metres, inches and feet together, and you can add joules and calories together, but you can't add metres to seconds, or feet to calories, or watts to pounds. \end{itemize} Brackets can be used to manipulate the order of operations, and nonlinear units like Celsius and Fahrenheit cannot be used in expressions. You can use a value in a nonlinear unit by putting brackets after it - for example, degC(12) represents the value 12 \textdegree{} C \subsection{Other Expressions} -\label{sec:org036b96f} +\label{sec:org03a3659} There are also a simplified version of expressions for prefixes and dimensions. Only multiplication, division and exponentation are supported. Currently, exponentation is not supported for dimensions, but that may be fixed in the future. -\end{document} \ No newline at end of file +\end{document} diff --git a/docs/roadmap.org b/docs/roadmap.org index 2eed941..5a3888f 100644 --- a/docs/roadmap.org +++ b/docs/roadmap.org @@ -9,7 +9,6 @@ Feature Requirements: - 7Units's expression converter should support most or all of the conversion features supported by GNU Units: - Converting to sums of units (it should also be possible to do this in the unit converter with preset combinations) - Non-integer exponents - - Fractions in unit expressions (like ~1|6~) - (/Optional/) Inverse nonlinear conversion with the tilde prefix - (/Optional/) Nonlinear units should be specifiable in unit files. - /Any other feature not listed should be considered optional./ diff --git a/src/main/java/sevenUnits/unit/UnitDatabase.java b/src/main/java/sevenUnits/unit/UnitDatabase.java index 7e76729..d738b78 100644 --- a/src/main/java/sevenUnits/unit/UnitDatabase.java +++ b/src/main/java/sevenUnits/unit/UnitDatabase.java @@ -1073,7 +1073,7 @@ public final class UnitDatabase { // add data to expression replacements static { // add spaces around operators - for (final String operator : Arrays.asList("\\*", "/", "\\^")) { + for (final String operator : Arrays.asList("\\*", "/", "\\|", "\\^")) { EXPRESSION_REPLACEMENTS.put(Pattern.compile(operator), " " + operator + " "); } @@ -1231,6 +1231,7 @@ public final class UnitDatabase { .addBinaryOperator("*", (o1, o2) -> o1.times(o2), 1) .addSpaceFunction("*") .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 1) + .addBinaryOperator("|", (o1, o2) -> o1.dividedBy(o2), 3) .addBinaryOperator("^", UnitDatabase::exponentiateUnits, 2) .build(); @@ -1246,6 +1247,7 @@ public final class UnitDatabase { .addBinaryOperator("*", (o1, o2) -> o1.times(o2), 1) .addSpaceFunction("*") .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 1) + .addBinaryOperator("|", (o1, o2) -> o1.dividedBy(o2), 3) .addBinaryOperator("^", UnitDatabase::exponentiateUnitValues, 2) .build(); @@ -1261,6 +1263,7 @@ public final class UnitDatabase { .addBinaryOperator("*", (o1, o2) -> o1.times(o2), 1) .addSpaceFunction("*") .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 1) + .addBinaryOperator("|", (o1, o2) -> o1.dividedBy(o2), 3) .addBinaryOperator("^", (o1, o2) -> o1.toExponent(o2.getMultiplier()), 2) .build(); @@ -1275,6 +1278,7 @@ public final class UnitDatabase { this::getDimension).addBinaryOperator("*", (o1, o2) -> o1.times(o2), 0) .addSpaceFunction("*") .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 0) + .addBinaryOperator("|", (o1, o2) -> o1.dividedBy(o2), 2) .addNumericOperator("^", (o1, o2) -> { int exponent = (int) Math.round(o2.value()); return o1.toExponent(exponent); @@ -1570,7 +1574,7 @@ public final class UnitDatabase { // FIXME the previous operaton also breaks stuff like "1e-5" for (int i = 0; i < modifiedExpression.length(); i++) { if (modifiedExpression.charAt(i) == '-' - && (i < 2 || Arrays.asList('+', '-', '*', '/', '^') + && (i < 2 || Arrays.asList('+', '-', '*', '/', '|', '^') .contains(modifiedExpression.charAt(i - 2)))) { // found a broken negative number modifiedExpression = modifiedExpression.substring(0, i + 1) @@ -1870,7 +1874,7 @@ public final class UnitDatabase { // (i.e. -2 becomes - 2) for (int i = 0; i < modifiedExpression.length(); i++) { if (modifiedExpression.charAt(i) == '-' - && (i < 2 || Arrays.asList('+', '-', '*', '/', '^') + && (i < 2 || Arrays.asList('+', '-', '*', '/', '|', '^') .contains(modifiedExpression.charAt(i - 2)))) { // found a broken negative number modifiedExpression = modifiedExpression.substring(0, i + 1) -- cgit v1.2.3