Pastey (std/text.e) - format function proposal for revision
- Posted by cargoan Jan 11, 2015
public function format(sequence format_pattern, object arg_list = {}) sequence result integer in_token integer tch integer i integer tend integer cap integer align integer psign integer msign integer zfill integer bwz integer spacer integer alt integer width integer decs integer pos integer argn integer argl integer trimming integer hexout integer binout integer tsep integer istext object prevargv object currargv sequence idname object envsym object envvar integer ep -- added --------------------------------------------------------------------------------------- integer pflag integer count -- --------------------------------------------------------------------------------------------- if atom(arg_list) then arg_list = {arg_list} end if result = "" in_token = 0 i = 0 tend = 0 argl = 0 spacer = 0 prevargv = 0 while i < length(format_pattern) do i += 1 tch = format_pattern[i] if not in_token then if tch = '[' then in_token = 1 tend = 0 cap = 0 align = 0 psign = 0 msign = 0 zfill = 0 bwz = 0 spacer = 0 alt = 0 width = 0 decs = -1 argn = 0 hexout = 0 binout = 0 trimming = 0 tsep = 0 istext = 0 idname = "" envvar = "" envsym = "" else result &= tch end if else switch tch do case ']' then in_token = 0 tend = i case '[' then result &= tch while i < length(format_pattern) do i += 1 if format_pattern[i] = ']' then in_token = 0 tend = 0 exit end if end while case 'w', 'u', 'l' then cap = tch case 'b' then bwz = 1 case 's' then spacer = 1 case 't' then trimming = 1 case 'z' then zfill = 1 case 'X' then hexout = 1 case 'B' then binout = 1 case 'c', '<', '>' then align = tch case '+' then psign = 1 case '(' then msign = 1 case '?' then alt = 1 case 'T' then istext = 1 case ':' then while i < length(format_pattern) do i += 1 tch = format_pattern[i] pos = find(tch, "0123456789") if pos = 0 then i -= 1 exit end if width = width * 10 + pos - 1 if width = 0 then zfill = '0' end if end while case '.' then decs = 0 while i < length(format_pattern) do i += 1 tch = format_pattern[i] pos = find(tch, "0123456789") if pos = 0 then i -= 1 exit end if decs = decs * 10 + pos - 1 end while case '{' then -- Use a named argument. integer sp sp = i + 1 i = sp while i < length(format_pattern) do if format_pattern[i] = '}' then exit end if if format_pattern[i] = ']' then exit end if i += 1 end while idname = trim(format_pattern[sp .. i-1]) & '=' if format_pattern[i] = ']' then i -= 1 end if for j = 1 to length(arg_list) do if sequence(arg_list[j]) then if search:begins(idname, arg_list[j]) then if argn = 0 then argn = j exit end if end if end if if j = length(arg_list) then idname = "" argn = -1 end if end for case '%' then -- Use the environment symbol integer sp sp = i + 1 i = sp while i < length(format_pattern) do if format_pattern[i] = '%' then exit end if if format_pattern[i] = ']' then exit end if i += 1 end while envsym = trim(format_pattern[sp .. i-1]) if format_pattern[i] = ']' then i -= 1 end if envvar = getenv(envsym) argn = -1 if atom(envvar) then envvar = "" end if case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' then if argn = 0 then i -= 1 while i < length(format_pattern) do i += 1 tch = format_pattern[i] pos = find(tch, "0123456789") if pos = 0 then i -= 1 exit end if argn = argn * 10 + pos - 1 end while end if case ',' then if i < length(format_pattern) then i +=1 tsep = format_pattern[i] end if case else -- ignore it end switch if tend > 0 then -- Time to replace the token. sequence argtext = "" if argn = 0 then argn = argl + 1 end if argl = argn if argn < 1 or argn > length(arg_list) then if length(envvar) > 0 then argtext = envvar currargv = envvar else argtext = "" currargv ="" end if else if string(arg_list[argn]) then if length(idname) > 0 then argtext = arg_list[argn][length(idname) + 1 .. $] else argtext = arg_list[argn] end if elsif integer(arg_list[argn]) -- for consistent formatting, we need to test in case of 64-bit euphoria -- changed ------------------------------------------------------------------------------------- -- and arg_list[argn] <= 0x3fff_fff -- ??? and arg_list[argn] <= 0x3fff_ffff -- --------------------------------------------------------------------------------------------- and arg_list[argn] >= -0x4000_0000 then if istext then argtext = {and_bits(0xFFFF_FFFF, math:abs(arg_list[argn]))} elsif bwz != 0 and arg_list[argn] = 0 then argtext = repeat(' ', width) elsif binout = 1 then argtext = stdseq:reverse( convert:int_to_bits(arg_list[argn], 32)) + '0' -- added --------------------------------------------------------------------------------------- if zfill != 0 and width > 0 then if width > length(argtext) then argtext = repeat('0', width - length(argtext)) & argtext end if else count = 1 while count < length(argtext) and argtext[count] = '0' do count += 1 end while argtext = argtext[count .. $] end if -- removed ------------------------------------------------------------------------------------- -- for ib = 1 to length(argtext) do -- if argtext[ib] = '1' then -- argtext = argtext[ib .. $] -- exit -- end if -- end for -- --------------------------------------------------------------------------------------------- elsif hexout = 0 then argtext = sprintf("%d", arg_list[argn]) if zfill != 0 and width > 0 then if argtext[1] = '-' then if width > length(argtext) then argtext = '-' & repeat('0', width - length(argtext)) & argtext[2..$] end if else if width > length(argtext) then argtext = repeat('0', width - length(argtext)) & argtext end if end if end if if arg_list[argn] > 0 then if psign then if zfill = 0 then argtext = '+' & argtext elsif argtext[1] = '0' then argtext[1] = '+' end if end if elsif arg_list[argn] < 0 then if msign then if zfill = 0 then argtext = '(' & argtext[2..$] & ')' else if argtext[2] = '0' then argtext = '(' & argtext[3..$] & ')' else -- Don't need the '(' prefix as its just going to -- be trunctated to fit the requested width. argtext = argtext[2..$] & ')' end if end if end if end if else argtext = sprintf("%x", arg_list[argn]) if zfill != 0 and width > 0 then if width > length(argtext) then argtext = repeat('0', width - length(argtext)) & argtext end if end if end if elsif atom(arg_list[argn]) then if istext then argtext = {and_bits(0xFFFF_FFFF, math:abs(floor(arg_list[argn])))} else if hexout then argtext = sprintf("%x", arg_list[argn]) if zfill != 0 and width > 0 then if width > length(argtext) then argtext = repeat('0', width - length(argtext)) & argtext end if end if else argtext = trim(sprintf("%15.15g", arg_list[argn])) -- Remove any leading 0 after e+ while ep != 0 with entry do argtext = remove(argtext, ep+2) entry ep = match("e+0", argtext) end while if zfill != 0 and width > 0 then if width > length(argtext) then if argtext[1] = '-' then argtext = '-' & repeat('0', width - length(argtext)) & argtext[2..$] else argtext = repeat('0', width - length(argtext)) & argtext end if end if end if if arg_list[argn] > 0 then if psign then if zfill = 0 then argtext = '+' & argtext elsif argtext[1] = '0' then argtext[1] = '+' end if end if elsif arg_list[argn] < 0 then if msign then if zfill = 0 then argtext = '(' & argtext[2..$] & ')' else if argtext[2] = '0' then argtext = '(' & argtext[3..$] & ')' else argtext = argtext[2..$] & ')' end if end if end if end if end if end if else if alt != 0 and length(arg_list[argn]) = 2 then object tempv if atom(prevargv) then if prevargv != 1 then tempv = arg_list[argn][1] else tempv = arg_list[argn][2] end if else if length(prevargv) = 0 then tempv = arg_list[argn][1] else tempv = arg_list[argn][2] end if end if if string(tempv) then argtext = tempv elsif integer(tempv) then if istext then argtext = {and_bits(0xFFFF_FFFF, math:abs(tempv))} elsif bwz != 0 and tempv = 0 then argtext = repeat(' ', width) else argtext = sprintf("%d", tempv) end if elsif atom(tempv) then if istext then argtext = {and_bits(0xFFFF_FFFF, math:abs(floor(tempv)))} elsif bwz != 0 and tempv = 0 then argtext = repeat(' ', width) else argtext = trim(sprintf("%15.15g", tempv)) end if else argtext = pretty:pretty_sprint( tempv, {2,0,1,1000,"%d","%.1
 
		

