/// <summary> /// Opens a file. /// </summary> /// <param name="file">The file to open.</param> /// <remarks> /// The base method calls Invoke-Item for <see cref="FileSystemInfo"/> files. /// </remarks> public virtual void OpenFile(FarFile file) { if (file == null) { throw new ArgumentNullException("file"); } if (file.Data == null) { return; } //! use try, e.g. Invoke-Item throws exception with any error action (PS bug?) try { // case: file system FileSystemInfo fi = Cast <FileSystemInfo> .From(file.Data); if (fi != null) { A.InvokeCode("Invoke-Item -LiteralPath $args[0] -ErrorAction Stop", fi.FullName); return; } } catch (RuntimeException ex) { A.Msg(ex); } }
/// <inheritdoc/> public override void GetContent(GetContentEventArgs args) { if (args == null) { return; } // info PSPropertyInfo pi = Cast <PSPropertyInfo> .From(args.File.Data); if (pi == null) { args.Result = JobResult.Ignore; return; } // text args.UseText = Converter.InfoToText(pi); if (args.UseText == null) { args.Result = JobResult.Ignore; return; } args.CanSet = pi.IsSettable; }
// Inserts steps at void InsertRange(int index, IEnumerable steps) { // state State = StepperState.Parsing; // steps foreach (object step in steps) { object insert = null; ScriptBlock block = Cast <ScriptBlock> .From(step); if (block != null) { insert = block; } else { string macro = Cast <string> .From(step); if (macro != null) { insert = macro; } else { Throw("Invalid step: " + TypeName(step)); } } _steps.Insert(index, insert); ++index; } }
internal void AddObjects(object values) { if (values == null) { return; } var added = AddedValues; IEnumerable enumerable = Cast <IEnumerable> .From(values); if (enumerable == null || enumerable is string) { added.Add(PSObject.AsPSObject(values)); } else { int maximumFileCount = Settings.Default.MaximumPanelFileCount; int fileCount = 0; foreach (object value in enumerable) { if (value == null) { continue; } // ask to cancel if (fileCount >= maximumFileCount && maximumFileCount > 0) { int res = ShowTooManyFiles(maximumFileCount, enumerable); // abort, show what we have got if (res == 0) { break; } if (res == 1) { // retry with a larger number maximumFileCount *= 2; } else { // ignore the limit maximumFileCount = 0; } } // add added.Add(PSObject.AsPSObject(value)); ++fileCount; } } }
static string TECompletionText(object value) { var t = Cast <Hashtable> .From(value); //! remote gets PSObject if (t == null) { return(value.ToString()); } return(t[CompletionText].ToString()); }
/// <summary> /// Puts a value into the command line or opens a lookup panel or member panel. /// </summary> /// <param name="file">The file to process.</param> public override void OpenFile(FarFile file) { if (file == null) { throw new ArgumentNullException("file"); } PSPropertyInfo pi = file.Data as PSPropertyInfo; // e.g. visible mode: sender is MemberDefinition if (pi == null) { return; } // lookup opener? if (_LookupOpeners != null) { ScriptHandler <OpenFileEventArgs> handler; if (_LookupOpeners.TryGetValue(file.Name, out handler)) { handler.Invoke(this, new OpenFileEventArgs(file)); return; } } // case: can show value in the command line string s = Converter.InfoToLine(pi); if (s != null) { // set command line ILine cl = Far.Api.CommandLine; cl.Text = "=" + s; cl.SelectText(1, s.Length + 1); return; } // case: enumerable IEnumerable ie = Cast <IEnumerable> .From(pi.Value); if (ie != null) { ObjectPanel op = new ObjectPanel(); op.AddObjects(ie); op.OpenChild(this); return; } // open members OpenFileMembers(file); }
/// <inheritdoc/> public override void SetText(SetTextEventArgs args) { if (args == null) { return; } PSPropertyInfo pi = Cast <PSPropertyInfo> .From(args.File.Data); if (pi == null) { args.Result = JobResult.Ignore; } else { A.SetPropertyFromTextUI(Value, pi, args.Text.TrimEnd()); } }
/// <summary> /// Creates a lookup handler designed only for <see cref="DataRow"/>. /// </summary> /// <param name="namePairs">Destination and source field name pairs.</param> /// <returns>Lookup handler to assigned to <see cref="AnyPanel.Lookup"/>.</returns> /// <remarks> /// This panel <see cref="Value"/> and lookup panel items should be <see cref="DataRow"/> objects, /// e.g. this panel shows members of a row from parent <see cref="DataPanel"/> /// and a lookup panel is also <see cref="DataPanel"/>. /// <para> /// The returned handler copies data from the source (lookup) row to the destination row using /// destination and source field name pairs, e.g.: <c>dst1, src1 [, dst2, src2 [, ...]]</c>. /// Example script: <c>Test-Panel-DbNotes-.ps1</c>. /// </para> /// </remarks> public EventHandler <OpenFileEventArgs> CreateDataLookup(string[] namePairs) { if (Cast <DataRow> .From(Target) == null) { throw new InvalidOperationException("Data lookup is designed only for data row objects."); } if (namePairs == null || namePairs.Length == 0) { throw new ArgumentException("'namePairs' must not be null or empty."); } if (namePairs.Length % 2 != 0) { throw new ArgumentException("'namePairs' must contain even number of items."); } return((new DataLookup(namePairs)).Invoke); }
/// <summary> /// Writes invocation errors. /// </summary> public static void WriteErrors(TextWriter writer, IEnumerable errors) { if (errors == null) { return; } foreach (object error in errors) { writer.WriteLine("ERROR:"); writer.WriteLine(error.ToString()); ErrorRecord asErrorRecord = Cast <ErrorRecord> .From(error); if (asErrorRecord != null && asErrorRecord.InvocationInfo != null) { writer.WriteLine(Kit.PositionMessage(asErrorRecord.InvocationInfo.PositionMessage)); } } }
/// <inheritdoc/> public override Explorer DoOpenFile(OpenFileEventArgs args) { if (args == null) { return(null); } object data = args.File.Data; PSObject psData = PSObject.AsPSObject(data); var type = psData.BaseObject.GetType(); // replace dictionary entry with its value if it is complex if (type == typeof(DictionaryEntry)) { var value = ((DictionaryEntry)psData.BaseObject).Value; if (value != null && !Converter.IsLinearType(value.GetType())) { data = value; psData = PSObject.AsPSObject(value); } } // replace key/value pair with its value if it is complex var typeName = type.FullName; if (typeName.StartsWith("System.Collections.Generic.KeyValuePair`", StringComparison.OrdinalIgnoreCase)) { var value = psData.Properties["Value"].Value; if (value != null && !Converter.IsLinearType(value.GetType())) { data = value; psData = PSObject.AsPSObject(value); } } // case: linear type: ignore, it is useless to open if (Converter.IsLinearType(type)) { args.Result = JobResult.Ignore; return(null); } // case: enumerable (string is excluded by linear type case) IEnumerable asIEnumerable = Cast <IEnumerable> .From(data); if (asIEnumerable != null) { var explorer = new ObjectExplorer(); explorer.AddObjects(asIEnumerable); return(explorer); } // case: group PSPropertyInfo pi = psData.Properties["Group"]; if (pi != null && pi.Value is IEnumerable && !(pi.Value is string)) { var explorer = new ObjectExplorer(); explorer.AddObjects(pi.Value); return(explorer); } // case: WMI if (typeName == "System.Management.ManagementClass") { pi = psData.Properties[Word.Name]; if (pi != null && pi.Value != null) { var values = A.InvokeCode("Get-WmiObject -Class $args[0] -ErrorAction SilentlyContinue", pi.Value.ToString()); var explorer = new ObjectExplorer(); explorer.AddObjects(values); return(explorer); } } // open members return(new MemberExplorer(data)); }
public static void ExpandCode(ILine editLine, Runspace runspace) { InitTabExpansion(); // hot line if (editLine == null) { editLine = Far.Api.Line; if (editLine == null) { A.Message("There is no current editor line."); return; } } int lineOffset = 0; string inputScript; int cursorColumn; var prefix = string.Empty; IEditor editor = null; Interactive console; InteractiveArea area; // script? if (A.Psf.PSVersion.Major > 2 && editLine.WindowKind == WindowKind.Editor && My.PathEx.IsPSFile((editor = Far.Api.Editor).FileName)) { int lineIndex = editor.Caret.Y; int lastIndex = editor.Count - 1; // previous text var sb = new StringBuilder(); for (int i = 0; i < lineIndex; ++i) { sb.AppendLine(editor[i].Text); } // current line lineOffset = sb.Length; cursorColumn = lineOffset + editLine.Caret; // remaining text for (int i = lineIndex; i < lastIndex; ++i) { sb.AppendLine(editor[i].Text); } sb.Append(editor[lastIndex]); // whole text inputScript = sb.ToString(); } // area? else if (editor != null && (console = editor.Host as Interactive) != null && (area = console.CommandArea()) != null) { int lineIndex = area.Caret.Y; int lastIndex = area.LastLineIndex; // previous text var sb = new StringBuilder(); for (int i = area.FirstLineIndex; i < lineIndex; ++i) { sb.AppendLine(editor[i].Text); } // current line lineOffset = sb.Length; cursorColumn = lineOffset + area.Caret.X; // remaining text for (int i = lineIndex; i < lastIndex; ++i) { sb.AppendLine(editor[i].Text); } sb.Append(editor[lastIndex]); // whole text inputScript = sb.ToString(); } // line else { // original line inputScript = editLine.Text; cursorColumn = editLine.Caret; // process prefix, used to be just for panels but it is needed in dialogs, too Entry.SplitCommandWithPrefix(ref inputScript, out prefix); // correct caret cursorColumn -= prefix.Length; if (cursorColumn < 0) { return; } } // skip empty (also avoid errors) if (inputScript.Length == 0) { return; } // invoke try { // call TabExpansion Hashtable result; using (var ps = runspace == null ? A.Psf.NewPowerShell() : PowerShell.Create()) { if (runspace != null) { ps.Runspace = runspace; } result = (Hashtable)ps.AddScript(_callTabExpansion, true).AddArgument(inputScript).AddArgument(cursorColumn).Invoke()[0].BaseObject; } // results var words = Cast <IList> .From(result["CompletionMatches"]); //! remote gets PSObject int replacementIndex = (int)result["ReplacementIndex"]; int replacementLength = (int)result["ReplacementLength"]; replacementIndex -= lineOffset; if (replacementIndex < 0 || replacementLength < 0) { return; } // variables from the current editor if (editLine.WindowKind == WindowKind.Editor) { // replaced text var lastWord = inputScript.Substring(lineOffset + replacementIndex, replacementLength); //! as TabExpansion.ps1 but ends with \$(\w*)$ var matchVar = Regex.Match(lastWord, @"^(.*[!;\(\{\|""'']*)\$(global:|script:|private:)?(\w*)$", RegexOptions.IgnoreCase); if (matchVar.Success) { var start = matchVar.Groups[1].Value; var scope = matchVar.Groups[2].Value; var re = new Regex(@"\$(global:|script:|private:)?(" + scope + matchVar.Groups[3].Value + @"\w+:?)", RegexOptions.IgnoreCase); var variables = new HashSet <string>(StringComparer.OrdinalIgnoreCase); foreach (var line1 in Far.Api.Editor.Lines) { foreach (Match m in re.Matches(line1.Text)) { var all = m.Value; if (all[all.Length - 1] != ':') { variables.Add(start + all); if (scope.Length == 0 && m.Groups[1].Value.Length > 0) { variables.Add(start + "$" + m.Groups[2].Value); } } } } // union lists foreach (var x in words) { if (x != null) { variables.Add(TECompletionText(x)); } } // final sorted list words = variables.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList(); } } // expand ExpandText(editLine, replacementIndex + prefix.Length, replacementLength, words); } catch (RuntimeException) { } }
static string TypeName(object value) { var it = Cast <object> .From(value); return(it == null ? "null" : it.GetType().FullName); }
/// <summary> /// Invokes the next step in the step sequence. /// </summary> public bool MoveNext() { AssumeCanStep(); _current = null; try { // this is running _RunningInstance = this; // done with steps? if (_StepIndex >= _steps.Count) { // event UnitCompleted?.Invoke(this, null); // remove user data if (_Data != null) { _Data.Clear(); } // done with units? if (++_UnitIndex >= _units.Count) { // state State = StepperState.Completed; _continuation?.Invoke(null); return(false); } // state State = StepperState.Loading; // reset steps _steps.Clear(); _StepIndex = 0; // get steps from the unit Collection <PSObject> steps; var path = _units[_UnitIndex]; using (var ps = A.Psf.NewPowerShell()) steps = ps.AddCommand(path).Invoke(); // no steps? 'continue' if (steps.Count == 0) { return(true); } // add steps and start InsertRange(0, steps); } // state State = StepperState.Stepping; // counter ++_StepCount; // next step object object it = _steps[_StepIndex]; if (it == null) { Throw("Step is null."); } // show if (Ask) { string text = it.ToString(); string title = "Step " + (_StepIndex + 1) + "/" + _steps.Count; if (_units.Count > 0) { if (_UnitIndex >= 0) { text = _units[_UnitIndex].ToString().Trim() + "\r" + text; } title += " Unit " + (_UnitIndex + 1) + "/" + _units.Count; } var args = new MessageArgs() { Text = text, Caption = title, Options = MessageOptions.LeftAligned, Buttons = new string[] { "Step", "Continue", "Cancel" }, Position = new Point(int.MaxValue, 1) }; switch (Far.Api.Message(args)) { case 0: break; case 1: Ask = false; break; default: return(false); } } // invoke the next step ScriptBlock block = Cast <ScriptBlock> .From(it); if (block != null) { // invoke the step script Collection <PSObject> result = null; try { result = block.Invoke(); } catch (RuntimeException ex) { Throw(block, "Step failed: " + ex.Message, ex); } // extra script, normally starts modal UI ScriptBlock script; if (result.Count == 1 && null != (script = result[0].BaseObject as ScriptBlock)) { ++_StepIndex; _current = new Action(delegate { script.Invoke(); }); return(true); } // unexpected output if (result.Count != 0) { Throw(block, string.Format(null, "Unexpected step output: {0} item(s): [{1}]...", result.Count, TypeName(result[0])), null); } } else { // post macro _current = it; } // post ++_StepIndex; return(true); } catch (Exception error) { _Error = error; State = StepperState.Failed; if (_continuation == null) { throw; } _continuation(error); return(false); } finally { // step is over _RunningInstance = null; } }