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
|
define_tag(
'load',
-namespace='tags_',
-req='path', -type='string',
-opt='ext', -type='string',
-opt='refresh', -type='boolean',
-priority='replace',
-description='Loads all files in the given path into the global namespace.'
);
// assumes custom tags/types are kept in separate files,
// each named with the name of the tag and the provided
// extension, i.e., a tag named foo_bar would be in a
// file named 'foo_bar.inc'.
// for files that contain multiple related tags/types,
// use the pattern <namespace>_library.<ext> and include
// a simple tag which returns 'Loaded' for that name, i.e.
// the Foo tag library would be called 'foo_library.inc',
// and would contain a tag at the end like so:
// define_tag('foo_library');
// return('Loaded');
// /define_tag;
// set defaults
// ext is the file extension to load
// refresh is whether or not to refresh all files/tags
!local_defined('ext') ? local('ext') = '.inc';
!local_defined('refresh') ? local('refresh') = false;
// initialize vars
// tagsLoaded stores the number of tags loaded
// ctags is an array of files to load
// to remove is an array of files to remove from ctags
// tagmapname is a unique name to use in globals
local(
'tagsLoaded' = 0,
'ctags' = array,
'toRemove' = array,
'tagmapname' = string_replaceregexp(
server_name + #path,
-find='^[a-zA-Z0-9]',
-replace='',
-ignorecase
)
);
// create some globals if they do not already exist
// one to control thread locking (LP8.1 compatible method)
// and one to store a count of successfully loaded files/tags
!global_defined(#tagmapname + '_lock') ? global(#tagmapname + '_lock') = thread_lock;
local('tagloader_threadlock') = @global(#tagmapname + '_lock');
!global_defined(#tagmapname + '_count') ? global(#tagmapname + '_count') = 0;
local('tagloader_count') = @global(#tagmapname + '_count');
if(#refresh && #tagloader_threadlock->lock);
#tagloader_count = 0;
#tagloader_threadlock->unlock;
/if;
// LP 8.5 and higher only could use this instead:
// thread_atomic(#tagloader_count);
// !#tagloader_count || #refresh ? #tagloader_count = 0;
// /thread_atomic;
// get list of tags
#path->endswith('/') ? #ctags = file_listdirectory(#path) | #ctags->insert(#path);
// remove files that start with a period (LP8.1 compatible method)
iterate(#ctags, local('i'));
#i->beginswith('.') || !#i->endswith(#ext) ? #toRemove->insert(#i);
/iterate;
#ctags->sort;
#toRemove->sort;
#ctags = #ctags->difference(#toRemove);
// LP 8.5 and higher only could use this instead:
// #ctags->removeall(match_regexp('^\\..*'));
// compare to current size, only run if different
if(#ctags->size != #tagloader_count || #refresh);
// loop through list
iterate(#ctags, local('thisTag'));
// pop off extension
local('thisTagName' = #thisTag);
#thisTagName->removetrailing(#ext);
// if not already defined (or refreshing)
if(!lasso_tagexists(#thisTagName) || #refresh);
// use global namespace so tags stay resident in memory
namespace_using(namespace_global);
protect;
#ctags->size > 1 ? library(#path + #thisTag) | library(#path);
#tagsLoaded += 1;
// log any errors
handle_error;
log_critical('[Tagloader] Error loading [' + #thisTagName + ']: ' + error_msg);
/handle_error;
/protect;
/namespace_using;
else;
// account for tags that already exist
#tagsLoaded += 1;
/if;
/iterate;
// update global
// LP 8.1 compatible method
if(#tagloader_threadlock->lock);
#tagloader_count = #tagsLoaded;
#tagloader_threadlock->unlock;
/if;
// LP 8.5 and higher only
// thread_atomic(#tagloader_count);
// #tagloader_count = #tagsLoaded;
// /thread_atomic;
// log results
log_warning('[Tagloader] ' + #tagsLoaded + ' of ' + #ctags->size + ' tags loaded successfully.');
/if;
/define_tag;
define_tag(
'unload',
-namespace='tags_',
-req='path',
-priority='replace',
-description='Unloads all tags in the given path from memory.'
);
if(file_isdirectory(#path));
local('files') = file_listdirectory(#path);
else;
local('files') = array(#path);
/if;
iterate(#files, local('i'));
if(!#i->beginswith('.') && !#i->endswith('/'));
local('ext') = #i->split('.')->last;
local('tagname') = string(#i)->removetrailing('.' + #ext)&;
namespace_unload(#tagname);
/if;
/iterate;
/define_tag;
|