forked from erkyrath/Inform7-IDE-Mac
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIFSyntaxStorage.h
237 lines (184 loc) · 10.5 KB
/
IFSyntaxStorage.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
//
// IFSyntaxStorage.h
// Inform
//
// Created by Andrew Hunter on 17/11/2004.
// Copyright 2004 Andrew Hunter. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "IFIntelFile.h"
//
// Predefined states
//
enum {
IFSyntaxStateNotHighlighted = 0xffffffff,
IFSyntaxStateDefault = 0
};
// Syntax styles
enum {
// Basic syntax types
IFSyntaxNone = 0,
IFSyntaxString,
IFSyntaxComment,
IFSyntaxMonospace,
// Inform 6 syntax types
IFSyntaxDirective,
IFSyntaxProperty,
IFSyntaxFunction,
IFSyntaxCode,
IFSyntaxCodeAlpha,
IFSyntaxAssembly,
IFSyntaxEscapeCharacter,
// Styles between 0x20-0x40 are the same as above but with a flag set
// Natural inform syntax types
IFSyntaxHeading = 0x80, // Heading style
IFSyntaxPlain, // 'No highlighting' style - lets user defined styles show through
IFSyntaxGameText, // Text that appears in the game
IFSyntaxSubstitution, // Substitution instructions
IFSyntaxNaturalInform, // Natural inform standard text
IFSyntaxTitle, // The title of a Natural Inform game
IFSyntaxStyleNotHighlighted = 0xf0, // Used internally by the highlighter to indicate that the highlights are invalid for a particular range
// Debugging syntax types
IFSyntaxDebugHighlight = 0xa0
};
typedef unsigned int IFHighlighterMode;
typedef unsigned int IFSyntaxState;
typedef unsigned char IFSyntaxStyle;
@class IFSyntaxStorage;
//
// Classes must implement this to create a new syntax highlighter
//
@protocol IFSyntaxHighlighter
// Notifying of the highlighter currently in use
- (void) setSyntaxStorage: (IFSyntaxStorage*) storage; // Sets the storage that the highlighter is (currently) dealing with
// The highlighter itself
- (IFSyntaxState) stateForCharacter: (unichar) chr // Retrieves the syntax state for a given character
afterState: (IFSyntaxState) lastState;
- (IFSyntaxStyle) styleForCharacter: (unichar) chr // Retrieves the style for a given character with the specified state transition
nextState: (IFSyntaxState) nextState
lastState: (IFSyntaxState) lastState;
- (void) rehintLine: (NSString*) line // Opportunity to highlight keywords, etc missed by the first syntax highlighting pass. styles has one entry per character in the line specified, and can be rewritten as required
styles: (IFSyntaxStyle*) styles
initialState: (IFSyntaxState) state;
// Styles
- (NSDictionary*) attributesForStyle: (IFSyntaxStyle) style; // Retrieves the text attributes a specific style should use
- (float) tabStopWidth; // Retrieves the width of a tab stop
@end
//
// Classes must implement this to provide syntax intelligence (real-time indexing and autocomplete)
//
@protocol IFSyntaxIntelligence
// Notifying of the highlighter currently in use
- (void) setSyntaxStorage: (IFSyntaxStorage*) storage; // Sets the syntax storage that the intelligence object should use
// Gathering information (works like rehint)
- (void) gatherIntelForLine: (NSString*) line // Gathers intelligence data for the given line (with the given syntax highlighting styles, initial state and line number), and places the resulting data into the given IntelFile object
styles: (IFSyntaxStyle*) styles
initialState: (IFSyntaxState) state
lineNumber: (int) lineNumber
intoData: (IFIntelFile*) data;
// Autotyping (occurs when inserting single characters, and allows us to turn '\n' into '\n\t' for example
- (NSString*) rewriteInput: (NSString*) input; // Opportunity to automatically insert data (for instance to implement auto-tabbing)
@end
///
/// NSTextStorage subclasses can implement this to be notified of events on the main text storage object
///
@protocol IFDerivativeStorage
- (void) didBeginEditing: (NSTextStorage*) storage;
- (void) didEdit: (NSTextStorage*) storage
mask: (unsigned int) mask
changeInLength: (int) lengthChange
range: (NSRange) range;
- (void) didEndEditing: (NSTextStorage*) storage;
@end
//
// An NSTextStorage object that performs syntax highlighting
//
@interface IFSyntaxStorage : NSTextStorage {
// The string
NSMutableAttributedString* string;
// Syntax state (static)
int nLines; // Number of lines
unsigned* lineStarts; // Start positions of each line
NSMutableArray* lineStates; // Syntax stack at the start of lines
IFSyntaxStyle* charStyles; // Syntax state for each character
NSMutableArray* lineStyles; // NSParagraphStyles for each line
NSMutableArray* highlightingStack; // Future ranges that still need highlighting
NSRange needsHighlighting; // Range that still needs highlighting
int amountHighlighted; // Amount highlighted this pass
// Syntax state (dynamic)
NSMutableArray* syntaxStack; // Current syntax stack
int syntaxPos; // Current highlighter position
IFSyntaxState syntaxState; // Active state
IFHighlighterMode syntaxMode; // 'Mode' - possible extra state from the highlighter
// The highlighter
id<IFSyntaxHighlighter,NSObject> highlighter;
// Paragraph styles
NSMutableArray* tabStops; // Tab stop array
NSMutableArray* paragraphStyles; // Maps number of tabs at the start of a line to the appropriate paragraph style
BOOL enableWrapIndent; // YES if we should change the indentation on line wrap
BOOL enableElasticTabs; // YES if elastic tabs should be enabled
BOOL computingElasticTabs; // YES if we're currently computing elastic tab sizes
// 'Intelligence'
id<IFSyntaxIntelligence,NSObject> intelSource;
IFIntelFile* intelData; // 'Intelligence' data
NSRange editingRange; // Used while rewriting
// Derivative storage objects
int numDerivative;
id<IFDerivativeStorage>* derivative;
}
// Setting/retrieving the highlighter
- (void) setHighlighter: (id<IFSyntaxHighlighter,NSObject>) highlighter; // Sets the syntax highlighter to use
- (id<IFSyntaxHighlighter>) highlighter; // Retrieves the active syntax highlighter
- (BOOL) highlighting; // YES if highlighting is/may be going on
// Communication from the highlighter
- (void) pushState; // Pushes the current state onto the stack
- (IFSyntaxState) popState; // Pops a state from the stack (which is returned)
- (void) backtrackWithStyle: (IFSyntaxStyle) newStyle // Overwrites the styles backwards from the current position
length: (int) backtrackLength;
- (void) setHighlighterMode: (IFHighlighterMode) newMode; // Allows the highlighter to run in different 'modes' (basically, extends the state data to 64 bits)
- (IFHighlighterMode) highlighterMode; // Retrieves the current highlighter mode
- (BOOL) preceededByKeyword: (NSString*) keyword // If the given keyword occurs offset characters behind the current position, returns YES (ie, if the given keyword occurs and ends offset characters previously)
offset: (int) offset;
// Actually performing highlighting
- (void) highlightRangeSoon: (NSRange) range; // The given range will be highlighted later (queues a request)
- (void) highlightRange: (NSRange) rangeToHighlight; // Highlights a piece of string
- (BOOL) highlighterPass; // Performs a highlighter pass (highlights only part of the file if there's a lot to do and queues another request)
- (void) startBackgroundHighlighting; // Queues up anything that needs highlighting in the background
- (void) stopBackgroundHighlighting; // Abandons the current highlighter queue
- (void) preferencesChanged: (NSNotification*) not; // Forces a rehighlight (to take account of new preferences)
- (BOOL) elasticTabs; // Whether or not elastic tabs are enabled
- (void) setElasticTabs: (BOOL) enableElasticTabs; // Sets whether or not elastic tabs should be used for this storage object
- (NSRange) rangeOfElasticRegionAtIndex: (int) charIndex; // Given a character index, works out the character range that elastic tabs should be applied to. Uses NSNotFound if elastic tabs shouldn't be applied to this range
- (NSArray*) elasticTabsInRegion: (NSRange) region; // Given a region, returns the set of tab stops to use for elastic tabs
- (NSDictionary*) paragraphStyleForTabStops: (int) numberOfTabstops; // Gets a paragraph style for the given number of tab stops
// Gathering/retrieving intelligence data
- (void) setIntelligence: (id<IFSyntaxIntelligence>) intel; // Sets the intelligence object for this highlighter
- (id<IFSyntaxIntelligence>) intelligence; // Retrieves the current intelligence object
- (IFIntelFile*) intelligenceData; // Retrieves the intel data for the current intelligence object
// Intelligence callbacks (rewriting lines)
- (int) editingLineNumber; // (To be called from rewriteInput) the number of the line being rewritten
- (int) numberOfTabStopsForLine: (int) lineNumber; // (To be called from rewriteInput) the number of tab stops on the given line
- (NSString*) textForLine: (int) lineNumber; // (To be called from rewriteInput) the text for a specific line number (which must be lower than the current line number)
- (IFSyntaxStyle) styleAtStartOfLine: (int) lineNumber; // (To be called from rewriteInput) the syntax highlighting style at the start of a specific line
- (IFSyntaxStyle) styleAtEndOfLine: (int) lineNumber; // (To be called from rewriteInput) the style at the end of a specific line
- (unichar) characterAtEndOfLine: (int) lineNumber; // (To be called from rewriteInput) the character at the end of a specific line
- (void) callbackForEditing: (SEL) selector // (To be called from rewriteInput) callback allows editing outside the current line
withValue: (id) parameter;
- (void) replaceLine: (int) lineNumber // (To be called from the callbackForEditing) replaces a line with another line
withLine: (NSString*) newLine; // DANGEROUS! May change styles, invoke the highlighter, etc
// Allowing derivative text storage objects
- (void) addDerivativeStorage: (id<IFDerivativeStorage>) newStorage; // Adds an object to monitor editing events on this object (NOT RETAINED)
- (void) removeDerivativeStorage: (id<IFDerivativeStorage>) oldStorage; // Removes a derivative storage object
@end
//
// Extra delegate methods for the IFSyntaxStorage object
// Enables other objects to ensure that undo works as intended
//
@interface NSObject(IFSyntaxStorageDelegate)
// Called when the syntax storage replaces some text automatically. A delegate can use this to ensure that the
// undo manager is up to date
- (void) rewroteCharactersInStorage: (IFSyntaxStorage*) storage
range: (NSRange) range
originalString: (NSString*) originalString
replacementString: (NSString*) replacementString;
@end