String#shorten & Array#punctuate #127

wants to merge 18 commits into

4 participants


String#truncate didn't provide the functionality I needed, as such String#shorten has been added. The use case for the method is primarily URLs, where the beginning and end are more important than the middle. As such shorten defaults to truncating the string in the middle and including the length of the splitter in the length required.

-> ""

Performs similar to String#truncate in that custom splitters can be included, as well as allowing the resultant string's length to omit the length of the splitter. The splitter can also be positioned at the left, right or middle of the string.

Array#punctuate builds a grammatical list from the array, taking a fn handler to deal with deep arrays. I've been working with long calling patterns for train services and this addition to Sugar help me deal with the headache. The trailing only on single length lists can be omitted too.

['Apples', 'Grapes', 'Bears'].punctuate()   -> 'Apples, Grapes and Bears';
[{type:'Apple', n:2}, {type:'Grape', n:1}, {type:'Bears', n:10}].punctuate(function(item) {
    var name = (item.n == 1) ? item.type.singularize() : item.type.pluralize();
    return item.n.toString() + " " + name;
})                              -> '2 Apples, 1 Grape and 10 Bears';

Extensive unit testing added for both methods. Tested in Node.js v0.6.14 and Safari 5.1.5 (Snow Leopard). Unable to use unit_test/../sugar.html in Chrome 18.x as XMLHttpRequest won't load local files because of Access-Control-Allow-Origin. Unsure if this is a know issue. The actual unit tests were ran independently and succeeded in Chrome.


I really like this. Punctuate is immune to localization though which is no good :(.


A simple parameter could be added to be used as the conjunction, that would suffice for the short term. However, I don't how to properly deal with it, from what I can tell Sugar's only concept of localization is with Dates. It might be an idea to include the conjunctions in there as it's already separated into locales. I'm not too sure, seems a lot to ask of the developer to include dates just to use one method that barely uses any of the functionality of it. I'll get thinking.


Wow, I really appreciate the work, and you've definitely been more thorough than most people adding merge requests, by adding the unit tests and all that... I want to give you the benefit of the doubt here but be aware that Sugar has now had some time to develop and I'm trying to be very strict with what makes it in (in fact by this point I'm more hoping to trim some of the fat out instead).

To that effect, Array#punctuate doesn't seem like a good candidate for Sugar right now... As @inossidabile says it's subject to localization, which is only applicable in the Date class and that's not likely to change for now. It's also quite specific and I'm not sure if I see a generalized need for it.

String#shorten is a little better, but the naming isn't very clear, and as it is it has quite complicated arguments, which is something I'd like to avoid. Also the behavior overlaps String#truncate.. the 2 should be brought together if the need is actually here.

@inossidabile What is it you like and which were you talking about here?

Lastly, yes, Access-Control-Allow-Origin prevents tests from being run as files, so I am always running them off a server.


I like the idea of both but I doubt punctuate should be added without localization. And I agree that shorten should be renamed to truncate.


I understand about wanting to trim Sugar down, no worries.

Yeah, I wasn't too optimistic about shorten's name. truncate is a much better verb, but rather than altering the functionality of truncate I just added a new method so we could differentiate between them in this discussion. The main difference, as I mentioned in at the beginning, is that shorten will return a string to the length you give it with the ellipsis being counted in the length. Judging from #128 this was the expected functionality for gaiottino too. I have no ties to shortens name, if it became a part of truncate that would be perfectly fine. At that point however, truncate would be very configurable, so it might be a good idea to drop the countSplitter parameter.

As for punctuate I'm going to try and fight my corner for a little longer! I took it from specialised functionality that worked with lists, and generalised it specifically with Sugar in mind. Ideas for generalised implementations:

  • People who liked this: James, Tim and David.
  • Contributers: Sarah, Thomas and Natalie.
  • Most recent releases: 1.2.4, 1.2.3 and 1.2.2.

If it doesn't make the cut there's no hard feelings, just happy to give back to an amazing library.


@inossidabile do you have such a need for "punctuate"? I can't really picture it.

@nadinengland When Sugar does get trimmed I want to keep the code around as methods can still be extended in externally. This is in fact part of what makes Sugar cool so having in the repository other useful code in one place that can be easily added to your project would be a big plus.

That said I still have an issue with the naming though... punctuate makes me want to stab something. It's more like humanJoin or something... no other possibilities?


@nadinengland also I think you're pointed out some good counter-intuitive parts with truncate, so I want to start there.


@andrewplummer cool, well keep me informed on truncate's progress.

I spent ages trying to get a good name for punctuate, some of the contenders I came up with were ['listify', 'commaize', 'sentencize'].punctuate(). They are all bad. I stuck with punctuate as it was an actual word. I like humanJoin, I feel it very accurately described what is doing. As for other name possibilities, it creates a list so humanList, or prettyList. Not sure.


I can't say I can't live without it. But I guess it could help creating more humanized interfaces. Which is important. punctuate('и') is something I would use to replace .join(', ').


I have altered the signature of Array#punctuate removing the useOnly flag, it no longer prints only with a single element array. It would have been to much headache for localization to have that there, and it's keeping it simple. After reading @inossidabile's reply I realised that localization is a much more important part of punctuate than the handler is, as such I swapped them around in the signature, reflecting its importance.

New unit tests have been added as well as existing ones modifying to copy with the signature swap.


Keep in mind that not all languages use even the same punctuation. Also for me the correct way is one, two, and three, although I actually just recently fought about this with UK/Australians, who apparently do it differently.

Some languages like Japanese have no spaces either, or occasionally use non-standard punctuation.

I also wonder how RTL languages would work.

Welcome to localizations! :D


Ah yes, the Oxford comma, I had discussions about this before. My use case came to the decision that we would not be using it. Originally it was a optional flag but I removed it as it cluttered the function's signature.

As for RTL Languages, I took a Hebrew string א ב ג ד ה ז ח ט and called punctuate on it in an array form.

"א ב ג ד ה ז ח ט".split(' ').punctuate('ו');
"א, ב, ג, ד, ה, ז, ח ו ט"

At first this appeared wrong as the commas are after the whitespace, but then I ran it thought Google Translate and it looks correct when the formatting is RTL.


@andrewplummer :

That said I still have an issue with the naming though... punctuate makes me want to stab something. It's more like humanJoin or something... no other possibilities?

In Rails this operation is called to_sentence, perhaps Array#toSentence?


Ahhh... that's starting to sound a lot better.


How do you feel about methods names with a 'to' prefix in them in JS? As you can tell from my other naming attempts, I was trying to come up with verbs that fit into Sugars' loose naming convention. I'd be happy with Array#toSentence, even if it does give me Java and C# like flashbacks, it's very descriptive.


Yep, toSentence works for me!


Well Array#punctuate is now Array#toSentence and it has had a refactor to be more readable and support the Oxford comma should that be desired in the future.

twoWordConjunction = ' ' + conjunction + ' ';
lastWordConjunction = ' ' + conjunction + ' ';

The refactor is very much inspired by Ruby's to_sentence, cheers @alassek.

@andrewplummer as for Array#shortern, is there a chance that its functionality will be merged into Sugar should I make it part of Array#truncate?


@nadinengland Can you give me a bit? I started working on merging the pull request but got a bit busy... It's definitely on the way though but I'm still trying to think about how to deal with the large number of arguments. If it does come in, it will be as truncate.


Certainly, if you have already begun I'll leave it with you.


So bottom line is that the functionality of String#shorten is going to find its way into String#truncate after refactoring and will go out next release.

Array#punctuate will not be used in the main Sugar core, but I've added it as an extra as Array#toSentence that can be opted in. However I think the arguments really need a cleanup.... the handler function isn't necessary as we already have Array#map, and I don't think only is very useful. A single param that is the conjunction string itself should be all that is required.

@nadinengland nadinengland Array#toSentence refactored to use simple signature
No longer takes a [handler], use Array#map for this.

I came to the same conclusion on only too, it was taken out in a previous commit. Excellent point about handler, I only recently (this weekend) understood the purpose of Array#map. Commit 5d98aac has the much simpler arguments signature.

When Array#toSentence becomes an opt-in method, how will that work? Are opt-in methods already part of Sugar? I know you can download a custom build of Sugar, ie dates and inflections, but I can't see any docs on opt-in methods.


No basically this is just code supplied in the repo but not included in the standard build.


OK, this is now available in the repo in v1.2.5. Also the functionality of shorten is now a part of truncate.


Awesome! EDIT: the punctuate method still exists in sugar-edge.development.js, just FYI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment