Skip to content

Commit cbe4f34

Browse files
committed
Split formatting support off of StringLiterals for Str.jl usage, make dynamic
1 parent 1438cf7 commit cbe4f34

10 files changed

Lines changed: 581 additions & 1 deletion

File tree

.codecov.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
comment: false

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.jl.cov
2+
*.jl.*.cov
3+
*.jl.mem

.travis.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Documentation: http://docs.travis-ci.com/user/languages/julia/
2+
language: julia
3+
os:
4+
- linux
5+
- osx
6+
julia:
7+
- 0.6
8+
- nightly
9+
notifications:
10+
email: false
11+
git:
12+
depth: 99999999
13+
14+
## uncomment the following lines to allow failures on nightly julia
15+
## (tests will run but not make your overall status red)
16+
#matrix:
17+
# allow_failures:
18+
# - julia: nightly
19+
20+
# uncomment the following lines to override the default test script
21+
script:
22+
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
23+
- julia -e 'Pkg.clone("https://github.com/JuliaString/Strs.jl.git") ; Pkg.clone("https://github.com/JuliaString/Format.jl.git"); Pkg.clone("https://github.com/JuliaString/StrLiterals.jl.git"); Pkg.clone(pwd()); Pkg.test("StrFormat"); coverage=true)'
24+
after_success:
25+
# push coverage results to Coveralls
26+
- julia -e 'cd(Pkg.dir("StrFormat")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
27+
# push coverage results to Codecov
28+
- julia -e 'cd(Pkg.dir("StrFormat")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())'

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2018 JuliaString
3+
Copyright (c) 2018: Gandalf Software, Inc. (Scott Paul Jones)
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

LICENSE.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
The StrFormat.jl package is licensed under the MIT "Expat" License:
2+
3+
> Copyright (c) 2018: Gandalf Software, Inc. (Scott Paul Jones)
4+
>
5+
> Permission is hereby granted, free of charge, to any person obtaining a copy
6+
> of this software and associated documentation files (the "Software"), to deal
7+
> in the Software without restriction, including without limitation the rights
8+
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
> copies of the Software, and to permit persons to whom the Software is
10+
> furnished to do so, subject to the following conditions:
11+
>
12+
> The above copyright notice and this permission notice shall be included in all
13+
> copies or substantial portions of the Software.
14+
>
15+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
> SOFTWARE.
22+
>

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# StrLiterals
2+
3+
[![Build Status](https://travis-ci.org/JuliaString/StrFormat.jl.svg?branch=master)](https://travis-ci.org/JuliaString/StrFormat.jl)
4+
5+
[![Coverage Status](https://coveralls.io/repos/github/JuliaString/StrFormat.jl/badge.svg?branch=master)](https://coveralls.io/github/JuliaString/StrFormat.jl?branch=master)
6+
7+
[![codecov.io](http://codecov.io/github/JuliaString/StrFormat.jl/coverage.svg?branch=master)](http://codecov.io/github/JuliaString/StrFormat.jl?branch=master)
8+
9+
StrFormat extends the string literals provided by the [StrLiterals](https://github.com/JuliaString/StrLiterals.jl) package.
10+
It uses an extensively modified fork of the [Formatting](https://github.com/JuliaIO/Formatting.jl) package to provide formatting capability, as well as Tom Breloff's [PR #10](https://github.com/JuliaIO/Formatting.jl/pull/10), which provides the capability of using settable printing defaults based on the types of the argument (see [Format](https://github.com/JuliaString/Format.jl).
11+
12+
The following extra format sequences (see [StrLiterals](https://github.com/JuliaString/StrLiterals.jl) for the full specification) are added:
13+
14+
* `\%<ccc><formatcode>(arguments)` is interpolated as a call to `cfmt("<cccc><formatcode>",arguments)`, where `<ccc><formatcode>` is a C-style format string.
15+
16+
* `\%(arguments)` is interpolated as a call to `fmt(arguments)`.
17+
This is especially useful when defaults have been set for the type of the first argument.
18+
19+
* `fmt_default!{T}(::Type{T}, syms::Symbol...; kwargs...)` sets the defaults for a particular type.
20+
* `fmt_default!(syms::Symbol...; kwargs...)` sets the defaults for all types.
21+
22+
Symbols that can currently be used are: `:ljust` or `:left`, `:rjust` or `:right`, `:commas`, `:zpad` or `:zeropad`, and `:ipre` or `:prefix`.
23+
* `reset!{T}(::Type{T})` resets the defaults for a particular type.
24+
* `defaultSpec(x)` will return the defaults for the type of x, and
25+
* `defaultSpec{T}(::Type{T})` will return the defaults for the given type.
26+
27+
There is currently support for Python style formatting, although that is a work-in-progress,
28+
and I am intending to improve the syntax to make it as close as possible to Python's 3.6 format strings.
29+
Currently, the syntax is `\{<formatstring>}(expression)`, however I plan on changing it shortly to `\{expression}` (equivalent to `pyfmt("", expression)`, and `\{expression;formatstring}` (equivalent to `pyfmt("formatstring", expression)`.

REQUIRE

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
julia 0.6
2+
Format
3+
Strs
4+
StrLiterals

appveyor.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
environment:
2+
matrix:
3+
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
4+
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
5+
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
6+
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
7+
8+
## uncomment the following lines to allow failures on nightly julia
9+
## (tests will run but not make your overall status red)
10+
#matrix:
11+
# allow_failures:
12+
# - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
13+
# - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
14+
15+
branches:
16+
only:
17+
- master
18+
- /release-.*/
19+
20+
notifications:
21+
- provider: Email
22+
on_build_success: false
23+
on_build_failure: false
24+
on_build_status_changed: false
25+
26+
install:
27+
- ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12"
28+
# If there's a newer build queued for the same PR, cancel this one
29+
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
30+
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
31+
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
32+
throw "There are newer queued builds for this pull request, failing early." }
33+
# Download most recent Julia Windows binary
34+
- ps: (new-object net.webclient).DownloadFile(
35+
$env:JULIA_URL,
36+
"C:\projects\julia-binary.exe")
37+
# Run installer silently, output to C:\projects\julia
38+
- C:\projects\julia-binary.exe /S /D=C:\projects\julia
39+
40+
build_script:
41+
# Need to convert from shallow to complete for Pkg.clone to work
42+
- IF EXIST .git\shallow (git fetch --unshallow)
43+
- C:\projects\julia\bin\julia -e "versioninfo();
44+
Pkg.clone(pwd(), \"StrFormat\")
45+
46+
test_script:
47+
- C:\projects\julia\bin\julia -e "Pkg.test(\"StrFormat\")"

src/StrFormat.jl

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
__precompile__(true)
2+
""""
3+
Add C, Python and type-based formatting to Str string literals
4+
5+
Copyright 2016-2018 Gandalf Software, Inc., Scott P. Jones
6+
Licensed under MIT License, see LICENSE.md
7+
"""
8+
module StrFormat
9+
10+
using Format, StrLiterals
11+
12+
parse_error(s) = throw(StrLiterals._ParseError(s))
13+
14+
_check_exp(ex) =
15+
isa(ex, Expr) && (ex.head === :continue) && parse_error("Incomplete expression")
16+
17+
function _parse_format(str, pos, fun)
18+
ex, j = StrLiterals._parse(str, pos; greedy=false)
19+
_check_exp(ex)
20+
ex, k = StrLiterals._parse(string("a", str[pos:j-1]), 1, greedy=true)
21+
_check_exp(ex)
22+
isa(ex, Symbol) && (println(string("a", str[pos:j-1])) ; dump(ex))
23+
ex.args[1] = fun
24+
ex, j
25+
end
26+
27+
function _parse_fmt(sx::Vector{Any}, s::AbstractString, unescape::Function,
28+
i::Integer, j::Integer, k::Integer)
29+
# Move past \\, k should point to '%'
30+
c, k = next(s, k)
31+
done(s, k) && parse_error("Incomplete % expression")
32+
# Handle interpolation
33+
isempty(s[i:j-1]) || push!(sx, unescape(s[i:j-1]))
34+
if s[k] == '('
35+
# Need to find end to parse to
36+
ex, j = _parse_format(s, k, Format.fmt)
37+
else
38+
# Move past %, c should point to letter
39+
beg = k
40+
while true
41+
c, k = next(s, k)
42+
done(s, k) && parse_error("Incomplete % expression")
43+
s[k] == '(' && break
44+
end
45+
ex, j = _parse_format(s, k, Format.cfmt)
46+
insert!(ex.args, 2, s[beg-1:k-1])
47+
end
48+
push!(sx, esc(ex))
49+
j
50+
end
51+
52+
function _parse_pyfmt(sx::Vector{Any}, s::AbstractString, unescape::Function,
53+
i::Integer, j::Integer, k::Integer)
54+
# Move past \\, k should point to '{'
55+
c, k = next(s, k)
56+
done(s, k) && parse_error("Incomplete {...} Python format expression")
57+
# Handle interpolation
58+
isempty(s[i:j-1]) || push!(sx, unescape(s[i:j-1]))
59+
beg = k # start location
60+
c, k = next(s, k)
61+
while c != '}'
62+
done(s, k) && parse_error(string("\\{ missing closing } in ", c))
63+
c, k = next(s, k)
64+
end
65+
done(s, k) && parse_error("Missing (expr) in Python format expression")
66+
c, k = next(s, k)
67+
c == '(' || parse_error(string("Missing (expr) in Python format expression: ", c))
68+
# Need to find end to parse to
69+
ex, j = _parse_format(s, k-1, Format.pyfmt)
70+
insert!(ex.args, 2, s[beg:k-3])
71+
push!(sx, esc(ex))
72+
j
73+
end
74+
75+
function __init__()
76+
StrLiterals.interpolate['%'] = _parse_fmt
77+
StrLiterals.interpolate['{'] = _parse_pyfmt
78+
end
79+
80+
end # module StrFormat

0 commit comments

Comments
 (0)