Skip to content

Commit cfcdfad

Browse files
committed
release/v0.6.0
2 parents ff722bf + 8fa3d86 commit cfcdfad

19 files changed

Lines changed: 363 additions & 16 deletions

README.org

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
let doc = try parser.parse(lines: lines)
2525
#+END_SRC
2626

27-
* Supported Syntax (so far) [15/18]
27+
* Supported Syntax (so far) [16/19]
2828
** DONE Affiliated Keywords (aka In Buffer Settings)
2929
CLOSED: [2016-09-03 Sat 12:47]
3030

@@ -70,6 +70,20 @@
7070
,* Section with multiple tags :tag1:tag2:tag3:
7171
#+END_SRC
7272

73+
** DONE Planning
74+
CLOSED: [2017-01-09 Mon 16:09]
75+
76+
#+BEGIN_SRC org
77+
,* DONE Closed task
78+
CLOSED: [2017-01-09 Mon 15:58]
79+
80+
,* Scheduled task
81+
SCHEDULED: <2017-01-09 Mon>
82+
83+
,* TODO task that has a deadline
84+
DEADLINE: <2017-01-16 Mon +1w>
85+
#+END_SRC
86+
7387
** DONE Paragraph
7488
CLOSED: [2016-09-03 Sat 12:47]
7589
Lines without *line breaker* becomes a *paragraph*.

Sources/Constants.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// Constants.swift
3+
// SwiftOrg
4+
//
5+
// Created by Xiaoxing Hu on 9/01/17.
6+
// Copyright © 2017 Xiaoxing Hu. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
public enum PlanningKeyword: String {
12+
case deadline = "DEADLINE"
13+
case scheduled = "SCHEDULED"
14+
case closed = "CLOSED"
15+
16+
static let all = [deadline.rawValue, scheduled.rawValue, closed.rawValue]
17+
}
18+
19+
public enum Priority: String {
20+
case A = "A"
21+
case B = "B"
22+
case C = "C"
23+
}

Sources/Info-iOS.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<key>CFBundlePackageType</key>
1616
<string>FMWK</string>
1717
<key>CFBundleShortVersionString</key>
18-
<string>0.5.1</string>
18+
<string>0.6.0</string>
1919
<key>CFBundleVersion</key>
2020
<string>$(CURRENT_PROJECT_VERSION)</string>
2121
<key>NSPrincipalClass</key>

Sources/Info-macOS.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<key>CFBundlePackageType</key>
1616
<string>FMWK</string>
1717
<key>CFBundleShortVersionString</key>
18-
<string>0.5.1</string>
18+
<string>0.6.0</string>
1919
<key>CFBundleVersion</key>
2020
<string>$(CURRENT_PROJECT_VERSION)</string>
2121
<key>NSHumanReadableCopyright</key>

Sources/JsonConverter.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ func toDict(_ node: Node) -> [String: Any] {
6161
json["label"] = footnote.label
6262
json["content"] = footnote.content.map { n in toDict(n) }
6363
}
64+
if let planning = node as? Planning {
65+
json["type"] = "planning"
66+
json["keyword"] = planning.keyword.rawValue
67+
// TODO: jsonfiy timestamp
68+
// if let timestamp = planning.timestamp {
69+
// var ts = [String: Any]()
70+
// ts["active"] = timestamp.active
71+
// ts["date"] = timestamp.date
72+
// ts["repeater"] = timestamp.repeater
73+
// json["timestamp"] = ts
74+
// }
75+
}
6476
return json
6577
}
6678

Sources/Node.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ extension OrgParser {
8383
return try parseDrawer()
8484
case .listItem:
8585
return try parseList()
86+
case .planning(let keyword, let timestamp):
87+
_ = tokens.dequeue()
88+
return Planning(keyword: keyword, timestamp: timestamp)
8689
default:
8790
throw Errors.unexpectedToken("\(token) is not expected")
8891
}

Sources/Regex.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ import Foundation
1010

1111
var expressions = [String: NSRegularExpression]()
1212
public extension String {
13-
func getExpression(_ regex: String, options: NSRegularExpression.Options) -> NSRegularExpression {
13+
14+
/// Cache regex (for performance and resource sake)
15+
///
16+
/// - Parameters:
17+
/// - regex: regex pattern
18+
/// - options: options
19+
/// - Returns: the regex
20+
private func getExpression(_ regex: String, options: NSRegularExpression.Options) -> NSRegularExpression {
1421
let expression: NSRegularExpression
1522
if let exists = expressions[regex] {
1623
expression = exists
@@ -21,7 +28,7 @@ public extension String {
2128
return expression
2229
}
2330

24-
func getMatches(_ match: NSTextCheckingResult) -> [String?] {
31+
private func getMatches(_ match: NSTextCheckingResult) -> [String?] {
2532
var matches = [String?]()
2633
switch match.numberOfRanges {
2734
case 0:

Sources/Section.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,17 @@
88

99
import Foundation
1010

11-
1211
public struct Section: Node {
13-
public enum Priority: String {
14-
case A = "A"
15-
case B = "B"
16-
case C = "C"
17-
}
1812

13+
// MARK: properties
1914
public var index: OrgIndex?
2015

2116
public var title: String?
2217
public var stars: Int
2318
public var keyword: String?
2419
public var priority: Priority?
20+
public var tags: [String]?
21+
public var content = [Node]()
2522

2623
public var drawers: [Drawer]? {
2724
let ds = content.filter { node in
@@ -31,10 +28,12 @@ public struct Section: Node {
3128
}
3229
return ds
3330
}
34-
public var tags: [String]?
3531

36-
public var content = [Node]()
32+
public var planning: Planning? {
33+
return content.first { $0 is Planning } as? Planning
34+
}
3735

36+
// MARK: func
3837
public init(stars l: Int, title t: String?, todos: [String]) {
3938
stars = l
4039
// TODO limit charset on tags
@@ -58,6 +57,15 @@ public struct Section: Node {
5857
}
5958
}
6059

60+
public struct Planning: Node {
61+
public let keyword: PlanningKeyword
62+
public let timestamp: Timestamp?
63+
64+
public var description: String {
65+
return "Planning(keyword: \(keyword), timestamp: \(timestamp))"
66+
}
67+
}
68+
6169
extension OrgParser {
6270
func parseSection(_ index: OrgIndex) throws -> Node? {
6371
skipBlanks() // in a section, you don't care about blanks

Sources/Timestamp.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// Timestamp.swift
3+
// SwiftOrg
4+
//
5+
// Created by Xiaoxing Hu on 8/01/17.
6+
// Copyright © 2017 Xiaoxing Hu. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
public struct Timestamp {
12+
public let active: Bool
13+
public let date: Date
14+
public let repeater: String?
15+
16+
static func from(string: String) -> Timestamp? {
17+
let markPattern = "\\+|\\+\\+|\\.\\+|-|--"
18+
let pattern = "^(<|\\[)(.+?)(?: (\(markPattern))(\\d+)([hdwmy])\\s*)?(>|])$"
19+
guard let m = string.trimmed.match(pattern) else {
20+
print("'\(string)' doesn't match.")
21+
return nil
22+
}
23+
24+
print("match: \(m)")
25+
26+
let formater = DateFormatter()
27+
let formats = [
28+
"yyyy-MM-dd EEE H:mm",
29+
"yyyy-MM-dd EEE",
30+
]
31+
32+
for format in formats {
33+
formater.dateFormat = format
34+
guard let date = formater.date(from: m[2]!) else { continue }
35+
let active = m[1]! == "<"
36+
37+
var repeater: String? = nil
38+
if let mark = m[3], let value = m[4], let unit = m[5] {
39+
repeater = "\(mark)\(value)\(unit)"
40+
}
41+
let timestamp = Timestamp(active: active, date: date, repeater: repeater)
42+
return timestamp
43+
}
44+
return nil
45+
}
46+
}

Sources/Tokens.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public struct TokenMeta {
1717
public enum Token {
1818
case setting(key: String, value: String?)
1919
case headline(stars: Int, text: String?)
20+
case planning(keyword: PlanningKeyword, timestamp: Timestamp?)
2021
case blank
2122
case horizontalRule
2223
case blockBegin(name: String, params: [String]?)
@@ -104,6 +105,10 @@ func defineTokens() {
104105
define("^(\\*+)\\s+(.*)$") { matches in
105106
.headline(stars: matches[1]!.characters.count, text: matches[2]) }
106107

108+
define("^\\s*(\(PlanningKeyword.all.joined(separator: "|"))):\\s+(.+)$") { matches in
109+
let timestamp = Timestamp.from(string: matches[2]!)
110+
return .planning(keyword: PlanningKeyword(rawValue: matches[1]!)!, timestamp: timestamp)
111+
}
107112
// Block
108113
define("^(\\s*)#\\+begin_([a-z]+)(?:\\s+(.*))?$",
109114
options: [.caseInsensitive])

0 commit comments

Comments
 (0)