# HG changeset patch # User akaeba # Date 1619953576 -7200 # Sun May 02 13:06:16 2021 +0200 # Node ID 9e7b36df760b2b79e0a4556b9cf2aea30f72eb65 # Parent 3d34b70b5a4949af35c15981cb7835da07cda47d pad.m: adds leading/trailing chars to string for pad * scripts/strings/pad.m: initial draft add initial implementation draft of matlabs pad function diff -r 3d34b70b5a49 -r 9e7b36df760b scripts/strings/module.mk --- a/scripts/strings/module.mk Fri Apr 16 23:06:32 2021 -0400 +++ b/scripts/strings/module.mk Sun May 02 13:06:16 2021 +0200 @@ -20,6 +20,7 @@ %reldir%/mat2str.m \ %reldir%/native2unicode.m \ %reldir%/ostrsplit.m \ + %reldir%/pad.m \ %reldir%/regexptranslate.m \ %reldir%/rindex.m \ %reldir%/startsWith.m \ diff -r 3d34b70b5a49 -r 9e7b36df760b scripts/strings/pad.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/strings/pad.m Sun May 02 13:06:16 2021 +0200 @@ -0,0 +1,235 @@ +######################################################################## +## +## Copyright (C) 1996-2021 The Octave Project Developers +## +## See the file COPYRIGHT.md in the top-level directory of this +## distribution or . +## +## This file is part of Octave. +## +## Octave is free software: you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . +## +######################################################################## + +## -*- texinfo -*- +## @deftypefn {} {@var{s} =} pad (@var{str}) +## @deftypefnx {} {@var{s} =} pad (@var{str}, @var{numberOfCharacters}) +## @deftypefnx {} {@var{s} =} pad (@var{str}, @var{side}) +## @deftypefnx {} {@var{s} =} pad (@var{str}, @var{numberOfCharacters}, @var{side}) +## @deftypefnx {} {@var{s} =} pad (@var{str}, @var{numberOfCharacters}, @var{side}, @var{padCharacter}) +## @cindex string length fixed +## Add leading and/or trailing characters to @var{s} +## +## If @var{str} is a cell array, @var{pad} adds to each string space characters +## except the longest string in the cell array. Two dimensional @var{str} +## character arrays stays untouched due automatic blank pad while definition. +## +## The total length of each element in @var{s} is defined by @var{numberOfCharacters}. +## If @var{str} has more characters as in @var{numberOfCharacters} specified no modifiction +## is done. +## +## @var{side} selects the side to fill with spaces. Valid arguments are +## 'left', 'right', 'both'. The default is 'right'. +## +## @var{padCharacter} overwrites the default blank pad by an character +## +## @example +## @group +## pad("Alexandra") +## @result{} "Alexandra" +## +## pad("Alexandra", 4) +## @result{} "Alexandra" +## +## pad("Alexandra", 12) +## @result{} "Alexandra " +## +## pad("Johannes", 15, 'left') +## @result{} " Johannes" +## +## pad(@{"Uta", "Elizabet", "Jakob"@}) +## @result{} +## @{ +## [1,1] = "Uta " +## [1,2] = "Elizabet" +## [1,3] = "Jakob " +## @} +## +## pad(@{"Uta", "Elizabet", "Jakob"@}, 'left') +## @result{} +## @{ +## [1,1] = " Uta" +## [1,2] = "Elizabet" +## [1,3] = " Jakob" +## @} +## +## pad(@{"Uta", "Elizabet", "Jakob"@}, 'both') +## @result{} +## @{ +## [1,1] = " Uta " +## [1,2] = "Elizabet" +## [1,3] = " Jakob " +## @} +## +## pad(@{"1.12", "10.42", "0.18"@}, 6, 'left', '0') +## @result{} +## @{ +## [1,1] = "001.12" +## [1,2] = "010.42" +## [1,3] = "000.18" +## @} +## @end group +## @end example +## +## @seealso{erase, join, replace, split, strip, strsplit} +## @end deftypefn + +function s = pad (str, varargin) + + s = str; + + ## Distinguish arguments + switch nargin + case 0 + print_usage (); + case 1 + numberOfCharacters = -1; + side = 'right'; + padCharacter = ' '; + case 2 + padCharacter = ' '; + # third argument can be 'numberOfCharacters' or 'side' + if ( isnumeric(varargin{1}) ) + numberOfCharacters = varargin{1}; + side = 'right'; + else + numberOfCharacters = -1; + side = varargin{1}; + endif + case 3 + numberOfCharacters = varargin{1}; + side = varargin{2}; + padCharacter = ' '; + case 4 + numberOfCharacters = varargin{1}; + side = varargin{2}; + padCharacter = varargin{3}; + otherwise + print_usage (); + endswitch + + ## Check for valid input + if (! ischar(padCharacter) ) + error ("Character to pad with: ' ' (default) | character"); + elseif ( 1 ~= length(padCharacter) ) + error ("Character pad dimension 1x0"); + endif + + ## Determine max string length + if ( -1 == numberOfCharacters ) + if ( iscell(str) ) + numberOfCharacters = max(max(cellfun(@length, str))); + else + numberOfCharacters = length(str); + endif + elseif ( 1 > numberOfCharacters ) + error("Total number of characters in output strings, specified as a positive integer.") + endif + + ## Dispatch based on input string type + if ( ischar(str) ) + ## in two dimensional char array is blank pad automatically performed + ## [row col] = size(str) + if ( 1 == min(size(str)) || (0 == min(size(str))) ) + s(1:max(length(str), numberOfCharacters)) = padCharacter; + if ( strcmp(side, 'right') ) + s(1:length(str)) = str; + elseif ( strcmp(side, 'left') ) + s(end-length(str)+1:end) = str; + elseif ( strcmp(side, 'both') ) + l = floor((length(s)+length(str))/2) - length(str) + 1; + r = l + length(str) - 1; + s(l:r) = str; + else + error ("Side of string to pad: 'right' (default) | 'left' | 'both'"); + endif + endif + elseif ( iscell(str) ) + s = cellfun(@(x) pad(x, numberOfCharacters, side, padCharacter), str, 'UniformOutput', false); + else + error ("Input text: string | char | cell"); + endif; +endfunction + + +## misc +%!assert (pad("abc"), "abc") ## nothing +%!assert (pad("abc", 'left'), "abc") ## pad site +%!assert (pad("abc", 'right'), "abc") ## +%!assert (pad("abc", 'both'), "abc") ## +%!assert (pad(""), "") ## empty +%!assert (pad("abc", 5), "abc ") ## pad +%!assert (pad("abcdefg", 5), "abcdefg") ## truncate +%!assert (pad({"Uta"; "Elizabet"; "Jakob"}, 'left'), {" Uta"; "Elizabet"; " Jakob"}) ## +%!assert (pad(["Uta"; "Elizabet"; "Jakob"], 'left'), ["Uta "; "Elizabet"; "Jakob "]) ## untouched + +## input +%!assert (pad("abc", 3, 'right'), "abc") +%!assert (pad("ab", 3, 'right'), "ab ") +%!assert (pad("a", 3, 'right'), "a ") +%!assert (pad("", 3, 'right'), " ") +%!assert (pad("abc", 3, 'left'), "abc") +%!assert (pad("ab", 3, 'left'), " ab") +%!assert (pad("a", 3, 'left'), " a") +%!assert (pad("", 3, 'left'), " ") +%!assert (pad("abc", 3, 'both'), "abc") +%!assert (pad("ab", 3, 'both'), "ab ") +%!assert (pad("a", 3, 'both'), " a ") +%!assert (pad("", 3, 'both'), " ") + +## pad length +%!assert (pad("abc", 5, 'right'), "abc ") +%!assert (pad("abc", 4, 'right'), "abc ") +%!assert (pad("abc", 3, 'right'), "abc") +%!assert (pad("abc", 2, 'right'), "abc") +%!assert (pad("abc", 1, 'right'), "abc") +%!assert (pad("abc", 5, 'left'), " abc") +%!assert (pad("abc", 4, 'left'), " abc") +%!assert (pad("abc", 3, 'left'), "abc") +%!assert (pad("abc", 2, 'left'), "abc") +%!assert (pad("abc", 1, 'left'), "abc") +%!assert (pad("abc", 5, 'both'), " abc ") +%!assert (pad("abc", 4, 'both'), "abc ") +%!assert (pad("abc", 3, 'both'), "abc") +%!assert (pad("abc", 2, 'both'), "abc") +%!assert (pad("abc", 1, 'both'), "abc") + +## pad type +%!assert (pad("abc", 5, 'right', '*'), "abc**") +%!assert (pad("abc", 5, 'left', '*'), "**abc") +%!assert (pad("abc", 5, 'both', '*'), "*abc*") + +## cell, uses via cellfun str pad +%!assert (pad({"1", "12", "123"}), {"1 ", "12 ", "123"}) +%!assert (pad({"1", "12", "123"}, 'left'), {" 1", " 12", "123"}) +%!assert (pad({"1.12", "10.42", "0.18"}, 6, 'left', '0'), {"001.12", "010.42", "000.18"}) +%!assert (pad({"1.12"; "10.42"; "0.18"}, 6, 'left', '0'), {"001.12"; "010.42"; "000.18"}) + +## error +%!error pad ([1, 2, 3]) +%!error pad ({"1.12", "10.42", "0.18"}, 'middle') +%!error pad ({"1.12", "10.42", "0.18"}, 10, 'left', '*#') +%!error pad ({"1.12", "10.42", "0.18"}, 10, 'left', {'a'}) +%!error pad ({"1.12", "10.42", "0.18"}, -2)