Permalink
Browse files

Added JavaScript tests and worked on README

  • Loading branch information...
1 parent 9cd79f3 commit 5d2a3ccf809be337e765e879ed9d59a29eb03a6d Kevin Malakoff committed Jul 30, 2012
Showing with 2,158 additions and 163 deletions.
  1. +274 −0 README.md
  2. +138 −21 SubjectiveScript.m.xcodeproj/project.pbxproj
  3. +3 −3 SubjectiveScript/Helpers/SS+System.m
  4. +1 −1 SubjectiveScript/JavaScript/NSArray+JavaScript.h
  5. +16 −8 SubjectiveScript/JavaScript/NSArray+JavaScript.m
  6. +6 −0 SubjectiveScript/JavaScript/NSDate+JavaScript.h
  7. +55 −1 SubjectiveScript/JavaScript/NSDate+JavaScript.m
  8. +1 −1 SubjectiveScript/JavaScript/NSDictionary+JavaScript.m
  9. +2 −1 SubjectiveScript/JavaScript/NSMutableArray+JavaScript.h
  10. +11 −1 SubjectiveScript/JavaScript/NSMutableArray+JavaScript.m
  11. +0 −1 SubjectiveScript/JavaScript/NSNumber+JavaScript.h
  12. +2 −6 SubjectiveScript/JavaScript/NSNumber+JavaScript.m
  13. +1 −2 SubjectiveScript/JavaScript/NSObject+JavaScript.h
  14. +3 −6 SubjectiveScript/JavaScript/NSObject+JavaScript.m
  15. +0 −1 SubjectiveScript/JavaScript/NSString+JavaScript.h
  16. +2 −4 SubjectiveScript/JavaScript/NSString+JavaScript.m
  17. +4 −3 SubjectiveScript/JavaScript/SS+JavaScript.h
  18. +63 −5 SubjectiveScript/JavaScript/SS+JavaScript.m
  19. +0 −34 SubjectiveScript/Ruby/NSString+Ruby.h
  20. +0 −34 SubjectiveScript/Ruby/NSString+Ruby.m
  21. +1 −4 SubjectiveScript/SubjectiveScript.h
  22. +3 −3 SubjectiveScript/Types/NSArray+SS.h
  23. +13 −6 SubjectiveScript/Types/NSArray+SS.m
  24. +1 −0 SubjectiveScript/Types/NSDate+SS.h
  25. +1 −1 SubjectiveScript/Types/NSNumber+SS.h
  26. +1 −1 SubjectiveScript/Types/NSNumber+SS.m
  27. +1 −1 SubjectiveScript/Types/NSObject+SS.h
  28. +2 −2 SubjectiveScript/Types/NSObject+SS.m
  29. +4 −1 SubjectiveScript/Types/NSString+SS.h
  30. +20 −4 SubjectiveScript/Types/NSString+SS.m
  31. +3 −2 SubjectiveScript/Types/SSTypes.h
  32. +79 −0 SubjectiveScript/Vendor/ISO8601Parser/ISO8601DateFormatter.h
  33. +876 −0 SubjectiveScript/Vendor/ISO8601Parser/ISO8601DateFormatter.m
  34. +13 −0 SubjectiveScriptTests/JavaScript/Array+JavaScriptTests.h
  35. +82 −0 SubjectiveScriptTests/JavaScript/Array+JavaScriptTests.m
  36. +13 −0 SubjectiveScriptTests/JavaScript/Date+JavaScriptTests.h
  37. +20 −0 SubjectiveScriptTests/JavaScript/Date+JavaScriptTests.m
  38. +13 −0 SubjectiveScriptTests/JavaScript/Functions+JavaScriptTests.h
  39. +27 −0 SubjectiveScriptTests/JavaScript/Functions+JavaScriptTests.m
  40. +13 −0 SubjectiveScriptTests/JavaScript/NSObject+JavaScriptTests.h
  41. +44 −0 SubjectiveScriptTests/JavaScript/NSObject+JavaScriptTests.m
  42. +13 −0 SubjectiveScriptTests/JavaScript/Number+JavaScriptTests.h
  43. +15 −0 SubjectiveScriptTests/JavaScript/Number+JavaScriptTests.m
  44. +13 −0 SubjectiveScriptTests/JavaScript/Object+JavaScriptTests.h
  45. +30 −0 SubjectiveScriptTests/JavaScript/Object+JavaScriptTests.m
  46. +13 −0 SubjectiveScriptTests/JavaScript/SS+JavaScriptTests.h
  47. +58 −0 SubjectiveScriptTests/JavaScript/SS+JavaScriptTests.m
  48. +13 −0 SubjectiveScriptTests/JavaScript/String+JavaScriptTests.h
  49. +34 −0 SubjectiveScriptTests/JavaScript/String+JavaScriptTests.m
  50. +1 −1 SubjectiveScriptTests/SubjectiveScriptTests.m
  51. +13 −0 SubjectiveScriptTests/Types/Array+SSTests.h
  52. +13 −0 SubjectiveScriptTests/Types/Array+SSTests.m
  53. +13 −0 SubjectiveScriptTests/Types/Date+SSTests.h
  54. +13 −0 SubjectiveScriptTests/Types/Date+SSTests.m
  55. +13 −0 SubjectiveScriptTests/Types/NSObject+SSTests.h
  56. +13 −0 SubjectiveScriptTests/Types/NSObject+SSTests.m
  57. +13 −0 SubjectiveScriptTests/Types/Number+SSTests.h
  58. +13 −0 SubjectiveScriptTests/Types/Number+SSTests.m
  59. +13 −0 SubjectiveScriptTests/Types/Object+SSTests.h
  60. +13 −0 SubjectiveScriptTests/Types/Object+SSTests.m
  61. +13 −0 SubjectiveScriptTests/Types/String+SSTests.h
  62. +13 −0 SubjectiveScriptTests/Types/String+SSTests.m
  63. +0 −4 SubjectiveScriptTests/Vendor/QUnitTestCase.m/QUnit.h
View
274 README.md
@@ -0,0 +1,274 @@
+[![Build Status](https:secure.travis-ci.org/kmalakoff/SubjectiveScript.m.png)](http:travis-ci.org/kmalakoff/SubjectiveScript.m)
+
+````
+SubjectiveScript.m
+````
+Subjective-Script makes Objective-C more scripty!
+
+The Idea
+========
+
+My language of preference is CoffeeScript and whenever I develop in Objective-C, I find myself often having to look up [NSSomething reallyLongFunctionName:YES withAVerboseParameterName:YES and:[NSSomethingElse whichAddsMoreBrackets]] and it isn't very enjoyable or speedy!
+
+While I was porting a test for [_.m](https://github.com/kmalakoff/_.m) from the original [Underscore.js](http://underscorejs.org/) that was easy to read:
+
+```JavaScript
+var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}];
+people = _.sortBy(people, function(person){ return person.age; });
+equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age');
+```
+
+It looked like this in Objective-C:
+
+```
+NSArray *people = [NSArray arrayWithObjects:
+ [NSDictionary dictionaryWithObjectsAndKeys: @"moe", @"name", [NSNumber numberWithInt:30], @"age", nil],
+ [NSDictionary dictionaryWithObjectsAndKeys: @"curly", @"name", [NSNumber numberWithInt:50], @"age", nil],
+ nil];
+
+STAssertEqualObjects([_.pluck(people, @"name") componentsJoinedByString:@", "],
+ @"moe, curly",
+ @"stooges sorted by age");
+```
+
+The keys were in the wrong order, there was too much typing involved, and it became unreadable. So I wrote [Subjective-Script](https://github.com/kmalakoff/SubjectiveScript.m) and ported [QUnit.m](https://github.com/kmalakoff/QUnit.m) to end up with this:
+
+```
+A* people = AO(OKV({@"name", @"curly"}, {@"age", N.I(50)}), OKV({@"name", @"moe"}, {@"age", N.I(30)}));
+people = _.sortBy(people, ^(O* person){ return person.get(@"age"); });
+equal(_.pluck(people, @"name").join(@", "), @"moe, curly", @"stooges sorted by age");
+```
+
+Much better! And best of all, I can reuse my knowledge of JavaScript for function names so I can stop looking things up and get stuff done!
+
+The Syntax
+==========
+
+Types
+-----
+While JavaScript allows flexibility in variable types, Objective-C requires explicit variable types. To try to keep it brief, I tried to condense types down to the shortest name possible:
+
+```
+typedef BOOL B;
+typedef NSInteger I;
+typedef NSUInteger UI;
+typedef float F;
+typedef double D;
+typedef id KV[2]; // key-value pair
+
+#define NSO NSObject
+#define A NSMutableArray
+#define NSA NSArray
+#define O NSMutableDictionary
+#define NSD NSDictionary
+#define S NSMutableString
+#define NSS NSString
+#define Date NSDate
+#define N NSNumber
+#define E NSException
+```
+
+and I tried to shorten NSNumbers, too, using the above abbreviations (B, I, UI, F, D):
+
+```
+N* value = N.B(true);
+equal(value.B, true, @"YES it is!")
+```
+
+Using Aggregate Types
+-----
+I tried many different ways, but this seemed to be easy-to-read and brief (with key-value pair matching checked by the compiler):
+
+```
+A* arrayOfInts = AI(1, 2, 3);
+A* arrayOfObjects = AO(N.I(1), N.F(2.0), @"hello", nil, O.new);
+I intValue = arrayOfInts.getAt(0).I; // or: intValue = arrayOfInts.get(@"1").I;
+arrayOfInts.setAt(0, N.I(intValue+1)); // or: arrayOfInts.set(@"1", N.I(intValue+1));
+
+O* obj = OKV({@"int", N.I(1)}, {@"float", N.F(2.0)}, {@"string", @"hello"}, {@"nil", nil}, {@"dictionary", O.new});
+intValue = obj.get(@"int").I;
+obj.set(@"int", N.I(intValue+1));
+```
+
+would be equivalent to the following Javascript:
+
+```
+var arrayOfInts = [1, 2, 3];
+var arrayOfObjects = [1, 2.0, 'hello', null, {}];
+var intValue = arrayOfInts[0];
+arrayOfInts[0] = intValue+1;
+
+var obj = {int: 1, float: 2.0, string: 'hello', nil: null, dictionary:{}};
+intValue = obj.int; // or: intValue = obj['int'];
+obj.int = intValue+1; // or: obj['int'] = intValue+1;
+```
+
+and if you are interested, Objective-C may make the syntax even lighter using [Objective-C literals](http://clang.llvm.org/docs/ObjectiveCLiterals.html) in the future:
+
+```
+NSA* arrayOfInts = @[@1, @2, @3];
+NSA* arrayOfObjects = @[@1, @2.0, @"hello", NSNull.null, @{}];
+NSD* obj = @{@int: @1, @float: @2.0, @string: @"hello", @nil: NSNull.null, @dictionary:@{}};
+```
+
+The JavaScript-Inspired Library
+==========
+
+To be able to reuse my JavaScript knowledge and not have to look through StackOverflow for really basic things that are hard to remember in Objective-C, I've ported some common JavaScript functions.
+
+
+All Objects
+-------
+
+```
+N.I(1).instanceof(N.class);
+// true
+
+(A.new).instanceof(NSA.class);
+// true
+
+N.B(true).toString();
+// @"true"
+
+OKV({@"key1", @"value1"}).toString();
+// @"[object Object]"
+
+AO(AI(1,2,3),N.F(4.5),OKV({@"five", @"5"})).toString();
+// @"[[1,2,3],4.5,[object Object]]
+```
+
+Arrays
+--------
+
+```
+AI(1,2,3).length;
+// 3
+
+AI(1,2,3).hasOwnProperty(@"2");
+// true
+
+AI(1,2,3).get(@"2");
+// N.I(3)
+
+AI(1,2,3).concat(AI(1,2,4);
+// [1,2,3,1,2,4]
+
+AO(@"Banana", @"Orange", @"Lemon", @"Apple", @"Mango").slice(-3,-1);
+// [Lemon,Apple]
+
+AI(1,2,3).reverse();
+// [3,2,1]
+
+AO(N.I(1),AI(2,3)).flatten(true);
+// [1,2,3]
+
+AI(1,2,3).pop();
+// N.I(3)
+
+AI(1,2,3).push(N.I(4)).push(@"out the door");
+// [1,2,3,4,out the door]
+
+AI(3,2,1,2).sort(nil);
+// [1,2,2,3]
+
+AO(@"Banana", @"Orange", @"Apple", @"Lemon").splice(2,1, @"Kiwi", @"Mango", nil);
+// [Banana,Orange,Kiwi,Mango,Lemon]
+
+AI(3,4,5).unshift(N.I(1),N.I(2),nil);
+// [1,2,3,4,5]
+
+AI(1,2,3,4,5).shift();
+// [2,3,4,5]
+```
+
+Objects/Dictionaries
+--------
+
+```
+OKV({@"int", N.I(1)}, {@"float", N.F(2.0)}).hasOwnProperty(@"int");
+// true
+
+OKV({@"int", N.I(1)}, {@"float", N.F(2.0)}).delete_(@"int").hasOwnProperty(@"int");
+// false
+
+@"int".in(OKV({@"int", N.I(1)}, {@"float", N.F(2.0)}));
+// true
+```
+
+Strings
+--------
+
+```
+@"hello world!".split(@" ")
+// [@"hello", @"world!"]
+
+@"hello world!".split(@"");
+// [@"h", @"e", @"l", @"l", @"o", @"w", @"o", @"r", @"l", @"d", @"!"]
+
+@"hello".add(@"world!");
+// @"hello world!"
+
+S* message = S.newS(@"hello"); message.append(@" world!");
+// message == @"hello world!"
+```
+
+Dates
+--------
+
+```
+SS.stringify(Date.newYMD_JS(2012, 7, 31));
+// @"2012-08-30T15:00:00.000Z"
+```
+
+Functions
+--------
+
+```
+O* obj = OKV({@"mirror", ^(NSS* string){return string.add(@" mirror"); }});
+@"mirror".call(obj, @"hello", nil);
+// @"hello mirror"
+
+@"mirror".apply(obj, AO(@"hello"));
+// @"hello mirror"
+```
+
+Utilities
+--------
+
+There are a few utilities on the Subjective-Script base object rather than making them global as in JavaScript.
+
+```
+SS.stringify(AO(N.I(1), N.F(2.0), N.F(3.1), @"hello", nil, O.new));
+// @"[1,2,3.1,\"hello\",null,{}]"
+
+SS.parseInt(@"123");
+// N.I(123)
+
+SS.typeof_(N.B(true));
+// @"boolean"
+
+SS.typeof_(@"string");
+// @"string"
+
+SS.typeof_(Date.new);
+// @"object"
+
+__block BOOL called1 = false;
+SSTimeout* timeout1 = SS.setTimeout(^{ called1 = true; }, NSEC_PER_SEC*1);
+SS.clearTimeout(timeout1);
+// not called
+
+__block BOOL called2 = false;
+SS.setTimeout(^{ called2 = true; }, NSEC_PER_SEC*2);
+// called
+```
+
+
+Want to Add Something?
+---------------
+
+Currently, this is still early days and there is a lot to add and test. Please help out!
+
+If there is anything else you would like added, just implement it in a good place, write the appropriate tests, and submit a pull request on [GitHub]((https://github.com/kmalakoff/_.m))
+
+Also, feel free to submit your favorite features from other languages as long as they are easy to remember and help speed up development!
Oops, something went wrong.

0 comments on commit 5d2a3cc

Please sign in to comment.