// PSF sets the current directory and location to the script directory. // This is often useful and consistent with invoking from panels. // NOTE: ISE [F5] does not. public static void InvokeScriptBeingEdited(IEditor editor) { // editor if (editor == null) { editor = A.Psf.Editor(); } // commit editor.Save(); // sync the directory and location to the script directory // maybe it is questionable but it is very handy too often string dir0, dir1; // save/set the directory, allow failures (e.g. a long path) // note: GetDirectoryName fails on a long path, too try { dir1 = Path.GetDirectoryName(editor.FileName); dir0 = Environment.CurrentDirectory; Environment.CurrentDirectory = dir1; } catch (PathTooLongException) { // PowerShell is not able to invoke this script anyway, almost for sure Far.Api.Message("The script path is too long.\rInvoking is not supported."); return; } try { Far.Api.UI.WindowTitle = "Running..."; // push/set the location; let's ignore issues A.Psf.Engine.SessionState.Path.PushCurrentLocation(null); A.Psf.Engine.SessionState.Path.SetLocation(Kit.EscapeWildcard(dir1)); // invoke the script A.Psf.Act("& '" + editor.FileName.Replace("'", "''") + "'", null, false); Far.Api.UI.WindowTitle = "Done " + DateTime.Now; } catch { Far.Api.UI.WindowTitle = "Failed"; throw; } finally { // restore the directory first Environment.CurrentDirectory = dir0; // then pop the location, it may fail perhaps A.Psf.Engine.SessionState.Path.PopLocation(null); } }
private void DoExplored(ItemExplorer explorer) { var info1 = explorer == null ? null : explorer.Info(); var info2 = Explorer.Info(); // fixed drive? if (Drive.Length > 0 && !Kit.Equals(Drive, info2.DriveName)) { return; } // customise if not yet if (Drive.Length == 0 && (explorer == null || info1.Provider.ImplementingType != info2.Provider.ImplementingType)) { if (string.IsNullOrEmpty(Drive)) { Columns = null; ExcludeMemberPattern = null; System.Collections.IDictionary options = A.Psf.Providers[info2.Provider.Name] as System.Collections.IDictionary; if (options != null) { try { Converter.SetProperties(this, options, true); } catch (ArgumentException ex) { throw new InvalidDataException("Invalid settings for '" + info2.Provider.Name + "' provider: " + ex.Message); } } } } // Set-Location, the core remembers it for the drive, this is handy A.Psf.Engine.SessionState.Path.SetLocation(Kit.EscapeWildcard(Explorer.Location)); //! path is used for Set-Location on Invoking() Title = "Items: " + Explorer.Location; CurrentLocation = Explorer.Location; //???? if (info2.Provider.ImplementingType == typeof(FileSystemProvider)) { UseSortGroups = true; Highlighting = PanelHighlighting.Full; // _090929_061740 Before Far 2.0.1145 we used to sync the current directory to // the PS location. Now it is not needed because Far does not do that any more. } else { UseSortGroups = false; Highlighting = PanelHighlighting.Default; } }
/// public PathInfoEx(string path) { var core = A.Psf.Engine.SessionState.Path; if (string.IsNullOrEmpty(path) || path == ".") { _PathInfo = core.CurrentLocation; } else { // 3 times faster than push/set/pop location; NB: it is slow anyway _PathInfo = core.GetResolvedPSPathFromPSPath(Kit.EscapeWildcard(path))[0]; } }
/// <inheritdoc/> public override void DoRenameFile(RenameFileEventArgs args) { if (args == null) { return; } if (!(args.Parameter is string newName)) { throw new InvalidOperationException(Res.ParameterString); } // workaround; Rename-Item has no -LiteralPath; e.g. z`z[z.txt is a big problem string src = Kit.EscapeWildcard(My.PathEx.Combine(Location, args.File.Name)); A.Psf.Engine.InvokeProvider.Item.Rename(src, newName); }
/// <inheritdoc/> public override void AcceptFiles(AcceptFilesEventArgs args) { if (args == null) { return; } // that source var that = args.Explorer as PropertyExplorer; if (that == null) { if (args.UI) { A.Message(Res.UnknownFileSource); } args.Result = JobResult.Ignore; return; } // names List <string> names = A.FileNameList(args.Files); //! gotchas in {Copy|Move}-ItemProperty: //! *) -Name takes a single string only? (help: yes (copy), no (move) - odd!) //! *) Names can't be pipelined (help says they can) //! so, use provider directly (no confirmation) string source = Kit.EscapeWildcard(that.ItemPath); string target = Kit.EscapeWildcard(this.ItemPath); if (args.Move) { foreach (string name in names) { A.Psf.Engine.InvokeProvider.Property.Move(source, name, target, name); } } else { foreach (string name in names) { A.Psf.Engine.InvokeProvider.Property.Copy(source, name, target, name); } } }
/// <inheritdoc/> public override void CloneFile(CloneFileEventArgs args) { if (args == null) { return; } if (!(args.Parameter is string newName)) { throw new InvalidOperationException(Res.ParameterString); } string src = Kit.EscapeWildcard(ItemPath); A.Psf.Engine.InvokeProvider.Property.Copy(src, args.File.Name, src, newName); args.PostName = newName; }
/// <inheritdoc/> public override void DoCloneFile(CloneFileEventArgs args) { if (args == null) { return; } if (!(args.Parameter is string newName)) { throw new InvalidOperationException(Res.ParameterString); } string source = Kit.EscapeWildcard(My.PathEx.Combine(Location, args.File.Name)); string target = My.PathEx.Combine(Location, newName); A.Psf.Engine.InvokeProvider.Item.Copy(source, target, false, CopyContainers.CopyTargetContainer); args.PostName = newName; }
/// <summary> /// Sync provider location and current directory with Far state. /// </summary> /// <remarks> /// Returned system path (if not null) must be restored by a called. /// </remarks> internal string SyncPaths() { // don't on running if (IsRunning) { return(null); } // don't on no panels mode IPanel panel = Far.Api.Panel; if (panel == null) { return(null); } // at first get both paths: for the current system directory and provider location string directory = Far.Api.CurrentDirectory; string location = null; if (panel.IsPlugin) { Panel plugin = panel as Panel; if (plugin != null) { var itemPanel = plugin as ItemPanel; if (itemPanel != null) { location = itemPanel.Explorer.Location; } else { FolderTree folderTree = plugin as FolderTree; if (folderTree != null) { location = panel.CurrentDirectory; if (location == "*") //_130117_234326 { location = directory; } } } } } // to set yet unknown location to the directory if (location == null) { location = directory; } // set the current provider location; let's do it first, in case of failure // we can skip directory setting/restoring in cases when they are the same. bool okLocation = true; try { //! Parameter is wildcard. Test: enter into a container "[]" and invoke a command. Engine.SessionState.Path.SetLocation(Kit.EscapeWildcard(location)); // drop failure info _failedInvokingLocationNew = null; _failedInvokingLocationOld = null; } catch { okLocation = false; // get the current string currentLocation = Engine.SessionState.Path.CurrentLocation.Path; // ask a user if he has not told to ignore this pair if (location != _failedInvokingLocationNew || currentLocation != _failedInvokingLocationOld) { string message = string.Format(null, @" Cannot set the current location to {0} Continue with this current location? {1} ", location, currentLocation); switch (Far.Api.Message(message, Res.Me, MessageOptions.GuiOnMacro | MessageOptions.AbortRetryIgnore | MessageOptions.Warning | MessageOptions.LeftAligned)) { case 1: break; case 2: _failedInvokingLocationNew = location; _failedInvokingLocationOld = currentLocation; break; default: if (Far.Api.MacroState != MacroState.None) { Far.Api.UI.Break(); } throw; } } } // do not try failed if (!okLocation && location == directory) { return(null); } // get the current directory to be restored by a caller string currentDirectory = Directory.GetCurrentDirectory(); // set the current directory to the active path to avoid confusions [_090929_061740] try { // try to set Directory.SetCurrentDirectory(directory); // drop failure info _failedInvokingDirectoryNew = null; _failedInvokingDirectoryOld = null; } catch { // ask a user if he has not told to ignore this pair if (directory != _failedInvokingDirectoryNew || currentDirectory != _failedInvokingDirectoryOld) { string message = string.Format(null, @" Cannot set the current directory to {0} Continue with this current directory? {1} ", directory, currentDirectory); switch (Far.Api.Message(message, Res.Me, MessageOptions.GuiOnMacro | MessageOptions.AbortRetryIgnore | MessageOptions.Warning | MessageOptions.LeftAligned)) { case 1: currentDirectory = null; break; case 2: currentDirectory = null; _failedInvokingDirectoryNew = directory; _failedInvokingDirectoryOld = currentDirectory; break; default: if (Far.Api.MacroState != MacroState.None) { Far.Api.UI.Break(); } throw; } } } // to be restored by a caller return(currentDirectory); }
/// <inheritdoc/> public override IEnumerable <FarFile> GetFiles(GetFilesEventArgs args) { var result = new List <FarFile>(); if (args == null) { return(result); } try { //! get properties // - Using -LiteralPath is a problem, e.g. Registry: returns nothing. // - Script is used for PS conversion of property values to string. // - Script has to ignore a property with empty name (if any, can be in Registry). // - If PS* included then they can't be found by `gp <path> <name>`; // so, don't add, they are noisy anyway (even if marked system or hidden). // get property bag 090409 Collection <PSObject> bag = A.Psf.Engine.InvokeProvider.Property.Get(Kit.EscapeWildcard(ItemPath), null); // filter var filter = new List <string>(5); filter.Add("PSChildName"); filter.Add("PSDrive"); filter.Add("PSParentPath"); filter.Add("PSPath"); filter.Add("PSProvider"); // add foreach (PSObject o in bag) { foreach (PSPropertyInfo pi in o.Properties) { // skip empty ?? still needed? string name = pi.Name; if (string.IsNullOrEmpty(name)) { continue; } // filter and shrink filter int i = filter.IndexOf(name); if (i >= 0) { filter.RemoveAt(i); continue; } // create file SetFile file = new SetFile() { Name = name, IsReadOnly = !pi.IsSettable, Data = pi, // set its value Description = Converter.FormatValue(pi.Value, Settings.Default.FormatEnumerationLimit) }; // add result.Add(file); } } } catch (RuntimeException error) { if (args.UI) { A.Message(error.Message); } } return(result); }
/// <inheritdoc/> public override void DeleteFiles(DeleteFilesEventArgs args) { if (args == null) { return; } // to ask bool confirm = args.UI && 0 != (long)Far.Api.GetSetting(FarSetting.Confirmations, "Delete"); // names to be deleted List <string> names = A.FileNameList(args.Files); //! Registry: workaround: (default) if (Provider.ImplementingType == typeof(RegistryProvider)) { for (int i = names.Count; --i >= 0;) { if (Kit.Equals(names[i], "(default)")) { // remove or not if (!confirm || 0 == Far.Api.Message("Delete the (default) property", Res.Delete, MessageOptions.YesNo)) { A.Psf.Engine.InvokeProvider.Property.Remove(Kit.EscapeWildcard(ItemPath), string.Empty); } // remove from the list in any case names.RemoveAt(i); break; } } // done? if (names.Count == 0) { return; } } using (var ps = A.Psf.NewPowerShell()) { ps.AddCommand("Remove-ItemProperty") .AddParameter("LiteralPath", ItemPath) .AddParameter(Word.Name, names) .AddParameter(Prm.Force) .AddParameter(Prm.ErrorAction, ActionPreference.Continue); if (confirm) { ps.AddParameter(Prm.Confirm); } ps.Invoke(); // ?? V2 CTP3 bug: Registry: Remove-ItemProperty -Confirm fails on 'No': // Remove-ItemProperty : Property X does not exist at path HKEY_CURRENT_USER\Y // There is no workaround added yet. Submitted: MS Connect #484664. if (ps.Streams.Error.Count > 0) { args.Result = JobResult.Incomplete; if (args.UI) { A.ShowError(ps); } } } }