Skip to content

Commit

Permalink
Dynamically increase decimal places till displayed result is non-zero #…
Browse files Browse the repository at this point in the history
  • Loading branch information
deanishe committed Jan 12, 2018
1 parent 96662e5 commit 6d83e77
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 33 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ Changelog
=========


### [3.5][v3.5] ###

Released 2018-01-12

- Add `DYNAMIC_DECIMALS` setting to expand the number of decimal places until the displayed result is non-zero.


### [3.4][v3.4] ###

Released 2017-12-27
Expand Down Expand Up @@ -160,4 +167,5 @@ Released 2014-08-09.
[v3.3]: https://github.com/deanishe/alfred-convert/releases/tag/v3.3
[v3.3.1]: https://github.com/deanishe/alfred-convert/releases/tag/v3.3.1
[v3.4]: https://github.com/deanishe/alfred-convert/releases/tag/v3.4
[v3.5]: https://github.com/deanishe/alfred-convert/releases/tag/v3.5
[openx]: https://openexchangerates.org/
Binary file not shown.
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,15 @@ The workflow is configured via the configuration sheet (`[𝒙]`) in Alfred Pref

Basic configuration is performed in the configuration sheet:

| Option | Meaning |
|-----------------------|----------------------------------------------------------------------------------------------------------|
| `APP_KEY` | API key for [openexchangerates.org][openx]. |
| `COPY_UNIT` | Include unit when copying conversion result. Any value but `0` or empty turns this option on. |
| `DECIMAL_PLACES` | Number of decimal places to show in results. |
| `DECIMAL_SEPARATOR` | Character to separate whole numbers and decimal fractions. Used for parsing input and generating output. |
| `THOUSANDS_SEPARATOR` | Character to delimit thousands Used for parsing input and generating output. |
| `UPDATE_INTERVAL` | How often (in minutes) to update currency exchange rates. |
| Option | Meaning |
|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
| `APP_KEY` | API key for [openexchangerates.org][openx]. |
| `COPY_UNIT` | Include unit when copying conversion result. Any value but `0` or empty turns this option on. |
| `DECIMAL_PLACES` | Number of decimal places to show in results. |
| `DECIMAL_SEPARATOR` | Character to separate whole numbers and decimal fractions. Used for parsing input and generating output. |
| `DYNAMIC_DECIMALS` | Dynamically increase the number of decimal places (up to 10) so that the result is non-zero. Any value but `0` or empty turns this option on. |
| `THOUSANDS_SEPARATOR` | Character to delimit thousands Used for parsing input and generating output. |
| `UPDATE_INTERVAL` | How often (in minutes) to update currency exchange rates. |


#### Active currencies ####
Expand Down Expand Up @@ -155,6 +156,8 @@ See [CHANGELOG][changelog] for more information.

| Release | Date |
|-----------------|----------------|
| [3.5][v3.5] | 2018-01-12 |
| [3.4][v3.4] | 2017-12-26 |
| [3.3.1][v3.3.1] | 2017-11-21 |
| [3.3][v3.3] | 2017-11-20 |
| [3.2.2][v3.2.2] | 2017-11-07 |
Expand Down Expand Up @@ -214,6 +217,8 @@ All other code/media are released under the [MIT Licence][mit].
[v3.2.2]: https://github.com/deanishe/alfred-convert/releases/tag/v3.2.2
[v3.3]: https://github.com/deanishe/alfred-convert/releases/tag/v3.3
[v3.3.1]: https://github.com/deanishe/alfred-convert/releases/tag/v3.3.1
[v3.4]: https://github.com/deanishe/alfred-convert/releases/tag/v3.4
[v3.5]: https://github.com/deanishe/alfred-convert/releases/tag/v3.5
[cryptocompare]: https://www.cryptocompare.com/
[openx]: https://openexchangerates.org/
[openx-free]: https://openexchangerates.org/signup/free
Expand Down
2 changes: 2 additions & 0 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
DECIMAL_SEPARATOR = os.getenv('DECIMAL_SEPARATOR') or '.'
THOUSANDS_SEPARATOR = os.getenv('THOUSANDS_SEPARATOR') or ''

DYNAMIC_DECIMALS = os.getenv('DYNAMIC_DECIMALS', '') not in ('', '0')
COPY_UNIT = os.getenv('COPY_UNIT', '') not in ('', '0')


# ----------------------------------------------------------------------
# Currency settings
# ----------------------------------------------------------------------
Expand Down
73 changes: 49 additions & 24 deletions src/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
DECIMAL_PLACES,
DECIMAL_SEPARATOR,
DEFAULT_SETTINGS,
DYNAMIC_DECIMALS,
HELP_URL,
ICON_UPDATE,
NOKEY_FILENAME,
Expand Down Expand Up @@ -153,19 +154,63 @@ class Formatter(object):
"""

def __init__(self, decimal_places=2, decimal_separator='.',
thousands_separator=''):
thousands_separator='', dynamic_decimals=True):
"""Create a new `Formatter`."""
self.decimal_places = decimal_places
self.decimal_separator = decimal_separator
self.thousands_separator = thousands_separator
self.dynamic_decimals = dynamic_decimals

def _decimal_places(self, n):
"""Calculate the number of decimal places the result should have.
If :attr:`dynamic_decimals` is `True`, increase the number of
decimal places until the result is non-zero.
Args:
n (float): Number that will be formatted.
Returns:
int: Number of decimal places for result.
"""
log.debug('DYNAMIC_DECIMALS are %s',
('off', 'on')[self.dynamic_decimals])

if not self.dynamic_decimals:
return self.decimal_places

m = max(self.decimal_places, 10) + 1
p = self.decimal_places
while p < m:
e = 10 ** p
i = n * e
# log.debug('n=%f, e=%d, i=%f, p=%d', n, e, i, p)
if n * e >= 10:
break

p += 1

# Remove trailing zeroes
s = str(i)
if '.' not in s: # not a fraction
return p

s = s.split('.')[-1]
# log.debug('s=%s, p=%d', s, p)
while s.endswith('0'):
s = s[:-1]
p -= 1
# log.debug('s=%s, p=%d', s, p)

return p

def formatted(self, n, unit=None):
"""Format number with thousands and decimal separators."""
sep = u''
if self.thousands_separator:
sep = u','

fmt = u'{{:0{}.{:d}f}}'.format(sep, self.decimal_places)
fmt = u'{{:0{}.{:d}f}}'.format(sep, self._decimal_places(n))
num = fmt.format(n)
# log.debug('n=%r, fmt=%r, num=%r', n, fmt, num)
num = num.replace(',', '||comma||')
Expand Down Expand Up @@ -436,27 +481,6 @@ def parse_units(self, query, qty=1):
return from_unit, to_unit


def format_number(n):
"""Format a floating point number with thousands/decimal separators.
Args:
n (float): Number to format
"""
sep = ''
if THOUSANDS_SEPARATOR:
sep = ','

fmt = '{{:0{}.{:d}f}}'.format(sep, DECIMAL_PLACES)
num = fmt.format(n)
# log.debug('n=%r, fmt=%r, num=%r', n, fmt, num)
num = num.replace(',', '||comma||')
num = num.replace('.', '||point||')
num = num.replace('||comma||', THOUSANDS_SEPARATOR)
num = num.replace('||point||', DECIMAL_SEPARATOR)
return num


def register_units():
"""Add built-in and user units to unit registry."""
# Add custom units from workflow and user data
Expand Down Expand Up @@ -541,7 +565,8 @@ def convert(query):
valid=False, icon=ICON_WARNING)

else: # Show results
f = Formatter(DECIMAL_PLACES, DECIMAL_SEPARATOR, THOUSANDS_SEPARATOR)
f = Formatter(DECIMAL_PLACES, DECIMAL_SEPARATOR, THOUSANDS_SEPARATOR,
DYNAMIC_DECIMALS)
wf.setvar('query', query)
for conv in results:
value = copytext = f.formatted(conv.to_number, conv.to_unit)
Expand Down
6 changes: 5 additions & 1 deletion src/info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,8 @@ DECIMAL_PLACES is the number of decimal places to show in conversion results.
DECIMAL_SEPARATOR is the character used to separate whole numbers from decimal fraction when parsing and outputting numbers.
DYNAMIC_DECIMALS is whether to dynamically increase the number of decimal places shown until the result is non-zero. Set to 0 or empty to turn off.
THOUSANDS_SEPARATOR is the character used to separate thousands when parsing and outputting numbers.
UPDATE_INTERVAL is the number of minutes between exchange rate updates.</string>
Expand Down Expand Up @@ -627,6 +629,8 @@ UPDATE_INTERVAL is the number of minutes between exchange rate updates.</string>
<string>2</string>
<key>DECIMAL_SEPARATOR</key>
<string>.</string>
<key>DYNAMIC_DECIMALS</key>
<string>1</string>
<key>THOUSANDS_SEPARATOR</key>
<string>,</string>
<key>UPDATE_INTERVAL</key>
Expand All @@ -637,7 +641,7 @@ UPDATE_INTERVAL is the number of minutes between exchange rate updates.</string>
<string>APP_KEY</string>
</array>
<key>version</key>
<string>3.4</string>
<string>3.5</string>
<key>webaddress</key>
<string></string>
</dict>
Expand Down

0 comments on commit 6d83e77

Please sign in to comment.