Exemple #1
0
        /// <summary>
        /// Try and convert the provided KeyInput value into OleCommandData.  This conversion is meant
        /// to simulate the standard converison of key input into OLE information in Visual Studio. This
        /// means we need to reproduce all of the behavior including not converting textual input
        /// here (unless it maps to a command).  Textual input typcially gets routed through WPF and
        /// is routed to IOleCommandTarget in the default handler
        /// </summary>
        private bool TryConvertToOleCommandData(KeyInput keyInput, out OleCommandData oleCommandData)
        {
            if (keyInput.RawChar.IsSome())
            {
                if (Char.IsLetterOrDigit(keyInput.Char))
                {
                    oleCommandData = OleCommandData.Empty;
                    return(false);
                }
            }

            return(OleCommandUtil.TryConvert(keyInput, SimulateStandardKeyMappings, out oleCommandData));
        }
Exemple #2
0
            private void SendTypeChar(char c)
            {
                var oleCommandData = OleCommandData.Allocate(c);

                try
                {
                    var commandGuid = VSConstants.VSStd2K;
                    OleCommandTarget.Exec(ref commandGuid, oleCommandData.CommandId, oleCommandData.CommandExecOpt, oleCommandData.VariantIn, oleCommandData.VariantOut);
                }
                finally
                {
                    OleCommandData.Release(ref oleCommandData);
                }
            }
Exemple #3
0
        /// <summary>
        /// Actually run the QueryStatus command and report the result
        /// </summary>
        private bool RunQueryStatusCore(OleCommandData oleCommandData)
        {
            var hr = _commandTarget.QueryStatus(oleCommandData, out OLECMD command);

            if (!ErrorHandler.Succeeded(hr))
            {
                return(false);
            }

            // TODO: Visual Studio has slightly different behavior here IIRC.  I believe it will
            // only cache if it's at least supported.  Need to check on that
            var result = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);

            return(result == (result & command.cmdf));
        }
Exemple #4
0
        /// <summary>
        /// Run the KeyInput value through Exec
        /// </summary>
        private void RunExec(KeyInput keyInput)
        {
            OleCommandData data;
            Guid           commandGroup;

            Assert.IsTrue(OleCommandUtil.TryConvert(keyInput, out commandGroup, out data));
            try
            {
                _target.Exec(ref commandGroup, data.CommandId, data.CommandExecOpt, data.VariantIn, data.VariantOut);
            }
            finally
            {
                OleCommandData.Release(ref data);
            }
        }
Exemple #5
0
        /// <summary>
        /// Actually run the QueryStatus command and report the result
        /// </summary>
        private bool RunQueryStatusCore(Guid commandGroup, OleCommandData oleCommandData)
        {
            var commands = new OLECMD[1];

            commands[0].cmdID = oleCommandData.CommandId;
            var hr = _commandTarget.QueryStatus(ref commandGroup, 1, commands, oleCommandData.VariantIn);

            if (!ErrorHandler.Succeeded(hr))
            {
                return(false);
            }

            // TODO: Visual Studio has slightly different behavior here IIRC.  I believe it will
            // only cache if it's at least supported.  Need to check on that
            var result = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);

            return(result == (result & commands[0].cmdf));
        }
Exemple #6
0
        /// <summary>
        /// Exec the operation in question
        /// </summary>
        private bool RunExecCore(OleCommandData oleCommandData)
        {
            var variantOut = IntPtr.Zero;

            try
            {
                var hr = _commandTarget.Exec(oleCommandData);
                return(ErrorHandler.Succeeded(hr));
            }
            finally
            {
                if (variantOut != IntPtr.Zero)
                {
                    NativeMethods.VariantClear(variantOut);
                    Marshal.FreeCoTaskMem(variantOut);
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Run QueryStatus and return whether or not it should be enabled
        /// </summary>
        private bool RunQueryStatus(OleCommandData oleCommandData)
        {
            // First check and see if this represents a cached call to QueryStatus.  Visual Studio
            // will cache the result of QueryStatus for most types of commands that Vim will be
            // interested in handling.
            //
            // I haven't figured out the exact rules by which this cache is reset yet but it appears
            // to be when a QueryStatus / Exec pair executes succesfully or when Visual Studio loses
            // and gains focus again.  These may be related

            var commandId = oleCommandData.CommandId;

            if (_cachedQueryStatusMap.TryGetValue(commandId, out bool result))
            {
                return(result);
            }

            result = RunQueryStatusCore(oleCommandData);
            _cachedQueryStatusMap[commandId] = result;
            return(result);
        }
Exemple #8
0
        /// <summary>
        /// Run the KeyInput value through QueryStatus.  Returns true if the QueryStatus call
        /// indicated the command was supported
        /// </summary>
        private bool RunQueryStatus(KeyInput keyInput)
        {
            OleCommandData data;
            Guid           commandGroup;

            Assert.IsTrue(OleCommandUtil.TryConvert(keyInput, out commandGroup, out data));
            try
            {
                var cmds = new OLECMD[1];
                cmds[0] = new OLECMD {
                    cmdID = data.CommandId
                };
                return
                    (ErrorHandler.Succeeded(_target.QueryStatus(ref commandGroup, 1, cmds, data.VariantIn)) &&
                     cmds[0].cmdf == (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED));
            }
            finally
            {
                OleCommandData.Release(ref data);
            }
        }
Exemple #9
0
        /// <summary>
        /// Actually run the QueryStatus command and report the result
        /// </summary>
        private bool RunQueryStatusCore(OleCommandData oleCommandData)
        {
            OLECMD command;
            var hr = _commandTarget.QueryStatus(oleCommandData, out command);
            if (!ErrorHandler.Succeeded(hr))
            {
                return false;
            }

            // TODO: Visual Studio has slightly different behavior here IIRC.  I believe it will
            // only cache if it's at least supported.  Need to check on that
            var result = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);
            return result == (result & command.cmdf);
        }
Exemple #10
0
        /// <summary>
        /// Run QueryStatus and return whether or not it should be enabled 
        /// </summary>
        private bool RunQueryStatus(OleCommandData oleCommandData)
        {
            // First check and see if this represents a cached call to QueryStatus.  Visual Studio
            // will cache the result of QueryStatus for most types of commands that Vim will be
            // interested in handling.
            //
            // I haven't figured out the exact rules by which this cache is reset yet but it appears
            // to be when a QueryStatus / Exec pair executes succesfully or when Visual Studio loses
            // and gains focus again.  These may be related

            bool result;
            var key = new CommandKey(oleCommandData.CommandGroup, oleCommandData.CommandId);
            if (_cachedQueryStatusMap.TryGetValue(key, out result))
            {
                return result;
            }

            result = RunQueryStatusCore(oleCommandData);
            _cachedQueryStatusMap[key] = result;
            return result;
        }
Exemple #11
0
 /// <summary>
 /// Exec the operation in question
 /// </summary>
 private bool RunExecCore(OleCommandData oleCommandData)
 {
     var variantOut = IntPtr.Zero;
     try
     {
         var hr = _commandTarget.Exec(oleCommandData);
         return ErrorHandler.Succeeded(hr);
     }
     finally
     {
         if (variantOut != IntPtr.Zero)
         {
             NativeMethods.VariantClear(variantOut);
             Marshal.FreeCoTaskMem(variantOut);
         }
     }
 }
Exemple #12
0
 /// <summary>
 /// Run the Exec operation.  Make sure to properly manage the QueryStatus cache
 /// </summary>
 private void RunExec(OleCommandData oleCommandData)
 {
     var result = RunExecCore(oleCommandData);
     if (result)
     {
         _cachedQueryStatusMap.Clear();
     }
 }
Exemple #13
0
        /// <summary>
        /// Try and convert the provided KeyInput value into OleCommandData.  This conversion is meant
        /// to simulate the standard converison of key input into OLE information in Visual Studio. This
        /// means we need to reproduce all of the behavior including not converting textual input
        /// here (unless it maps to a command).  Textual input typcially gets routed through WPF and 
        /// is routed to IOleCommandTarget in the default handler
        /// </summary>
        private bool TryConvertToOleCommandData(KeyInput keyInput, out OleCommandData oleCommandData)
        {
            if (keyInput.RawChar.IsSome())
            {
                if (Char.IsLetterOrDigit(keyInput.Char))
                {
                    oleCommandData = OleCommandData.Empty;
                    return false;
                }
            }

            return OleCommandUtil.TryConvert(keyInput, SimulateStandardKeyMappings, out oleCommandData);
        }
Exemple #14
0
        /// <summary>
        /// Actually run the QueryStatus command and report the result
        /// </summary>
        private bool RunQueryStatusCore(Guid commandGroup, OleCommandData oleCommandData)
        {
            var commands = new OLECMD[1];
            commands[0].cmdID = oleCommandData.CommandId;
            var hr = _commandTarget.QueryStatus(ref commandGroup, 1, commands, oleCommandData.VariantIn);
            if (!ErrorHandler.Succeeded(hr))
            {
                return false;
            }

            // TODO: Visual Studio has slightly different behavior here IIRC.  I believe it will
            // only cache if it's at least supported.  Need to check on that
            var result = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);
            return result == (result & commands[0].cmdf);
        }
Exemple #15
0
 /// <summary>
 /// Run the Exec operation.  Make sure to properly manage the QueryStatus cache
 /// </summary>
 private void RunExec(Guid commandGroup, OleCommandData oleCommandData)
 {
     var result = RunExecCore(commandGroup, oleCommandData);
     if (result)
     {
         _cachedQueryStatusMap.Clear();
     }
 }
        public void TryConvert_TextInputToOleCommandData()
        {
            var textView = EditorUtil.CreateTextView("");
            var buffer = EditorUtil.FactoryService.Vim.CreateVimBuffer(textView);
            buffer.SwitchMode(ModeKind.Insert, ModeArgument.None);
            foreach (var cur in KeyInputUtil.VimKeyInputList)
            {
                if (!buffer.InsertMode.IsDirectInsert(cur))
                {
                    continue;
                }

                var oleCommandData = new OleCommandData();
                try
                {
                    KeyInput converted;
                    Guid commandGroup;
                    Assert.IsTrue(OleCommandUtil.TryConvert(cur, out commandGroup, out oleCommandData));

                    // We lose fidelity on these keys because they both get written out as numbers
                    // at this point
                    if (VimKeyUtil.IsKeypadKey(cur.Key))
                    {
                        continue;
                    }
                    Assert.IsTrue(OleCommandUtil.TryConvert(commandGroup, oleCommandData, out converted));
                    Assert.AreEqual(converted, cur);
                }
                finally
                {
                    OleCommandData.Release(ref oleCommandData);
                }
            }
        }