diff --git a/README.org b/README.org index 2c0a9f4..3fd150e 100644 --- a/README.org +++ b/README.org @@ -1,16 +1,38 @@ -* units-global-mode +* units-mode This mode uses [[https://www.gnu.org/software/units/units.html][gnu units]] to facilitate unit conversions inside emacs. *This package is a work in progress* +* Contents :TOC: +- [[#units-mode][units-mode]] +- [[#features][Features]] +- [[#installation][Installation]] +- [[#examples][Examples]] + - [[#simple-conversion][Simple conversion]] + - [[#derived-units][Derived units]] + - [[#multiple-units][Multiple units]] + * Features - [X] convert region to other units -- [ ] check ~--conformable~ units +- [X] check ~--conformable~ units for completion + +* Installation +First clone this repo into your local machine, then you can load it. + +An example config using ~use-package~ is like this: +#+begin_src emacs-lisp +(use-package units-mode + :load-path "/path/to/units-mode" + :hook text-mode + :config + (local-set-key (kbd "C-c u") 'units-convert-region-and-insert)) +#+end_src -* Example +* Examples +** Simple conversion If you have L = 23 ft @@ -19,13 +41,33 @@ And you ran ~units-convert-region-and-insert~ while selecting ~23 ft~ you'll be L = 23 ft = 7010.4 mm + There is completion for the target unit, that is non-exhaustive. So feel free to type whatever unit you want to. But pressing tab will help you see some of them. + +** Derived units + Similarly, g = 9.81 m/s^2 g = 9.81 m/s^2 = 32.185039 ft/s^2 -There is completion for the target unit, that is non-exhaustive as it only includes defined units and not derived ones like ~ft/s^2~ +Completion only includes defined units and not derived ones like ~ft/s^2~, so you need to type it fully. Running ~units-convert-region~ will just show the converted results in the minibuffer. If there is errors, like units aren't matched then it'll end with the error from ~units~ + +** Multiple units +Since units can allow you to convert to multiple units, this package also can. + +For example using ~ft;in~ in ~1m~ here returns this: + + L = 1m + L = 1m = 3 ft + 3.3700787 in + L = 1m = 3 ft + 3.3700787 in = 100 cm + + As you can see in the third line, you can use that value again to convert to something else as ~units~ supports simple calculations on units. + +Also note that it'll remove the unit with 0 coefficient, for example converting ~1mile~ to ~ft;in~ will result in this: + + L = 1mile + L = 1mile = 5280 ft diff --git a/tests/units-tests.el b/tests/units-tests.el index 83386f5..7ddd575 100644 --- a/tests/units-tests.el +++ b/tests/units-tests.el @@ -2,15 +2,44 @@ ;; conversion tests (ert-deftest units-convert-single-test () - (should (= (units-convert-single 10 "ft" "m") 3.048)) - (should (= (units-convert-single 1 "m" "ft") 3.2808399)) - (should (= (units-convert-single 1 "kg" "g") 1e3)) - (should (= (units-convert-single 1 "hour" "seconds") (* 60 60))) - (should (= (units-convert-single 1 "day" "hour") 24))) + (should (= (string-to-number + (units-convert-single 10 "ft" "m")) 3.048)) + (should (= (string-to-number + (units-convert-single 1 "m" "ft")) 3.2808399)) + (should (= (string-to-number + (units-convert-single 1 "kg" "g")) 1e3)) + (should (= (string-to-number + (units-convert-single 1 "hour" "seconds")) (* 60 60))) + (should (= (string-to-number + (units-convert-single 1 "day" "hour")) 24))) (ert-deftest units-convert-test () - (should (= (units-convert "10ft" "m") 3.048)) - (should (= (units-convert "1 m" "ft") 3.2808399)) - (should (= (units-convert "1kg" "g") 1e3)) - (should (= (units-convert "1 hour" "seconds") (* 60 60))) - (should (= (units-convert "1 day" "hour") 24))) + (should (= (string-to-number + (units-convert "10ft" "m")) 3.048)) + (should (= (string-to-number + (units-convert "1 m" "ft")) 3.2808399)) + (should (= (string-to-number + (units-convert "1kg" "g")) 1e3)) + (should (= (string-to-number + (units-convert "1 hour" "seconds")) (* 60 60))) + (should (= (string-to-number + (units-convert "1 day" "hour")) 24)) + (should (string= (units-convert "1.5 day" "day;hour") "1;12")) + (should (string= (units-convert ".5 day" "day;hour") "0;12"))) + +(ert-deftest units-convert-formatted-test () + (should (string= + (units-convert-formatted "10ft" "m") "3.048 m")) + (should (string= + (units-convert-formatted "1 m" "ft") "3.2808399 ft")) + (should (string= + (units-convert-formatted "1kg" "g") "1000 g")) + (should (string= + (units-convert-formatted "1 hour" "seconds") "3600 seconds")) + (should (string= + (units-convert-formatted "1 day" "hours") "24 hours")) + (should (string= + (units-convert-formatted "1.5 day" "day;hours") + "1 day + 12 hours")) + (should (string= + (units-convert-formatted ".5 day" "day;hours") "12 hours"))) diff --git a/units-mode.el b/units-mode.el index d4d4fe5..8e237f2 100644 --- a/units-mode.el +++ b/units-mode.el @@ -29,6 +29,7 @@ ;; This is emacs interface to gnu units program . ;;; Code: +(require 'cl-lib) (defcustom units-binary-path "units" "Path to the units binary.") @@ -56,15 +57,34 @@ value))) (defun units-convert (value to-unit) - (let ((out-lines (split-string (string-trim-right (units-command value to-unit)) "\n"))) + (let ((out-lines (split-string + (string-trim-right + (units-command value to-unit)) "\n"))) (if (length= out-lines 1) - (string-to-number (car out-lines)) + (car out-lines) (user-error "%s" (string-join out-lines "\n"))))) (defun units-convert-single (value from-unit to-unit) (units-convert (format "%s %s" value from-unit) to-unit)) +(defun units-convert-formatted (value to-unit) + (let ((converted (units-convert value to-unit))) + (if (cl-search ";" to-unit) + (let ((values (split-string converted ";")) + (units (split-string to-unit ";"))) + (string-join + (cl-loop for val in values + for unt in units + if (> (string-to-number val) 0) + collect (format "%s %s" val unt)) " + ")) + (format "%s %s" converted to-unit)))) + +(setq values (split-string "1;0;1" ";")) +(setq units (split-string "m;cm;mm" ";")) + + + (defun units-conformable-list (value) (split-string (string-trim @@ -79,7 +99,7 @@ (completing-read "Convert to: " (units-conformable-list region-text))))) - (message "%s" (units-convert region-text to-unit))) + (message "%s" (units-convert-formatted region-text to-unit))) (defun units-convert-region-and-insert (region-text to-unit) (interactive @@ -90,13 +110,12 @@ (completing-read "Convert to: " (units-conformable-list region-text))))) - (save-excursion - (goto-char (region-end)) - (insert (concat " = " - (number-to-string - (units-convert region-text to-unit)) - " " - to-unit)))) + (goto-char (region-end)) + (insert (concat " = " + (units-convert-formatted region-text to-unit)))) + +(define-minor-mode units-mode + "Minor mode for Calculations related to units.") (provide 'units-mode)