diff options
Diffstat (limited to 'clap.zig')
| -rw-r--r-- | clap.zig | 76 |
1 files changed, 60 insertions, 16 deletions
| @@ -13,6 +13,7 @@ const testing = std.testing; | |||
| 13 | pub const args = @import("clap/args.zig"); | 13 | pub const args = @import("clap/args.zig"); |
| 14 | pub const parsers = @import("clap/parsers.zig"); | 14 | pub const parsers = @import("clap/parsers.zig"); |
| 15 | pub const streaming = @import("clap/streaming.zig"); | 15 | pub const streaming = @import("clap/streaming.zig"); |
| 16 | pub const ccw = @import("clap/codepoint_counting_writer.zig"); | ||
| 16 | 17 | ||
| 17 | test "clap" { | 18 | test "clap" { |
| 18 | testing.refAllDecls(@This()); | 19 | testing.refAllDecls(@This()); |
| @@ -1153,10 +1154,10 @@ pub fn help( | |||
| 1153 | const max_spacing = blk: { | 1154 | const max_spacing = blk: { |
| 1154 | var res: usize = 0; | 1155 | var res: usize = 0; |
| 1155 | for (params) |param| { | 1156 | for (params) |param| { |
| 1156 | var cs = io.countingWriter(io.null_writer); | 1157 | var cs = ccw.codepointCountingWriter(io.null_writer); |
| 1157 | try printParam(cs.writer(), Id, param); | 1158 | try printParam(cs.writer(), Id, param); |
| 1158 | if (res < cs.bytes_written) | 1159 | if (res < cs.codepoints_written) |
| 1159 | res = @intCast(cs.bytes_written); | 1160 | res = @intCast(cs.codepoints_written); |
| 1160 | } | 1161 | } |
| 1161 | 1162 | ||
| 1162 | break :blk res; | 1163 | break :blk res; |
| @@ -1166,22 +1167,22 @@ pub fn help( | |||
| 1166 | opt.description_indent + | 1167 | opt.description_indent + |
| 1167 | max_spacing * @intFromBool(!opt.description_on_new_line); | 1168 | max_spacing * @intFromBool(!opt.description_on_new_line); |
| 1168 | 1169 | ||
| 1169 | var first_paramter: bool = true; | 1170 | var first_parameter: bool = true; |
| 1170 | for (params) |param| { | 1171 | for (params) |param| { |
| 1171 | if (!first_paramter) | 1172 | if (!first_parameter) |
| 1172 | try writer.writeByteNTimes('\n', opt.spacing_between_parameters); | 1173 | try writer.writeByteNTimes('\n', opt.spacing_between_parameters); |
| 1173 | 1174 | ||
| 1174 | first_paramter = false; | 1175 | first_parameter = false; |
| 1175 | try writer.writeByteNTimes(' ', opt.indent); | 1176 | try writer.writeByteNTimes(' ', opt.indent); |
| 1176 | 1177 | ||
| 1177 | var cw = io.countingWriter(writer); | 1178 | var cw = ccw.codepointCountingWriter(writer); |
| 1178 | try printParam(cw.writer(), Id, param); | 1179 | try printParam(cw.writer(), Id, param); |
| 1179 | 1180 | ||
| 1180 | const Writer = DescriptionWriter(@TypeOf(writer)); | 1181 | const Writer = DescriptionWriter(@TypeOf(writer)); |
| 1181 | var description_writer = Writer{ | 1182 | var description_writer = Writer{ |
| 1182 | .underlying_writer = writer, | 1183 | .underlying_writer = writer, |
| 1183 | .indentation = description_indentation, | 1184 | .indentation = description_indentation, |
| 1184 | .printed_chars = @intCast(cw.bytes_written), | 1185 | .printed_chars = @intCast(cw.codepoints_written), |
| 1185 | .max_width = opt.max_width, | 1186 | .max_width = opt.max_width, |
| 1186 | }; | 1187 | }; |
| 1187 | 1188 | ||
| @@ -1260,8 +1261,7 @@ pub fn help( | |||
| 1260 | } else { | 1261 | } else { |
| 1261 | // For none markdown like format, we just respect the newlines in the input | 1262 | // For none markdown like format, we just respect the newlines in the input |
| 1262 | // string and output them as is. | 1263 | // string and output them as is. |
| 1263 | var i: usize = 0; | 1264 | for (0..non_emitted_newlines) |_| |
| 1264 | while (i < non_emitted_newlines) : (i += 1) | ||
| 1265 | try description_writer.newline(); | 1265 | try description_writer.newline(); |
| 1266 | } | 1266 | } |
| 1267 | 1267 | ||
| @@ -1292,7 +1292,7 @@ fn DescriptionWriter(comptime UnderlyingWriter: type) type { | |||
| 1292 | debug.assert(word.len != 0); | 1292 | debug.assert(word.len != 0); |
| 1293 | 1293 | ||
| 1294 | var first_word = writer.printed_chars <= writer.indentation; | 1294 | var first_word = writer.printed_chars <= writer.indentation; |
| 1295 | const chars_to_write = word.len + @intFromBool(!first_word); | 1295 | const chars_to_write = try std.unicode.utf8CountCodepoints(word) + @intFromBool(!first_word); |
| 1296 | if (chars_to_write + writer.printed_chars > writer.max_width) { | 1296 | if (chars_to_write + writer.printed_chars > writer.max_width) { |
| 1297 | // If the word does not fit on this line, then we insert a new line and print | 1297 | // If the word does not fit on this line, then we insert a new line and print |
| 1298 | // it on that line. The only exception to this is if this was the first word. | 1298 | // it on that line. The only exception to this is if this was the first word. |
| @@ -1744,6 +1744,50 @@ test "clap.help" { | |||
| 1744 | \\-d, --dd <V3>... Both repeated option. | 1744 | \\-d, --dd <V3>... Both repeated option. |
| 1745 | \\ | 1745 | \\ |
| 1746 | ); | 1746 | ); |
| 1747 | |||
| 1748 | // Test with multibyte characters. | ||
| 1749 | try testHelp(.{ | ||
| 1750 | .indent = 0, | ||
| 1751 | .max_width = 46, | ||
| 1752 | .description_on_new_line = false, | ||
| 1753 | .description_indent = 4, | ||
| 1754 | .spacing_between_parameters = 2, | ||
| 1755 | }, | ||
| 1756 | \\-a Shört flåg. | ||
| 1757 | \\ | ||
| 1758 | \\ | ||
| 1759 | \\-b <V1> Shört öptiön. | ||
| 1760 | \\ | ||
| 1761 | \\ | ||
| 1762 | \\ --aa Löng fläg. | ||
| 1763 | \\ | ||
| 1764 | \\ | ||
| 1765 | \\ --bb <V2> Löng öptiön. | ||
| 1766 | \\ | ||
| 1767 | \\ | ||
| 1768 | \\-c, --cc Bóth fläg. | ||
| 1769 | \\ | ||
| 1770 | \\ | ||
| 1771 | \\ --complicate Fläg wíth ä cömplǐcätéd | ||
| 1772 | \\ änd vërý löng dèscrıptıön | ||
| 1773 | \\ thät späns mültíplë | ||
| 1774 | \\ lınēs. | ||
| 1775 | \\ | ||
| 1776 | \\ Pärägräph number 2: | ||
| 1777 | \\ * Bullet pöint | ||
| 1778 | \\ * Bullet pöint | ||
| 1779 | \\ | ||
| 1780 | \\ Exämple: | ||
| 1781 | \\ sömething sömething | ||
| 1782 | \\ sömething | ||
| 1783 | \\ | ||
| 1784 | \\ | ||
| 1785 | \\-d, --dd <V3> Böth öptiön. | ||
| 1786 | \\ | ||
| 1787 | \\ | ||
| 1788 | \\-d, --dd <V3>... Böth repeäted öptiön. | ||
| 1789 | \\ | ||
| 1790 | ); | ||
| 1747 | } | 1791 | } |
| 1748 | 1792 | ||
| 1749 | /// Will print a usage message in the following format: | 1793 | /// Will print a usage message in the following format: |
| @@ -1752,18 +1796,18 @@ test "clap.help" { | |||
| 1752 | /// First all none value taking parameters, which have a short name are printed, then non | 1796 | /// First all none value taking parameters, which have a short name are printed, then non |
| 1753 | /// positional parameters and finally the positional. | 1797 | /// positional parameters and finally the positional. |
| 1754 | pub fn usage(stream: anytype, comptime Id: type, params: []const Param(Id)) !void { | 1798 | pub fn usage(stream: anytype, comptime Id: type, params: []const Param(Id)) !void { |
| 1755 | var cos = io.countingWriter(stream); | 1799 | var cos = ccw.codepointCountingWriter(stream); |
| 1756 | const cs = cos.writer(); | 1800 | const cs = cos.writer(); |
| 1757 | for (params) |param| { | 1801 | for (params) |param| { |
| 1758 | const name = param.names.short orelse continue; | 1802 | const name = param.names.short orelse continue; |
| 1759 | if (param.takes_value != .none) | 1803 | if (param.takes_value != .none) |
| 1760 | continue; | 1804 | continue; |
| 1761 | 1805 | ||
| 1762 | if (cos.bytes_written == 0) | 1806 | if (cos.codepoints_written == 0) |
| 1763 | try stream.writeAll("[-"); | 1807 | try stream.writeAll("[-"); |
| 1764 | try cs.writeByte(name); | 1808 | try cs.writeByte(name); |
| 1765 | } | 1809 | } |
| 1766 | if (cos.bytes_written != 0) | 1810 | if (cos.codepoints_written != 0) |
| 1767 | try cs.writeAll("]"); | 1811 | try cs.writeAll("]"); |
| 1768 | 1812 | ||
| 1769 | var has_positionals: bool = false; | 1813 | var has_positionals: bool = false; |
| @@ -1782,7 +1826,7 @@ pub fn usage(stream: anytype, comptime Id: type, params: []const Param(Id)) !voi | |||
| 1782 | continue; | 1826 | continue; |
| 1783 | }; | 1827 | }; |
| 1784 | 1828 | ||
| 1785 | if (cos.bytes_written != 0) | 1829 | if (cos.codepoints_written != 0) |
| 1786 | try cs.writeAll(" "); | 1830 | try cs.writeAll(" "); |
| 1787 | 1831 | ||
| 1788 | try cs.writeAll("["); | 1832 | try cs.writeAll("["); |
| @@ -1806,7 +1850,7 @@ pub fn usage(stream: anytype, comptime Id: type, params: []const Param(Id)) !voi | |||
| 1806 | if (param.names.short != null or param.names.long != null) | 1850 | if (param.names.short != null or param.names.long != null) |
| 1807 | continue; | 1851 | continue; |
| 1808 | 1852 | ||
| 1809 | if (cos.bytes_written != 0) | 1853 | if (cos.codepoints_written != 0) |
| 1810 | try cs.writeAll(" "); | 1854 | try cs.writeAll(" "); |
| 1811 | 1855 | ||
| 1812 | try cs.writeAll("<"); | 1856 | try cs.writeAll("<"); |