Skip to content

Commit db7ef21

Browse files
authored
File extension based charset. (#8)
* adds support for extension based charset * Update README.md
1 parent da4b346 commit db7ef21

File tree

6 files changed

+143
-84
lines changed

6 files changed

+143
-84
lines changed

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,13 @@ For number 3, remember that Port doesn't check the source code but instead their
168168

169169
## I've imported/exported a source code but it seems to have broken my encoding? Strange characters are showing up!
170170

171-
This can be caused due to Port working with UTF-8 by default. You can use the following methods to try and fix it:
171+
This can be caused due to Port working with UTF-8 by default. You can change this behavior according to your preferences by providing exactly which encoding should be used for a specific extension, you can do so by using the following methods:
172172

173-
* If you're having issues with a routine getting __imported__ with wrong encoding, you can use the method `SetRoutineInputTranslateTable`, this includes class items.
174-
* If you're having issues with a routine getting __exported__ with wrong encoding, you can use the method `SetRoutineOutputTranslateTable`, this also includes class items.
175-
* If you're having issues __importing__ with any files are that aren't routines, which means that they're public type classified, including CSP files. Then you can use the method `SetPublicFileInputTranslateTable`.
176-
* Finally, you're having issues __exporting__ any files that aren't routines as well, then you can use the method `SetPublicFileOutputTranslateTable`.
173+
* `SetInputCharset("charset")` will transcode the incoming document content to the provided charset.
174+
* `SetOutputCharset("charset")` will transcode the outgoing document content to the provided charset.
177175

178-
> __NOTE:__ All the methods accept only a single parameter which is a string representing the charset. If you don't want to apply any translation, you can pass "RAW" to all methods.
176+
So, let's say if you are using ISO-8859-1 or Windows 1252 when handling CSPs, you can configure _Port_ to use it instead of UTF-8.
177+
Note that by default Studio uses RAW format (which equals to non-unicode) for editing files. This might be a good use case for manually changing the charset for CSP files.
179178

180179
## It seems I'm not able to export GBL or any binary related files?
181180

cls/Port/Configuration.cls

Lines changed: 18 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -138,61 +138,37 @@ ClassMethod RegisterExtendedHooks(implementer As %String) As %Status
138138
return $$$OK
139139
}
140140

141-
ClassMethod GetExtendedHooksImplementer() As %String
142-
{
143-
return $get(^Port.Configuration("source.hooks.custom"))
144-
}
145-
146-
/// Defines the encoding used to save the routine items, this includes class items. Pass RAW to preserve the content as-is.
147-
ClassMethod SetRoutineInputTranslateTable(charset As %String) As %Status
148-
{
149-
set ^Port.Configuration("io.routine.in") = charset
150-
return $$$OK
151-
}
152-
153-
/// Defines the encoding used to save the exported files originated from routines, this includes class items. Pass RAW to preserve the content as-is.
154-
ClassMethod SetRoutineOutputTranslateTable(charset As %String) As %Status
155-
{
156-
set ^Port.Configuration("io.routine.out") = charset
157-
return $$$OK
158-
}
159-
160-
/// Defines the encoding used to save CSP items. Pass RAW to preserve the content as-is.
161-
ClassMethod SetPublicFileInputTranslateTable(charset As %String) As %Status
162-
{
163-
set ^Port.Configuration("io.public.in") = charset
164-
return $$$OK
165-
}
166-
167-
/// Defines the encoding used to save public files originated from CSP items. Pass RAW to preserve the content as-is.
168-
ClassMethod SetPublicFileOutputTranslateTable(charset As %String) As %Status
141+
/// Get the charset to be used when saving a document that has the provided extension.
142+
/// Defaults to "UTF8".
143+
ClassMethod GetInputCharset(extension As %String) As %String
169144
{
170-
set ^Port.Configuration("io.public.out") = charset
171-
return $$$OK
145+
return $get(^Port.Configuration("source.charset.input", $$$ucase(extension)), "UTF8")
172146
}
173147

174-
/// Retrieves the current configured routine translate table for inputs. Defaults to UTF-8.
175-
ClassMethod GetRoutineInputTranslateTable(charset As %String) As %Status
148+
/// Get the charset to be used when retrieving a document that has the provided extension.
149+
/// Defaults to "UTF8".
150+
ClassMethod GetOutputCharset(extension As %String) As %String
176151
{
177-
return $get(^Port.Configuration("io.routine.in"), "UTF8")
152+
return $get(^Port.Configuration("source.charset.output", $$$ucase(extension)), "UTF8")
178153
}
179154

180-
/// Retrieves the current configured routine translate table for outputs. Defaults to UTF-8.
181-
ClassMethod GetRoutineOutputTranslateTable(charset As %String) As %Status
155+
/// Set the character set to be used when saving a document with the provided extension.
156+
ClassMethod SetInputCharset(extension As %String, charset As %String) As %Status
182157
{
183-
return $get(^Port.Configuration("io.routine.out"), "UTF8")
158+
set ^Port.Configuration("source.charset.input", $$$ucase(extension)) = charset
159+
return $$$OK
184160
}
185161

186-
/// Retrieves the current configured routine translate table for outputs. Defaults to UTF-8.
187-
ClassMethod GetPublicFileInputTranslateTable(charset As %String) As %Status
162+
/// Set the character set to be used when retrieving a document with the provided extension.
163+
ClassMethod SetOutputCharset(extension As %String, charset As %String) As %Status
188164
{
189-
return $get(^Port.Configuration("io.public.in"), "UTF8")
165+
set ^Port.Configuration("source.charset.output", $$$ucase(extension)) = charset
166+
return $$$OK
190167
}
191168

192-
/// Retrieves the current configured public file translate table for outputs. Defaults to UTF-8.
193-
ClassMethod GetPublicFileOutputTranslateTable(charset As %String) As %Status
169+
ClassMethod GetExtendedHooksImplementer() As %String
194170
{
195-
return $get(^Port.Configuration("io.public.out"), "UTF8")
171+
return $get(^Port.Configuration("source.hooks.custom"))
196172
}
197173

198174
/// Defines which format the Port should for running unit test. When "XML" is selected, Port will export test classes as xml.

cls/Port/Project/Exporter.cls

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ Method ExportPublicFile(itemName As %String) As %Status
111111
}
112112

113113
set workspace = ##class(Port.Configuration).GetWorkspace(..Project.Name)
114+
set extension = $piece(itemName, ".", *)
114115

115116
try {
116117
set csp = ##class(%RoutineMgr).%New(itemName)
@@ -129,7 +130,7 @@ Method ExportPublicFile(itemName As %String) As %Status
129130

130131
set io = $$$GETIO
131132

132-
$$$SETIO(##class(Port.Configuration).GetPublicFileOutputTranslateTable())
133+
$$$SETIO(##class(Port.Configuration).GetOutputCharset(extension))
133134
set exported = ##class(%File).CopyFile(csp.Code.Filename, destination, 1)
134135
$$$SETIO(io)
135136

@@ -162,6 +163,7 @@ Method ExportRoutine(name As %String) As %Status
162163
set workspace = ##class(Port.Configuration).GetWorkspace(..Project.Name)
163164
set destination = ##class(Port.Util).ItemToPath(name, workspace)
164165
set destinationLocation = ##class(%File).GetDirectory(destination)
166+
set extension = $piece(name, ".", *)
165167

166168
$$$ThrowOnError(..Synchronizer.AddToWhitelist(name))
167169

@@ -174,7 +176,7 @@ Method ExportRoutine(name As %String) As %Status
174176
}
175177

176178
set file = ##class(%Stream.FileCharacter).%New()
177-
set file.TranslateTable = ##class(Port.Configuration).GetRoutineOutputTranslateTable()
179+
set file.TranslateTable = ##class(Port.Configuration).GetOutputCharset(extension)
178180
do file.LinkToFile(destination)
179181

180182
set routine = ##class(%RoutineMgr).%OpenId(name)
@@ -237,7 +239,7 @@ Method ExportClass(className As %String, fromPackage As %Boolean = 0) As %Status
237239
$$$ThrowOnError(##class(%Compiler.UDL.TextServices).GetTextAsStream($namespace, itemName, .stream))
238240

239241
set file = ##class(%Stream.FileCharacter).%New()
240-
set file.TranslateTable = ##class(Port.Configuration).GetRoutineOutputTranslateTable()
242+
set file.TranslateTable = ##class(Port.Configuration).GetOutputCharset("CLS")
241243
do file.LinkToFile(destination)
242244

243245
$$$ThrowOnError(file.CopyFromAndSave(stream))

cls/Port/Project/Importer.cls

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -301,13 +301,16 @@ Method Import() As %Status
301301

302302
ClassMethod ImportFromExternalSource(itemName As %String, origin As %String, itemType As %String) As %Status [ Final, Internal, Private ]
303303
{
304-
if (itemType = "CLS") {
304+
set extension = $$$ucase($piece(origin, ".", *))
305+
set tt = ##class(Port.Configuration).GetInputCharset(extension)
306+
307+
if (itemType = "CLS") {
305308
set fs = ##class(%Stream.FileCharacter).%New()
306-
set fs.TranslateTable = ##class(Port.Configuration).GetRoutineInputTranslateTable()
309+
set fs.TranslateTable = tt
307310
$$$QuitOnError(fs.LinkToFile(origin))
308311
$$$QuitOnError(##class(%Compiler.UDL.TextServices).SetTextFromStream($namespace, itemName, fs))
309312
} elseif ##class(Port.Util).IsRoutine(itemName) || (itemType = "CSP") {
310-
if itemName [ "/" set itemName = $$$LPadProvidedSlash(itemName, "/")
313+
if itemName [ "/" set itemName = $$$LPadProvidedSlash(itemName, "/")
311314

312315
if ##class(%RoutineMgr).Exists(itemName) {
313316
set routine = ##class(%RoutineMgr).%OpenId(itemName)
@@ -316,14 +319,14 @@ ClassMethod ImportFromExternalSource(itemName As %String, origin As %String, ite
316319
}
317320

318321
set localSource = ##class(%Stream.FileCharacter).%New()
319-
set localSource.TranslateTable = ##class(Port.Configuration).GetRoutineInputTranslateTable()
322+
set localSource.TranslateTable = tt
320323

321324
if itemType = "CSP" {
322-
if routine = "" return $$$PERROR($$$NoCompatibleApplicationForPublicFile, origin)
323-
set extension = $$$ucase($piece(origin, ".", *))
325+
if routine = "" return $$$PERROR($$$NoCompatibleApplicationForPublicFile, origin)
324326
if extension = "" set extension = "TXT"
325327
do ##class(%CSP.StreamServer).FileClassify(extension, .type, .bin)
326-
328+
if extension [ "CSP" || (extension = "CSR") set bin = 0
329+
327330
/// We can't use any translation table when importing a binary, so we do a bit-to-bit copy.
328331
if bin {
329332
set destination = routine.Code.Filename
@@ -333,8 +336,7 @@ ClassMethod ImportFromExternalSource(itemName As %String, origin As %String, ite
333336
$$$QuitOnError(##class(Port.Util).EnsurePathExists(path))
334337
$$$QuitOnError(##class(%File).CopyFile(origin, destination))
335338
return $$$OK
336-
} else {
337-
set tt = ##class(Port.Configuration).GetPublicFileInputTranslateTable()
339+
} else {
338340
set localSource.TranslateTable = tt
339341
set routine.Code.TranslateTable = tt
340342
}

port-prod.xml

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,42 @@ Defines a class used to handle source control hooks after Port execution.</Descr
241241
]]></Implementation>
242242
</Method>
243243

244+
<Method name="GetInputCharset">
245+
<ClassMethod>1</ClassMethod>
246+
<FormalSpec>extension:%String</FormalSpec>
247+
<ReturnType>%String</ReturnType>
248+
<Implementation><![CDATA[ return $get(^Port.Configuration("source.charset.input", $$$ucase(extension)), "UTF-8")
249+
]]></Implementation>
250+
</Method>
251+
252+
<Method name="GetOutputCharset">
253+
<ClassMethod>1</ClassMethod>
254+
<FormalSpec>extension:%String</FormalSpec>
255+
<ReturnType>%String</ReturnType>
256+
<Implementation><![CDATA[ return $get(^Port.Configuration("source.charset.output", $$$ucase(extension)), "UTF-8")
257+
]]></Implementation>
258+
</Method>
259+
260+
<Method name="SetInputCharset">
261+
<ClassMethod>1</ClassMethod>
262+
<FormalSpec>extension:%String,charset:%String</FormalSpec>
263+
<ReturnType>%Status</ReturnType>
264+
<Implementation><![CDATA[
265+
set ^Port.Configuration("source.charset.output", extension) = charset
266+
return $$$OK
267+
]]></Implementation>
268+
</Method>
269+
270+
<Method name="SetOutputCharset">
271+
<ClassMethod>1</ClassMethod>
272+
<FormalSpec>extension:%String,charset:%String</FormalSpec>
273+
<ReturnType>%Status</ReturnType>
274+
<Implementation><![CDATA[
275+
set ^Port.Configuration("source.charset.input", extension) = charset
276+
return $$$OK
277+
]]></Implementation>
278+
</Method>
279+
244280
<Method name="GetExtendedHooksImplementer">
245281
<ClassMethod>1</ClassMethod>
246282
<ReturnType>%String</ReturnType>
@@ -1556,6 +1592,7 @@ The CSP application name is mirrored into subfolders inside the public folder.</
15561592
}
15571593
15581594
set workspace = ##class(Port.Configuration).GetWorkspace(..Project.Name)
1595+
set extension = $piece(itemName, ".", *)
15591596
15601597
try {
15611598
set csp = ##class(%RoutineMgr).%New(itemName)
@@ -1574,7 +1611,7 @@ The CSP application name is mirrored into subfolders inside the public folder.</
15741611
15751612
set io = $$$GETIO
15761613
1577-
$$$SETIO(##class(Port.Configuration).GetPublicFileOutputTranslateTable())
1614+
$$$SETIO(##class(Port.Configuration).GetOutputCharset(extension))
15781615
set exported = ##class(%File).CopyFile(csp.Code.Filename, destination, 1)
15791616
$$$SETIO(io)
15801617
@@ -1611,6 +1648,7 @@ Export a routine to the workspace, the path inside the workspace is taken from t
16111648
set workspace = ##class(Port.Configuration).GetWorkspace(..Project.Name)
16121649
set destination = ##class(Port.Util).ItemToPath(name, workspace)
16131650
set destinationLocation = ##class(%File).GetDirectory(destination)
1651+
set extension = $piece(name, ".", *)
16141652
16151653
$$$ThrowOnError(..Synchronizer.AddToWhitelist(name))
16161654
@@ -1623,7 +1661,7 @@ Export a routine to the workspace, the path inside the workspace is taken from t
16231661
}
16241662
16251663
set file = ##class(%Stream.FileCharacter).%New()
1626-
set file.TranslateTable = ##class(Port.Configuration).GetRoutineOutputTranslateTable()
1664+
set file.TranslateTable = ##class(Port.Configuration).GetOutputCharset(extension)
16271665
do file.LinkToFile(destination)
16281666
16291667
set routine = ##class(%RoutineMgr).%OpenId(name)
@@ -1690,7 +1728,7 @@ Export a class to the workspace's 'cls' folder. Each class package is treated li
16901728
$$$ThrowOnError(##class(%Compiler.UDL.TextServices).GetTextAsStream($namespace, itemName, .stream))
16911729
16921730
set file = ##class(%Stream.FileCharacter).%New()
1693-
set file.TranslateTable = ##class(Port.Configuration).GetRoutineOutputTranslateTable()
1731+
set file.TranslateTable = ##class(Port.Configuration).GetOutputCharset("CLS")
16941732
do file.LinkToFile(destination)
16951733
16961734
$$$ThrowOnError(file.CopyFromAndSave(stream))
@@ -2090,13 +2128,16 @@ Export a class to the workspace's 'cls' folder. Each class package is treated li
20902128
<Private>1</Private>
20912129
<ReturnType>%Status</ReturnType>
20922130
<Implementation><![CDATA[
2093-
if (itemType = "CLS") {
2131+
set extension = $$$ucase($piece(origin, ".", *))
2132+
set tt = ##class(Port.Configuration).GetInputCharset(extension)
2133+
2134+
if (itemType = "CLS") {
20942135
set fs = ##class(%Stream.FileCharacter).%New()
2095-
set fs.TranslateTable = ##class(Port.Configuration).GetRoutineInputTranslateTable()
2136+
set fs.TranslateTable = tt
20962137
$$$QuitOnError(fs.LinkToFile(origin))
20972138
$$$QuitOnError(##class(%Compiler.UDL.TextServices).SetTextFromStream($namespace, itemName, fs))
20982139
} elseif ##class(Port.Util).IsRoutine(itemName) || (itemType = "CSP") {
2099-
if itemName [ "/" set itemName = $$$LPadProvidedSlash(itemName, "/")
2140+
if itemName [ "/" set itemName = $$$LPadProvidedSlash(itemName, "/")
21002141
21012142
if ##class(%RoutineMgr).Exists(itemName) {
21022143
set routine = ##class(%RoutineMgr).%OpenId(itemName)
@@ -2105,14 +2146,14 @@ Export a class to the workspace's 'cls' folder. Each class package is treated li
21052146
}
21062147
21072148
set localSource = ##class(%Stream.FileCharacter).%New()
2108-
set localSource.TranslateTable = ##class(Port.Configuration).GetRoutineInputTranslateTable()
2149+
set localSource.TranslateTable = tt
21092150
21102151
if itemType = "CSP" {
2111-
if routine = "" return $$$PERROR($$$NoCompatibleApplicationForPublicFile, origin)
2112-
set extension = $$$ucase($piece(origin, ".", *))
2152+
if routine = "" return $$$PERROR($$$NoCompatibleApplicationForPublicFile, origin)
21132153
if extension = "" set extension = "TXT"
21142154
do ##class(%CSP.StreamServer).FileClassify(extension, .type, .bin)
2115-
2155+
if extension [ "CSP" || (extension = "CSR") set bin = 0
2156+
21162157
/// We can't use any translation table when importing a binary, so we do a bit-to-bit copy.
21172158
if bin {
21182159
set destination = routine.Code.Filename
@@ -2122,8 +2163,7 @@ Export a class to the workspace's 'cls' folder. Each class package is treated li
21222163
$$$QuitOnError(##class(Port.Util).EnsurePathExists(path))
21232164
$$$QuitOnError(##class(%File).CopyFile(origin, destination))
21242165
return $$$OK
2125-
} else {
2126-
set tt = ##class(Port.Configuration).GetPublicFileInputTranslateTable()
2166+
} else {
21272167
set localSource.TranslateTable = tt
21282168
set routine.Code.TranslateTable = tt
21292169
}

0 commit comments

Comments
 (0)