It is currently May 6th, 2024, 7:40 am

Suggestion: String Meter enhancement - Redux

Report bugs with the Rainmeter application and suggest features.
User avatar
Mordasius
Posts: 1173
Joined: January 22nd, 2011, 4:23 pm
Location: GMT +8

Re: Suggestion: String Meter enhancement - Redux

Post by Mordasius »

jsmorley wrote:I'd be curious to see what you came up with for the Lua, I don't think string.format (printf more or less) can quite do exactly what you want in and of itself, so it feels like you might have to "stringify" the number and do some moderately complicated analysis to handle stuff like numbers that are already longer than the desired length, integers with no decimal, negative numbers, etc.
and maybe you were about to say that this would be easy peasy using LUA's string.format with a monospaced or fixed-width font (like Consolas, Courier, ‎Lucida, ‎Monaco, etc.) but a waste of effort with other fonts.
Last edited by Mordasius on May 6th, 2015, 1:50 pm, edited 1 time in total.
User avatar
jsmorley
Developer
Posts: 22631
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Suggestion: String Meter enhancement - Redux

Post by jsmorley »

Mordasius wrote: ...and maybe you were about to say that this would be easy peasy using LUA's string.format with a monospaced or fixed-width font (like Courier) but a waste of effort with other fonts....
I might have been... ;-)

But as I said, I'm not in the business of critiquing "design", beauty is in the eye of the beholder. The ten-thousand Rainmeter skins with animated My Little Pony characters is evidence of that...
User avatar
eclectic-tech
Rainmeter Sage
Posts: 5407
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Suggestion: String Meter enhancement - Redux

Post by eclectic-tech »

Mordasius wrote: and maybe you were about to say that this would be easy peasy using LUA's string.format with a monospaced or fixed-width font (like Consolas, Courier, ‎Lucida, ‎Monaco, etc.) but a waste of effort with other fonts.
Here is Mordasius's sample! :thumbup:
User avatar
jsmorley
Developer
Posts: 22631
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Suggestion: String Meter enhancement - Redux

Post by jsmorley »

eclectic-tech wrote: Here is Mordasius's sample! :thumbup:
Not quite what the user is looking for though. His concern isn't with "justifying" the text left or right, but simply making any number a fixed number of "characters" by rounding / padding / truncating the value so if for instance he wants a consistent character length of 10, he wants to format:

Code: Select all

123.1234
0
12
-123456.0
12345678905.123
all as 10 "characters", while maintaining the correct value if rounding is needed.

http://docs.rainmeter.net/snippets/round

So presumably:

Code: Select all

123.123400
0.00000000
12.0000000
-123456.00
1234567891
With a fixed-width font, or a font with at least fixed-width numbers, as moshi points out, this would indeed give you a very consistent pixel length for the numbers.

I don't think string.format alone is going to do it. I actually think it will be moderately tricky, although I can't say I have really taken a hard look at it.

The other rub of course is that as soon as he has this, he is going to find that it isn't going to work with AutoScale on a String meter, and he is probably going to first scale it himself in Lua, and set the B/s, kB/s, MB/s indicators aside. Then format the length, and tack on the scale indicators.

http://docs.rainmeter.net/snippets/autoscale
User avatar
Mordasius
Posts: 1173
Joined: January 22nd, 2011, 4:23 pm
Location: GMT +8

Re: Suggestion: String Meter enhancement - Redux

Post by Mordasius »

jsmorley wrote:.. beauty is in the eye of the beholder. The ten-thousand Rainmeter skins with animated My Little Pony characters is evidence of that...
Ten thousand dreams I have had
In every one a pony dancing
It's all over now and I'm wide awake
Looking for a thread to shake
If I could poke the beholder's eye
Just to prove a pony would cry
And here it is an animation
I think of you and your creation - and then hit delete


with apologies to Fahrenkrog-petersen, Joern-uwe/karges, Carlo/mc Alea, Kevin and a nod to those that translated 99 Red Balloons to English
User avatar
jsmorley
Developer
Posts: 22631
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Suggestion: String Meter enhancement - Redux

Post by jsmorley »

Mordasius wrote: Ten thousand dreams I have had
In every one a pony dancing
It's all over now and I'm wide awake
Looking for a thread to shake
If I could poke the beholder's eye
Just to prove a pony would cry
And here it is an animation
I think of you and your creation - and then hit delete


with apologies to Fahrenkrog-petersen, Joern-uwe/karges, Carlo/mc Alea, Kevin and a nod to those that translated 99 Red Balloons to English
LOL! That's great...
User avatar
SilverAzide
Rainmeter Sage
Posts: 2618
Joined: March 23rd, 2015, 5:26 pm

Re: Suggestion: String Meter enhancement - Redux

Post by SilverAzide »

Hi guys,
Since you asked, here's the Lua script I came up with. It's my first attempt at Lua, so I'm sure there are plenty of better ways to skin this cat. Feedback is welcome!

(This will be part of the Gadgets suite I'm working on, thus the references in the file. The measure's output matches the number formatting of the old addgadgets.com Windows Sidebar gadgets I am trying to emulate.)

Code: Select all

--
-- GadgetsFormatter v1.0 by SilverAzide
--
-- This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 License.
--
----------------------------------------------------------------------------------------------------
--
-- Rainmeter's String meter formats numbers using a "variable scale, fixed precision" methodology.
-- ("Scale" is the total number of digits, not including signs and decimals, and "precision" is the
-- number of digits after the decimal.)
--
--   Examples:  3.141      (scale=4, precision=3; i.e., "NumOfDecimals=3")
--              314.159    (scale=6, precision=3)
--              3141.593   (scale=7, precision=3)
--              314159.265 (scale=9, precision=3)
--
-- This script uses a "fixed scale, variable precision" methodology when formatting numbers.  This
-- results in values that have a predicable string length and can lead to a cleaner looking display.
-- This will also match the formatting of the original addgadgets.com Sidebar gadgets.
--
--   Examples:  3.14159  (scale=6, precision=5)
--              314.159  (scale=6, precision=3)
--              3141.53  (scale=6, precision=2)
--              314159   (scale=6, precision=0)
--
-- This script implies use of "AutoScale" (i.e., all values will be scaled).  If scaling is not
-- desired, use the existing Rainmeter String meter instead.
--
-- Using this script involves "wrapping" the formatting script measure around the meter that will
-- display the result.  When using Rainmeter normally, a measure's output is used as the input to a
-- String meter.  When using this script, a measure's output is used as input to the script
-- measure, and the output of the script measure is then used as input to a String meter.
--
-- REMEMBER:
--
--   This measure returns a formatted STRING.  Numeric formatting options in String meters will
--   not have any effect (NumOfDecimals, Scale, AutoScale, etc.).
--
-- Options
--
--   MeasureName
--
--     The name of the measure to be bound to this one (i.e., the source of the input value).
--
--   Factor
--
--     Specifies the scale factor.  Same as the Rainmeter String meter's "AutoScale" option:
--
--       1:  Scales by 1024 (default).
--       1k: Scales by 1024 with kilo as the lowest unit.
--       2:  Scales by 1000.
--       2k: Scales by 1000 with kilo as the lowest unit.
--
--     NOTE:
--
--       The value returned by the plugin includes a space between the scaled number and the scale
--       unit abbreviation.  To remove this space simply add Substitute=" ":"" to the measure.
--
--   Scale
--
--     Specifies the numeric scale (i.e., the number of digits in the number).  The default is 3.
--
--
-- Example skin:
--
-- ; measure network inbound bytes/sec
-- [MeasureNetIn]
-- Measure=NetIn
-- Interface=0
--
-- ; measure to format inbound bytes/sec; e.g., "12.34 M"
-- [FormatNetIn]
-- Measure=Script
-- ScriptFile=#@#GadgetsFormatter.lua
-- MeasureName=MeasureNetIn
-- Scale=4
-- Factor=1k
--
-- ; display inbound bytes/sec; e.g., "12.34 MB/s"
-- [MeterNetIn]
-- Meter=String
-- MeasureName=FormatNetIn
-- Text="%1B/s"
--
----------------------------------------------------------------------------------------------------
--
function Initialize()
  --
  -- this function is called when the measure is initialized or reloaded
  --

  -- initialize array of suffixes for scaled values
  asSuffix = { " ", " k", " M", " G", " T", " P", " E", " Z", " Y" }

  -- initialize default divisor
  nDivisor = 1024.0

  --
  -- get measure options
  --
  sMeasureName = SELF:GetOption("MeasureName")
  nScale = math.floor(tonumber(SELF:GetOption("Scale")))
  sFactor = string.lower(SELF:GetOption("Factor"))

  -- get a reference to the specified input measure
  msMeasure = SKIN:GetMeasure(sMeasureName)

  --
  -- do validation
  --
  -- validate Scale
  if nScale > 0 then
    -- OK
  else
    -- invalid or missing input
    nScale = 3
  end

  -- validate Factor and initialize divisor if needed
  if sFactor == "1k" then
    -- OK
  elseif sFactor == "2" or sFactor == "2k" then
    nDivisor = 1000.0
  else
    sFactor = "1"
  end

  return
end                                                                                    -- Initialize

function Update()
  --
  -- this function is called whenever the measure is updated
  --

  -- initialize local vars
  local nDigitsAfterDecimal = 0
  local nDigitsBeforeDecimal = 0
  local nDivCount = 1
  local sPattern = ""
  local sText = ""

  -- get the current value of the input measure
  local nValue = msMeasure:GetValue()

  -- if minimum value is K, divide value by divisor
  if sFactor == "1k" or sFactor == "2k" then
    nValue = nValue / nDivisor
    nDivCount = nDivCount + 1
  end

  --
  -- format the value as text
  --
  while true do
    if math.abs(nValue) < nDivisor then
      nDigitsBeforeDecimal = math.max(1, math.floor(math.log10(math.abs(nValue))) + 1)
      nDigitsAfterDecimal = math.max(0, nScale - nDigitsBeforeDecimal)

      -- get formatting directive and get the formatted string
      sPattern = "%." .. nDigitsAfterDecimal .. "f"
      sText = string.format(sPattern, nValue)
      break

    else
      nValue = nValue / nDivisor
      nDivCount = nDivCount + 1
    end
  end

  return(sText .. asSuffix[nDivCount])
end                                                                                        -- Update
Gadgets Wiki GitHub More Gadgets...
User avatar
jsmorley
Developer
Posts: 22631
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Suggestion: String Meter enhancement - Redux

Post by jsmorley »

So you knocked that out after a few minutes of looking at the Rainmeter Lua docs, my crappy little tutorial skin, and presumably the online Lua docs / tutorials as a reference?

Note to self: DO NOT EVER humiliate yourself by arguing with this guy about anything having to do with programming.

The only thing I might suggest you at least think about is having this be a callable Lua "function", rather than using the Update() function that is called on every update of the measure.

So for instance on a measure that you want to get this treatment when the value cahanges you can:

OnChangeAction=[!CommandMeasure ScriptMeasureName "FunctionName('parm1','parm2','parm3'"]

The advantages to this are:

1) You don't need a separate Script measure for each measure that you want to apply this to.
2) You can pass the value that you want to format as a parameter, rather than having the Lua script have to "come get it".
3) You can limit when this is actually executed to when it is actually needed, and not on every skin update.

There are different ways to come at this. You might pass the name of a String meter as one of the parameters, and have the Lua do SKIN:Bang('!SetOption', someMeter, 'Text', someValue), or you might have the Lua set a variable that you pass the name of in the parameters like SKIN:Bang('!SetVariable', varName, someValue) and just have the String meter dynamically use the #VarName# variable as the Text.

So for instance:

Skin:
[MeasureNetIn]
Measure=NetIn
OnChangeAction=[!CommandMeasure FormatScript "Format([MeasureNetIn],NetInVar)"]

[FormatScript]
Measure=Script
ScriptFile=FormatNumber.lua

[MeterNetIn]
Meter=String
Text=#NetInVar#

FormatNumber.lua:
function Format(arg1, arg2)
...format arg1...
SKIN:Bang('!SetVariable', arg2, arg1)
end

Anyway, nice work.
User avatar
moshi
Posts: 1740
Joined: November 13th, 2012, 9:53 pm

Re: Suggestion: String Meter enhancement - Redux

Post by moshi »

just for fun, please ignore:

Code: Select all

[Variables]
Length=9

[MeasureMem]
Measure=PhysicalMemory
RegExpSubstitute=1
Substitute="\d":"","\.":""

[MeasureMem2]
Measure=Calc
Formula=round(MeasureMem/1024**((MeasureMem=0?1:ceil(log(MeasureMem)/(10*log(2))))-1),(#Length#-2))
RegExpSubstitute=1
Substitute="^(.+)$":"\1.000000000000000000000000","^(.+)\.(.+)\.(.+)$":"\1.\2\3","^(.{#Length#}).*$":"\1"

[MeterTime]
Meter=String
MeasureName=MeasureMem
AutoScale=1
PostFix=B
Prefix=[MeasureMem2]
DynamicVariables=1
(formula stolen from smurfier)
User avatar
SilverAzide
Rainmeter Sage
Posts: 2618
Joined: March 23rd, 2015, 5:26 pm

Re: Suggestion: String Meter enhancement - Redux

Post by SilverAzide »

jsmorley wrote:The only thing I might suggest you at least think about is having this be a callable Lua "function", rather than using the Update() function that is called on every update of the measure.
OK! I see what you mean, I have a ton of Script measures, and this would get rid of all that overhead. I'll give that a shot!
Last edited by SilverAzide on May 6th, 2015, 6:18 pm, edited 1 time in total.
Gadgets Wiki GitHub More Gadgets...