Put "give execute permission" option on the save panel

This commit is contained in:
1024jp 2016-03-06 18:38:53 +09:00
parent cbc052720c
commit c93209bd56
7 changed files with 181 additions and 0 deletions

View File

@ -7,6 +7,7 @@ develop
### New Features
- Now, the execute permission can be given to the file to save from the save panel.
- Add “Trim Trailing Whitespace” action to “Text” menu.
- Add option to trim trailing whitespace automatically on save (in “General” pane).

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9532" systemVersion="15D21" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9532"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="CEDocument">
<connections>
<outlet property="savePanelAccessoryView" destination="c22-O7-iKe" id="KQ3-o9-1zF"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="c22-O7-iKe">
<rect key="frame" x="0.0" y="0.0" width="206" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<button translatesAutoresizingMaskIntoConstraints="NO" id="MYJ-5I-MJB">
<rect key="frame" x="18" y="8" width="170" height="18"/>
<buttonCell key="cell" type="check" title="Give execute permission" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="KjO-BV-esE">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="-2" name="value" keyPath="executable" id="LIn-h3-qco"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="MYJ-5I-MJB" secondAttribute="bottom" constant="10" id="Aa6-XJ-bZ7"/>
<constraint firstItem="MYJ-5I-MJB" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" constant="10" id="nfC-KA-Ydc"/>
<constraint firstAttribute="trailing" secondItem="MYJ-5I-MJB" secondAttribute="trailing" constant="20" symbolic="YES" id="vT5-kx-hsa"/>
<constraint firstItem="MYJ-5I-MJB" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" constant="20" symbolic="YES" id="wUp-C6-D78"/>
</constraints>
<point key="canvasLocation" x="452" y="394"/>
</customView>
</objects>
</document>

View File

@ -85,6 +85,8 @@
2A3A75AB19E77E87001DAB88 /* SyntaxOutlineEditView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2A3A75A219E77E87001DAB88 /* SyntaxOutlineEditView.xib */; };
2A3A75AC19E77E87001DAB88 /* SyntaxValidationView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2A3A75A419E77E87001DAB88 /* SyntaxValidationView.xib */; };
2A3A75B319E77F32001DAB88 /* CESyntaxValidationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A3A75B219E77F32001DAB88 /* CESyntaxValidationViewController.m */; };
2A3CC1F71C8B442600506DB8 /* SaveDocumentAccessory.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2A3CC1F51C8B442600506DB8 /* SaveDocumentAccessory.xib */; };
2A3CC1F81C8B442600506DB8 /* SaveDocumentAccessory.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2A3CC1F51C8B442600506DB8 /* SaveDocumentAccessory.xib */; };
2A3FB2AD18ECEFF200D9CB2C /* CESyntaxEditSheetController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A3FB2AC18ECEFF200D9CB2C /* CESyntaxEditSheetController.m */; };
2A41CB3D1C3906BA00F9122B /* CEInvisibles.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A41CB3C1C3906BA00F9122B /* CEInvisibles.m */; };
2A41CB3E1C3906BA00F9122B /* CEInvisibles.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A41CB3C1C3906BA00F9122B /* CEInvisibles.m */; };
@ -568,6 +570,10 @@
2A3A759319E77D66001DAB88 /* CEMigrationWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CEMigrationWindowController.m; sourceTree = "<group>"; };
2A3A75B119E77F32001DAB88 /* CESyntaxValidationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CESyntaxValidationViewController.h; sourceTree = "<group>"; };
2A3A75B219E77F32001DAB88 /* CESyntaxValidationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CESyntaxValidationViewController.m; sourceTree = "<group>"; };
2A3CC1F61C8B442600506DB8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SaveDocumentAccessory.xib; sourceTree = "<group>"; };
2A3CC1FA1C8B59EB00506DB8 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/SaveDocumentAccessory.strings; sourceTree = "<group>"; };
2A3CC1FC1C8B59EE00506DB8 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/SaveDocumentAccessory.strings"; sourceTree = "<group>"; };
2A3CC1FE1C8B59F100506DB8 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/SaveDocumentAccessory.strings; sourceTree = "<group>"; };
2A3FB2AB18ECEFF200D9CB2C /* CESyntaxEditSheetController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CESyntaxEditSheetController.h; sourceTree = "<group>"; };
2A3FB2AC18ECEFF200D9CB2C /* CESyntaxEditSheetController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CESyntaxEditSheetController.m; sourceTree = "<group>"; };
2A4063FA1B9DA6080032AC7F /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/SyntaxValidationView.strings; sourceTree = "<group>"; };
@ -1597,6 +1603,7 @@
isa = PBXGroup;
children = (
2AFFB72A18D8C7DE00118477 /* OpenDocumentAccessory.xib */,
2A3CC1F51C8B442600506DB8 /* SaveDocumentAccessory.xib */,
2A07202C18E0E421006F3A43 /* PrintPanelAccessory.xib */,
2588E9CC07C4851C0060021D /* ProgressSheet.xib */,
2AB4326C1912ADAC00835004 /* CharacterPopover.xib */,
@ -1906,6 +1913,7 @@
2A6F0D931B5500E100C2D03C /* NaviBar_Show.tiff in Resources */,
2A6F0D941B5500E100C2D03C /* LineNumber_Hide.tiff in Resources */,
2A6F0D951B5500E100C2D03C /* LineNumber_Show.tiff in Resources */,
2A3CC1F81C8B442600506DB8 /* SaveDocumentAccessory.xib in Resources */,
2A5DBE591B5D2DB400F8CB13 /* SyntaxOutlineEditView.xib in Resources */,
2A6F0D961B5500E100C2D03C /* StatusBar_Hide.tiff in Resources */,
2A6F0D971B5500E100C2D03C /* StatusBar_Show.tiff in Resources */,
@ -2000,6 +2008,7 @@
2A961C5418FC699E002076B6 /* ScriptMenu Folder.rtf in Resources */,
2A961C5218FC699E002076B6 /* AppleScript.rtf in Resources */,
2A42825518FCD47B00386899 /* Acknowledgements.rtf in Resources */,
2A3CC1F71C8B442600506DB8 /* SaveDocumentAccessory.xib in Resources */,
8C081B4B07D0A85A0060191A /* GetInfo.tiff in Resources */,
8C98366708C0211D00746F92 /* IncompatibleChars.tiff in Resources */,
8CA71BCE07D2A79100C146B0 /* BiggerFont.tiff in Resources */,
@ -2705,6 +2714,17 @@
name = SyntaxValidationView.xib;
sourceTree = "<group>";
};
2A3CC1F51C8B442600506DB8 /* SaveDocumentAccessory.xib */ = {
isa = PBXVariantGroup;
children = (
2A3CC1F61C8B442600506DB8 /* Base */,
2A3CC1FA1C8B59EB00506DB8 /* ja */,
2A3CC1FC1C8B59EE00506DB8 /* zh-Hans */,
2A3CC1FE1C8B59F100506DB8 /* de */,
);
name = SaveDocumentAccessory.xib;
sourceTree = "<group>";
};
2A436DCB1A4243D500275FD4 /* DocumentInspectorView.xib */ = {
isa = PBXVariantGroup;
children = (

View File

@ -73,6 +73,7 @@ NSString *_Nonnull const CEIncompatibleConvertedCharKey = @"convertedChar";
@interface CEDocument ()
@property (nonatomic, nullable) CEPrintPanelAccessoryController *printPanelAccessoryController;
@property (nonatomic, nullable) IBOutlet NSView *savePanelAccessoryView;
@property (nonatomic) NSStringEncoding readingEncoding; // encoding to read document file
@property (nonatomic) BOOL needsShowUpdateAlertWithBecomeKey;
@ -85,6 +86,7 @@ NSString *_Nonnull const CEIncompatibleConvertedCharKey = @"convertedChar";
@property (nonatomic) BOOL shouldSaveXattr;
@property (nonatomic, nonnull, copy) NSString *autosaveIdentifier;
@property (nonatomic) BOOL suppressesIANACharsetConflictAlert;
@property (nonatomic, getter=isExecutable) BOOL executable;
// readonly
@property (readwrite, nonatomic, nullable) CEWindowController *windowController;
@ -215,6 +217,7 @@ NSString *_Nonnull const CEIncompatibleConvertedCharKey = @"convertedChar";
if ([self fileURL]) {
NSDictionary<NSString *, id> *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[[self fileURL] path] error:outError];
[self setFileAttributes:attributes];
[self setExecutable:([attributes filePosixPermissions] & S_IXUSR) != 0];
}
// try reading the `com.apple.TextEncoding` extended attribute
@ -432,6 +435,30 @@ NSString *_Nonnull const CEIncompatibleConvertedCharKey = @"convertedChar";
}
// ------------------------------------------------------
/// customize document's file attributes
- (nullable NSDictionary<NSString *, id> *)fileAttributesToWriteToURL:(nonnull NSURL *)url ofType:(nonnull NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation originalContentsURL:(nullable NSURL *)absoluteOriginalContentsURL error:(NSError * _Nullable __autoreleasing *)outError
// ------------------------------------------------------
{
NSMutableDictionary<NSString *, id> *attributes = [[super fileAttributesToWriteToURL:url ofType:typeName forSaveOperation:saveOperation originalContentsURL:absoluteOriginalContentsURL error:outError] ?: @{} mutableCopy];
// give the execute permission if user requested
if ([self isExecutable] && saveOperation != NSAutosaveElsewhereOperation) {
NSUInteger permissions = [attributes filePosixPermissions];
if (permissions == 0) {
if (absoluteOriginalContentsURL) { // read from old one if not exists
permissions = [[[NSFileManager defaultManager] attributesOfItemAtPath:[absoluteOriginalContentsURL path] error:outError] filePosixPermissions];
} else {
permissions = 0644; // ???: Is the default permission really always 644?
}
}
attributes[NSFilePosixPermissions] = @(permissions | S_IXUSR);
}
return [attributes copy];
}
// ------------------------------------------------------
/// ()
- (BOOL)shouldRunSavePanelWithAccessoryView
@ -455,6 +482,12 @@ NSString *_Nonnull const CEIncompatibleConvertedCharKey = @"convertedChar";
[savePanel setExtensionHidden:NO];
[savePanel setCanSelectHiddenExtension:NO];
// set accessory view
if (![self savePanelAccessoryView]) {
[[NSBundle mainBundle] loadNibNamed:@"SaveDocumentAccessory" owner:self topLevelObjects:nil];
}
[savePanel setAccessoryView:[self savePanelAccessoryView]];
// append file extension as a part of the file name
// -> NSSaveAsOperation will remove the current file extension from file name in the nameField
// as we set nil to `setAllowedFileTypes:` just above.

View File

@ -0,0 +1,29 @@
/*
SaveDocumentAccessory.strings (German)
CotEditor
http://coteditor.com
Created by 1024jp on 2016-03-06.
------------------------------------------------------------------------------
© 2016 CotEditor Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* Class = "NSButtonCell"; title = "Give execute permission"; ObjectID = "KjO-BV-esE"; */
"KjO-BV-esE.title" = "Ausführungsrecht geben";

View File

@ -0,0 +1,29 @@
/*
SaveDocumentAccessory.strings (Japanese)
CotEditor
http://coteditor.com
Created by 1024jp on 2016-03-06.
------------------------------------------------------------------------------
© 2016 CotEditor Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* Class = "NSButtonCell"; title = "Give execute permission"; ObjectID = "KjO-BV-esE"; */
"KjO-BV-esE.title" = "実行権を付与";

View File

@ -0,0 +1,30 @@
/*
SaveDocumentAccessory.strings (Simplified Chinese)
CotEditor
http://coteditor.com
Created by 1024jp on 2016-03-06.
Localized by onevcat
------------------------------------------------------------------------------
© 2016 CotEditor Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* Class = "NSButtonCell"; title = "Give execute permission"; ObjectID = "KjO-BV-esE"; */
"KjO-BV-esE.title" = "Give execute permission"; // FIXME: added