diff --git a/src/CodeIndex.Server/Controllers/LuceneController.cs b/src/CodeIndex.Server/Controllers/LuceneController.cs index e89164d..2a10899 100644 --- a/src/CodeIndex.Server/Controllers/LuceneController.cs +++ b/src/CodeIndex.Server/Controllers/LuceneController.cs @@ -40,7 +40,7 @@ public FetchResult<IEnumerable<CodeSource>> GetCodeSources(string searchQuery, b { searchQuery.RequireNotNullOrEmpty(nameof(searchQuery)); - var showResultsValue = showResults.HasValue && showResults.Value <= 100 && showResults.Value > 0 ? showResults.Value : 100; + var showResultsValue = showResults.HasValue && showResults.Value <= 100 && showResults.Value > 0 ? showResults.Value : 1000; result = new FetchResult<IEnumerable<CodeSource>> { diff --git a/src/CodeIndex.VisualStudioExtension/CodeIndex.VisualStudioExtension.csproj b/src/CodeIndex.VisualStudioExtension/CodeIndex.VisualStudioExtension.csproj new file mode 100644 index 0000000..2052cd7 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/CodeIndex.VisualStudioExtension.csproj @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <MinimumVisualStudioVersion>16.0</MinimumVisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + <TargetFrameworkProfile /> + </PropertyGroup> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <ProjectGuid>{ED1D3026-8695-4B9B-9FA9-2D68E28EE850}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>CodeIndex.VisualStudioExtension</RootNamespace> + <AssemblyName>CodeIndex.VisualStudioExtension</AssemblyName> + <TargetFrameworkVersion>v4.8</TargetFrameworkVersion> + <GeneratePkgDefFile>true</GeneratePkgDefFile> + <UseCodebase>true</UseCodebase> + <IncludeAssemblyInVSIXContainer>true</IncludeAssemblyInVSIXContainer> + <IncludeDebugSymbolsInVSIXContainer>false</IncludeDebugSymbolsInVSIXContainer> + <IncludeDebugSymbolsInLocalVSIXDeployment>false</IncludeDebugSymbolsInLocalVSIXDeployment> + <CopyBuildOutputToOutputDirectory>true</CopyBuildOutputToOutputDirectory> + <CopyOutputSymbolsToOutputDirectory>true</CopyOutputSymbolsToOutputDirectory> + <StartAction>Program</StartAction> + <StartProgram Condition="'$(DevEnvDir)' != ''">$(DevEnvDir)devenv.exe</StartProgram> + <StartArguments>/rootsuffix Exp</StartArguments> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Compile Include="..\CodeIndex.Common\CodeSource.cs"> + <Link>Models\CodeSource.cs</Link> + </Compile> + <Compile Include="..\CodeIndex.Common\FetchResult.cs"> + <Link>Models\FetchResult.cs</Link> + </Compile> + <Compile Include="..\CodeIndex.Common\Status.cs"> + <Link>Models\Status.cs</Link> + </Compile> + <Compile Include="Controls\CodeIndexSearchControl.xaml.cs"> + <DependentUpon>CodeIndexSearchControl.xaml</DependentUpon> + </Compile> + <Compile Include="CodeIndexSearchWindow.cs" /> + <Compile Include="CodeIndexSearchWindowCommand.cs" /> + <Compile Include="CodeIndexSearchWindowControl.xaml.cs"> + <DependentUpon>CodeIndexSearchWindowControl.xaml</DependentUpon> + </Compile> + <Compile Include="Models\BaseViewModel.cs" /> + <Compile Include="Models\CodeIndexSearchViewModel.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="CodeIndex.VisualStudioExtensionPackage.cs" /> + <Compile Include="Properties\CodeIndexSettings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTimeSharedInput>True</DesignTimeSharedInput> + <DependentUpon>CodeIndexSettings.settings</DependentUpon> + </Compile> + <Compile Include="ProvideToolboxControlAttribute.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="app.config" /> + <None Include="Properties\CodeIndexSettings.settings"> + <Generator>SettingsSingleFileGenerator</Generator> + <LastGenOutput>CodeIndexSettings.Designer.cs</LastGenOutput> + </None> + <None Include="source.extension.vsixmanifest"> + <SubType>Designer</SubType> + </None> + </ItemGroup> + <ItemGroup> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="PresentationCore" /> + <Reference Include="PresentationFramework" /> + <Reference Include="PresentationFramework.Aero2" /> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="System.Design" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Web" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xaml" /> + <Reference Include="System.Xml" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="WindowsBase" /> + </ItemGroup> + <ItemGroup> + <PackageReference Include="Microsoft.AspNet.WebApi.Client"> + <Version>5.2.7</Version> + </PackageReference> + <PackageReference Include="Microsoft.VisualStudio.SDK" Version="16.0.204" ExcludeAssets="runtime" /> + <PackageReference Include="Microsoft.VSSDK.BuildTools" Version="16.6.2031"> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + <PrivateAssets>all</PrivateAssets> + </PackageReference> + </ItemGroup> + <ItemGroup> + <VSCTCompile Include="VisualStudioExtensionPackage.vsct"> + <ResourceName>Menus.ctmenu</ResourceName> + </VSCTCompile> + </ItemGroup> + <ItemGroup> + <Content Include="Resources\CodeIndexSearchWindowCommand.png" /> + </ItemGroup> + <ItemGroup> + <Page Include="Controls\CodeIndexSearchControl.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="CodeIndexSearchWindowControl.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Resources\Style.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + </ItemGroup> + <ItemGroup /> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project> \ No newline at end of file diff --git a/src/CodeIndex.VisualStudioExtension/CodeIndex.VisualStudioExtensionPackage.cs b/src/CodeIndex.VisualStudioExtension/CodeIndex.VisualStudioExtensionPackage.cs new file mode 100644 index 0000000..53f4c7b --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/CodeIndex.VisualStudioExtensionPackage.cs @@ -0,0 +1,56 @@ +using System; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft.VisualStudio.Shell; +using Task = System.Threading.Tasks.Task; + +namespace CodeIndex.VisualStudioExtension +{ + /// <summary> + /// This is the class that implements the package exposed by this assembly. + /// </summary> + /// <remarks> + /// <para> + /// The minimum requirement for a class to be considered a valid package for Visual Studio + /// is to implement the IVsPackage interface and register itself with the shell. + /// This package uses the helper classes defined inside the Managed Package Framework (MPF) + /// to do it: it derives from the Package class that provides the implementation of the + /// IVsPackage interface and uses the registration attributes defined in the framework to + /// register itself and its components with the shell. These attributes tell the pkgdef creation + /// utility what data to put into .pkgdef file. + /// </para> + /// <para> + /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file. + /// </para> + /// </remarks> + [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] + [Guid(PackageGuidString)] + [ProvideMenuResource("Menus.ctmenu", 1)] + [ProvideToolWindow(typeof(CodeIndex.VisualStudioExtension.CodeIndexSearchWindow))] + public sealed class VisualStudioExtensionPackage : AsyncPackage + { + /// <summary> + /// CodeIndex.VisualStudioExtensionPackage GUID string. + /// </summary> + public const string PackageGuidString = "1eaddb39-c1f2-42e2-807d-234d73e8ef2a"; + + #region Package Members + + /// <summary> + /// Initialization of the package; this method is called right after the package is sited, so this is the place + /// where you can put all the initialization code that rely on services provided by VisualStudio. + /// </summary> + /// <param name="cancellationToken">A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down.</param> + /// <param name="progress">A provider for progress updates.</param> + /// <returns>A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method.</returns> + protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress) + { + // When initialized asynchronously, the current thread may be a background thread at this point. + // Do any initialization that requires the UI thread after switching to the UI thread. + await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + await CodeIndex.VisualStudioExtension.CodeIndexSearchWindowCommand.InitializeAsync(this); + } + + #endregion + } +} diff --git a/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindow.cs b/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindow.cs new file mode 100644 index 0000000..edbd64d --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindow.cs @@ -0,0 +1,34 @@ +using System; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio.Shell; + +namespace CodeIndex.VisualStudioExtension +{ + /// <summary> + /// This class implements the tool window exposed by this package and hosts a user control. + /// </summary> + /// <remarks> + /// In Visual Studio tool windows are composed of a frame (implemented by the shell) and a pane, + /// usually implemented by the package implementer. + /// <para> + /// This class derives from the ToolWindowPane class provided from the MPF in order to use its + /// implementation of the IVsUIElementPane interface. + /// </para> + /// </remarks> + [Guid("6d5fde57-9331-4f68-8c3e-2945d8049f40")] + public class CodeIndexSearchWindow : ToolWindowPane + { + /// <summary> + /// Initializes a new instance of the <see cref="CodeIndexSearchWindow"/> class. + /// </summary> + public CodeIndexSearchWindow() : base(null) + { + this.Caption = "Code Index Search"; + + // This is the user control hosted by the tool window; Note that, even if this class implements IDisposable, + // we are not calling Dispose on this object. This is because ToolWindowPane calls Dispose on + // the object returned by the Content property. + this.Content = new CodeIndexSearchWindowControl(); + } + } +} diff --git a/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindowCommand.cs b/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindowCommand.cs new file mode 100644 index 0000000..9ddfb49 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindowCommand.cs @@ -0,0 +1,99 @@ +using System; +using System.ComponentModel.Design; +using System.Globalization; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Task = System.Threading.Tasks.Task; + +namespace CodeIndex.VisualStudioExtension +{ + /// <summary> + /// Command handler + /// </summary> + internal sealed class CodeIndexSearchWindowCommand + { + /// <summary> + /// Command ID. + /// </summary> + public const int CommandId = 4129; + + /// <summary> + /// Command menu group (command set GUID). + /// </summary> + public static readonly Guid CommandSet = new Guid("c025b4ef-e6ed-42b4-9c22-2d6835421d25"); + + /// <summary> + /// VS Package that provides this command, not null. + /// </summary> + private readonly AsyncPackage package; + + /// <summary> + /// Initializes a new instance of the <see cref="CodeIndexSearchWindowCommand"/> class. + /// Adds our command handlers for menu (commands must exist in the command table file) + /// </summary> + /// <param name="package">Owner package, not null.</param> + /// <param name="commandService">Command service to add command to, not null.</param> + private CodeIndexSearchWindowCommand(AsyncPackage package, OleMenuCommandService commandService) + { + this.package = package ?? throw new ArgumentNullException(nameof(package)); + commandService = commandService ?? throw new ArgumentNullException(nameof(commandService)); + + var menuCommandID = new CommandID(CommandSet, CommandId); + var menuItem = new MenuCommand(this.Execute, menuCommandID); + commandService.AddCommand(menuItem); + } + + /// <summary> + /// Gets the instance of the command. + /// </summary> + public static CodeIndexSearchWindowCommand Instance + { + get; + private set; + } + + /// <summary> + /// Gets the service provider from the owner package. + /// </summary> + private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider + { + get + { + return this.package; + } + } + + /// <summary> + /// Initializes the singleton instance of the command. + /// </summary> + /// <param name="package">Owner package, not null.</param> + public static async Task InitializeAsync(AsyncPackage package) + { + // Switch to the main thread - the call to AddCommand in CodeIndexSearchWindowCommand's constructor requires + // the UI thread. + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken); + + OleMenuCommandService commandService = await package.GetServiceAsync((typeof(IMenuCommandService))) as OleMenuCommandService; + Instance = new CodeIndexSearchWindowCommand(package, commandService); + } + + /// <summary> + /// Shows the tool window when the menu item is clicked. + /// </summary> + /// <param name="sender">The event sender.</param> + /// <param name="e">The event args.</param> + private void Execute(object sender, EventArgs e) + { + this.package.JoinableTaskFactory.RunAsync(async delegate + { + ToolWindowPane window = await this.package.ShowToolWindowAsync(typeof(CodeIndexSearchWindow), 0, true, this.package.DisposalToken); + if ((null == window) || (null == window.Frame)) + { + throw new NotSupportedException("Cannot create tool window"); + } + }); + } + } +} diff --git a/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindowControl.xaml b/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindowControl.xaml new file mode 100644 index 0000000..2936f7f --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindowControl.xaml @@ -0,0 +1,17 @@ +<UserControl x:Class="CodeIndex.VisualStudioExtension.CodeIndexSearchWindowControl" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:vsshell="clr-namespace:Microsoft.VisualStudio.Shell;assembly=Microsoft.VisualStudio.Shell.15.0" xmlns:visualstudioextension="clr-namespace:CodeIndex.VisualStudioExtension" + Background="{DynamicResource {x:Static vsshell:VsBrushes.WindowKey}}" + Foreground="{DynamicResource {x:Static vsshell:VsBrushes.WindowTextKey}}" + mc:Ignorable="d" + d:DesignHeight="225.889" d:DesignWidth="783.068" + Name="MyToolWindow"> + <Grid> + <DockPanel LastChildFill="True"> + <visualstudioextension:CodeIndexSearchControl x:Name="SearchControl"></visualstudioextension:CodeIndexSearchControl> + </DockPanel> + </Grid> +</UserControl> diff --git a/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindowControl.xaml.cs b/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindowControl.xaml.cs new file mode 100644 index 0000000..01cc3f8 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/CodeIndexSearchWindowControl.xaml.cs @@ -0,0 +1,20 @@ +using System.Windows.Controls; + +namespace CodeIndex.VisualStudioExtension +{ + /// <summary> + /// Interaction logic for CodeIndexSearchWindowControl. + /// </summary> + public partial class CodeIndexSearchWindowControl : UserControl + { + /// <summary> + /// Initializes a new instance of the <see cref="CodeIndexSearchWindowControl"/> class. + /// </summary> + public CodeIndexSearchWindowControl() + { + InitializeComponent(); + + SearchControl.DataContext = new CodeIndexSearchViewModel(); + } + } +} \ No newline at end of file diff --git a/src/CodeIndex.VisualStudioExtension/Controls/CodeIndexSearchControl.xaml b/src/CodeIndex.VisualStudioExtension/Controls/CodeIndexSearchControl.xaml new file mode 100644 index 0000000..d028be4 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/Controls/CodeIndexSearchControl.xaml @@ -0,0 +1,137 @@ +<UserControl x:Class="CodeIndex.VisualStudioExtension.CodeIndexSearchControl" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + mc:Ignorable="d" + d:DesignHeight="281.2" d:DesignWidth="987.2" Foreground="Black" Background="#FF2D2D30"> + <Grid> + <DockPanel LastChildFill="True" Margin="6"> + <WrapPanel HorizontalAlignment="Left" DockPanel.Dock="Top"> + <Label Content="Content:"/> + <TextBox Height="23" TextWrapping="Wrap" Text="{Binding Content, UpdateSourceTrigger=PropertyChanged}" Width="240" KeyDown="TextBox_KeyDown"/> + <Label Content="File Name:"/> + <TextBox Height="23" TextWrapping="Wrap" Text="{Binding FileName, UpdateSourceTrigger=PropertyChanged}" Width="120" KeyDown="TextBox_KeyDown"/> + <Label Content="File Extension:"/> + <TextBox Height="23" TextWrapping="Wrap" Text="{Binding FileExtension, UpdateSourceTrigger=PropertyChanged}" Width="120" KeyDown="TextBox_KeyDown"/> + <Label Content="File Location:"/> + <TextBox Height="23" TextWrapping="Wrap" Text="{Binding FileLocation, UpdateSourceTrigger=PropertyChanged}" Width="120" KeyDown="TextBox_KeyDown"/> + <Label Content="Show Results: "/> + <ComboBox SelectedValue="{Binding ShowResultsNumber}" ItemsSource="{Binding Options}" DisplayMemberPath="Name" SelectedValuePath="Value" Width="100" VerticalAlignment="Center"/> + <Button x:Name="SearchButton" Margin="10 0 0 0" Content="Search" Command="{Binding SearchIndexCommand}" Style="{DynamicResource InfoButton}"/> + <Button Margin="10 0 0 0" Content="Stop Search" Command="{Binding StopSearchCommand}" Style="{DynamicResource WarnButton}"/> + </WrapPanel> + <WrapPanel DockPanel.Dock="Top"> + <Label Content="Service Url:"/> + <TextBox Height="23" TextWrapping="NoWrap" Text="{Binding ServiceUrl}" Width="200"/> + <Label Content="Result Info:"/> + <ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="60"> + <Label Content="{Binding ResultInfo}" Foreground="Yellow"/> + </ScrollViewer> + </WrapPanel> + <DataGrid Background="#FF2D2D30" Margin="0 6 0 0" ItemsSource="{Binding SearchResult}" AutoGenerateColumns="True" IsReadOnly="True" HeadersVisibility="Column"/> + </DockPanel> + </Grid> + <UserControl.Resources> + <Style TargetType="{x:Type Label}"> + <Setter Property="Foreground" Value="White"/> + <Setter Property="Margin" Value="2"/> + </Style> + <Style TargetType="{x:Type TextBox}"> + <Setter Property="Background" Value="#FF434343"/> + <Setter Property="Foreground" Value="White"/> + </Style> + <Style TargetType="{x:Type DataGridRow}"> + <Setter Property="Foreground" Value="White"/> + <Setter Property="Background" Value="#FF2D2D30"/> + </Style> + <Style TargetType="{x:Type DataGridColumnHeader}"> + <Setter Property="Foreground" Value="White"/> + <Setter Property="Background" Value="#FF434343"/> + </Style> + <Style TargetType="{x:Type DataGridCell}"> + <Setter Property="Background" Value="Transparent"/> + <Setter Property="BorderBrush" Value="Transparent"/> + <Setter Property="BorderThickness" Value="1"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type DataGridCell}"> + <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> + <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> + </Border> + </ControlTemplate> + </Setter.Value> + </Setter> + <Style.Triggers> + <Trigger Property="IsSelected" Value="True"> + <Setter Property="Background" Value="#FF0078D7"/> + <Setter Property="Foreground" Value="White"/> + <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> + </Trigger> + <Trigger Property="IsKeyboardFocusWithin" Value="True"> + <Setter Property="BorderBrush" Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}"/> + </Trigger> + <MultiTrigger> + <MultiTrigger.Conditions> + <Condition Property="IsSelected" Value="true"/> + <Condition Property="Selector.IsSelectionActive" Value="false"/> + </MultiTrigger.Conditions> + <Setter Property="Background" Value="#FF0078D7"/> + <Setter Property="Foreground" Value="White"/> + <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> + </MultiTrigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> + </Trigger> + </Style.Triggers> + </Style> + <Style TargetType="{x:Type Button}" x:Key="InfoButton"> + <Setter Property="Width" Value="70"/> + <Setter Property="Height" Value="25"/> + <Setter Property="Foreground" Value="White"/> + <Setter Property="BorderThickness" Value="0"/> + <Setter Property="Background" Value="#43a9c7"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="Button"> + <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True"> + <TextBlock Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/> + </Border> + <ControlTemplate.Triggers> + <Trigger Property="IsMouseOver" Value="True"> + <Setter TargetName="border" Property="Background" Value="#2f96b4"/> + </Trigger> + <Trigger Property="IsPressed" Value="True"> + <Setter TargetName="border" Property="Background" Value="#2a89a4"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + <Style TargetType="{x:Type Button}" x:Key="WarnButton"> + <Setter Property="Width" Value="80"/> + <Setter Property="Height" Value="25"/> + <Setter Property="Foreground" Value="White"/> + <Setter Property="BorderThickness" Value="0"/> + <Setter Property="Background" Value="#FFFF3A18"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="Button"> + <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True"> + <TextBlock Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/> + </Border> + <ControlTemplate.Triggers> + <Trigger Property="IsMouseOver" Value="True"> + <Setter TargetName="border" Property="Background" Value="#FFFF6E54"/> + </Trigger> + <Trigger Property="IsPressed" Value="True"> + <Setter TargetName="border" Property="Background" Value="#FFFF9887"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + </UserControl.Resources> +</UserControl> diff --git a/src/CodeIndex.VisualStudioExtension/Controls/CodeIndexSearchControl.xaml.cs b/src/CodeIndex.VisualStudioExtension/Controls/CodeIndexSearchControl.xaml.cs new file mode 100644 index 0000000..bf61000 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/Controls/CodeIndexSearchControl.xaml.cs @@ -0,0 +1,28 @@ +using System.Windows.Controls; +using System.Windows.Input; + +namespace CodeIndex.VisualStudioExtension +{ + /// <summary> + /// Interaction logic for CodeIndexSearchControl.xaml. + /// </summary> + [ProvideToolboxControl("CodeIndex.VisualStudioExtension.CodeIndexSearchControl", true)] + public partial class CodeIndexSearchControl : UserControl + { + public CodeIndexSearchControl() + { + InitializeComponent(); + } + + void TextBox_KeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + if(e.KeyboardDevice.Modifiers != ModifierKeys.Control) + { + SearchButton.Command?.Execute(null); + } + } + } + } +} diff --git a/src/CodeIndex.VisualStudioExtension/Models/BaseViewModel.cs b/src/CodeIndex.VisualStudioExtension/Models/BaseViewModel.cs new file mode 100644 index 0000000..1d143a6 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/Models/BaseViewModel.cs @@ -0,0 +1,27 @@ +using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Windows.Threading; + +namespace CodeIndex.VisualStudioExtension +{ + public class BaseViewModel : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + public void NotifyPropertyChange([CallerMemberName]string memberName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(memberName)); + } + + public void NotifyPropertyChange(Func<string> propertyName) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName.Invoke())); + } + + public static void InvokeDispatcher(Action action, Dispatcher dispatcher, DispatcherPriority dispatcherPriority = DispatcherPriority.Normal) + { + dispatcher?.BeginInvoke(dispatcherPriority, action); + } + } +} diff --git a/src/CodeIndex.VisualStudioExtension/Models/CodeIndexSearchViewModel.cs b/src/CodeIndex.VisualStudioExtension/Models/CodeIndexSearchViewModel.cs new file mode 100644 index 0000000..4acfa45 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/Models/CodeIndexSearchViewModel.cs @@ -0,0 +1,257 @@ +using CodeIndex.Common; +using CodeIndex.VisualStudioExtension.Properties; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace CodeIndex.VisualStudioExtension +{ + public class CodeIndexSearchViewModel : BaseViewModel + { + public CodeIndexSearchViewModel() + { + ServiceUrl = CodeIndexSettings.Default.ServiceUrl; + } + + public string FileName { get; set; } + public string Content { get; set; } + public string FileExtension { get; set; } + public string FileLocation { get; set; } + public int ShowResultsNumber { get; set; } = 50; + public string ServiceUrl + { + get => serviceUrl; + set + { + if (value != null && value.EndsWith("/")) + { + value = value.Substring(0, value.Length - 1); + } + + CodeIndexSettings.Default.ServiceUrl = value; + serviceUrl = value; + } + } + public string ResultInfo + { + get => resultInfo; + set + { + resultInfo = value; + NotifyPropertyChange(); + } + } + public Item<int>[] Options { get; } = new[] + { + new Item<int>("Top 10", 10), + new Item<int>("Top 20", 20), + new Item<int>("Top 50", 50), + new Item<int>("Top 100", 100), + new Item<int>("Top 1000", 1000) + }; + + public List<CodeSource> SearchResult + { + get => searchResult; + set + { + searchResult = value; + NotifyPropertyChange(); + } + } + + public class Item<T> + { + public Item(string name, T value) + { + Name = name; + Value = value; + } + + public string Name { get; } + public T Value { get; } + } + + + ICommand searchIndexCommand; + ICommand stopSearchCommand; + string serviceUrl; + List<CodeSource> searchResult = new List<CodeSource>(); + string resultInfo; + CancellationTokenSource tokenSource; + + public ICommand SearchIndexCommand + { + get + { + if (searchIndexCommand == null) + { + searchIndexCommand = new CommonCommand( + param => SearchCodeIndexAsync(), + param => true + ); + } + return searchIndexCommand; + } + } + + + public ICommand StopSearchCommand + { + get + { + if (stopSearchCommand == null) + { + stopSearchCommand = new CommonCommand( + param => tokenSource?.Cancel(), + param => true + ); + } + return stopSearchCommand; + } + } + + #region SearchCodeIndex + + bool IsSearching { get; set; } + + async Task SearchCodeIndexAsync() + { + if (!IsSearching) + { + try + { + IsSearching = true; + tokenSource?.Dispose(); + tokenSource = new CancellationTokenSource(); + ResultInfo = "Searching..."; + + await SearchCodeIndexCoreAsync(); + } + catch (TaskCanceledException) + { + ResultInfo = "Search cancelled."; + } + catch (Exception ex) + { + ResultInfo = "Exception Occur: " + ex; + } + finally + { + IsSearching = false; + } + } + } + + async Task SearchCodeIndexCoreAsync() + { + if (IsValidate()) + { + var url = $"{ServiceUrl}/api/lucene/GetCodeSources?searchQuery=" + System.Web.HttpUtility.UrlEncode(GetSearchStr()) + "&showResults=" + ShowResultsNumber + "&preview=true" + "&contentQuery=" + System.Web.HttpUtility.UrlEncode(Content ?? string.Empty); + + var client = new HttpClient(); + var response = await client.GetAsync(url, tokenSource.Token); + var result = await response.Content.ReadAsAsync<FetchResult<List<CodeSource>>>(); + + if (result.Status.Success) + { + SearchResult = result.Result; + } + else + { + SearchResult.Clear(); + } + + ResultInfo = $"Successful: {result.Status.Success}, Desc: {result.Status.StatusDesc}, Fetch Count: {SearchResult.Count}."; + } + else + { + ResultInfo = "Search query can't be empty."; + } + } + + string GetSearchStr() + { + var searchQueries = new List<string>(); + + if (!string.IsNullOrWhiteSpace(FileName)) + { + searchQueries.Add($"{nameof(CodeSource.FileName)}:{FileName}"); + } + + if (!string.IsNullOrWhiteSpace(Content)) + { + searchQueries.Add($"{nameof(CodeSource.Content)}:{Content}"); + } + + if (!string.IsNullOrWhiteSpace(FileExtension)) + { + searchQueries.Add($"{nameof(CodeSource.FileExtension)}:{FileExtension}"); + } + + if (!string.IsNullOrWhiteSpace(FileLocation)) + { + if (SurroundWithQuotation(FileLocation)) + { + FileLocation = FileLocation.Replace("\\", "\\\\"); + } + + searchQueries.Add($"{nameof(CodeSource.FilePath)}:{FileLocation}"); + } + + return string.Join(" AND ", searchQueries); + } + + static bool SurroundWithQuotation(string content) + { + return !string.IsNullOrWhiteSpace(content) && content.StartsWith("\"") && content.EndsWith("\""); + } + + bool IsValidate() + { + return !string.IsNullOrEmpty(GetSearchStr()); + } + + #endregion + + public class CommonCommand : ICommand + { + readonly Action<object> execute; + readonly Predicate<object> canExecute; + + public CommonCommand(Action<object> execute) : this(execute, null) + { + } + + public CommonCommand(Action<object> execute, Predicate<object> canExecute) + { + if (execute == null) + throw new ArgumentNullException("execute"); + + this.execute = execute; + this.canExecute = canExecute; + } + + [DebuggerStepThrough] + public bool CanExecute(object parameters) + { + return canExecute == null ? true : canExecute(parameters); + } + + public event EventHandler CanExecuteChanged + { + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } + } + + public void Execute(object parameters) + { + execute(parameters); + } + } + } +} diff --git a/src/CodeIndex.VisualStudioExtension/Properties/AssemblyInfo.cs b/src/CodeIndex.VisualStudioExtension/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..639a0e6 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/Properties/AssemblyInfo.cs @@ -0,0 +1,34 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Code Index Search")] +[assembly: AssemblyDescription("Code Index Search Extension For Visual Studio")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CodeIndex.VisualStudioExtension")] +[assembly: AssemblyCopyright("https://github.com/qiuhaotc/CodeIndex")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.1.0.0")] +[assembly: AssemblyFileVersion("0.1.0.0")] +[assembly: Guid("8F594ABC-BDED-431E-BF88-23AFE38F9032")] diff --git a/src/CodeIndex.VisualStudioExtension/Properties/CodeIndexSettings.Designer.cs b/src/CodeIndex.VisualStudioExtension/Properties/CodeIndexSettings.Designer.cs new file mode 100644 index 0000000..c5842e2 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/Properties/CodeIndexSettings.Designer.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace CodeIndex.VisualStudioExtension.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")] + internal sealed partial class CodeIndexSettings : global::System.Configuration.ApplicationSettingsBase { + + private static CodeIndexSettings defaultInstance = ((CodeIndexSettings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new CodeIndexSettings()))); + + public static CodeIndexSettings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("https://codeindex.qhnetdisk.tk/")] + public string ServiceUrl { + get { + return ((string)(this["ServiceUrl"])); + } + set { + this["ServiceUrl"] = value; + } + } + } +} diff --git a/src/CodeIndex.VisualStudioExtension/Properties/CodeIndexSettings.settings b/src/CodeIndex.VisualStudioExtension/Properties/CodeIndexSettings.settings new file mode 100644 index 0000000..9c15cb7 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/Properties/CodeIndexSettings.settings @@ -0,0 +1,9 @@ +<?xml version='1.0' encoding='utf-8'?> +<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="CodeIndex.VisualStudioExtension.Properties" GeneratedClassName="CodeIndexSettings"> + <Profiles /> + <Settings> + <Setting Name="ServiceUrl" Type="System.String" Scope="User"> + <Value Profile="(Default)">https://codeindex.qhnetdisk.tk/</Value> + </Setting> + </Settings> +</SettingsFile> \ No newline at end of file diff --git a/src/CodeIndex.VisualStudioExtension/ProvideToolboxControlAttribute.cs b/src/CodeIndex.VisualStudioExtension/ProvideToolboxControlAttribute.cs new file mode 100644 index 0000000..775f936 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/ProvideToolboxControlAttribute.cs @@ -0,0 +1,83 @@ +using Microsoft.VisualStudio.Shell; +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace CodeIndex.VisualStudioExtension +{ + /// <summary> + /// This attribute adds a ToolboxControlsInstaller key for the assembly to install toolbox controls from the assembly. + /// </summary> + /// <remarks> + /// For example + /// [$(Rootkey)\ToolboxControlsInstaller\$FullAssemblyName$] + /// "Codebase"="$path$" + /// "WpfControls"="1" + /// </remarks> + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + [ComVisible(false)] + public sealed class ProvideToolboxControlAttribute : RegistrationAttribute + { + private const string ToolboxControlsInstallerPath = "ToolboxControlsInstaller"; + private readonly string name; + private readonly bool areWPFControls; + + /// <summary> + /// Creates a new ProvideToolboxControl attribute to register the assembly for toolbox controls installer. + /// </summary> + /// <param name="name">The name of the toolbox controls.</param> + /// <param name="areWPFControls">Indicates whether the toolbox controls are WPF controls.</param> + public ProvideToolboxControlAttribute(string name, bool areWPFControls) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + this.name = name; + this.areWPFControls = areWPFControls; + } + + /// <summary> + /// Called to register this attribute with the given context. The context + /// contains the location where the registration information should be placed. + /// It also contains other information such as the type being registered and path information. + /// </summary> + /// <param name="context">Given context to register in.</param> + public override void Register(RegistrationContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + using (Key key = context.CreateKey(string.Format(CultureInfo.InvariantCulture, "{0}\\{1}", + ToolboxControlsInstallerPath, + context.ComponentType.Assembly.FullName))) + { + key.SetValue(string.Empty, this.name); + key.SetValue("Codebase", context.CodeBase); + if (this.areWPFControls) + { + key.SetValue("WPFControls", "1"); + } + } + } + + /// <summary> + /// Called to unregister this attribute with the given context. + /// </summary> + /// <param name="context">A registration context provided by an external registration tool. + /// The context can be used to remove registry keys, log registration activity, and obtain information + /// about the component being registered.</param> + public override void Unregister(RegistrationContext context) + { + if (context != null) + { + context.RemoveKey(string.Format(CultureInfo.InvariantCulture, "{0}\\{1}", + ToolboxControlsInstallerPath, + context.ComponentType.Assembly.FullName)); + } + } + } +} diff --git a/src/CodeIndex.VisualStudioExtension/Resources/CodeIndexSearchWindowCommand.png b/src/CodeIndex.VisualStudioExtension/Resources/CodeIndexSearchWindowCommand.png new file mode 100644 index 0000000..b22d975 Binary files /dev/null and b/src/CodeIndex.VisualStudioExtension/Resources/CodeIndexSearchWindowCommand.png differ diff --git a/src/CodeIndex.VisualStudioExtension/Resources/Style.xaml b/src/CodeIndex.VisualStudioExtension/Resources/Style.xaml new file mode 100644 index 0000000..4f44c3d --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/Resources/Style.xaml @@ -0,0 +1,3 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + +</ResourceDictionary> \ No newline at end of file diff --git a/src/CodeIndex.VisualStudioExtension/VisualStudioExtensionPackage.vsct b/src/CodeIndex.VisualStudioExtension/VisualStudioExtensionPackage.vsct new file mode 100644 index 0000000..55d5c59 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/VisualStudioExtensionPackage.vsct @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="utf-8"?> +<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + <!-- This is the file that defines the actual layout and type of the commands. + It is divided in different sections (e.g. command definition, command + placement, ...), with each defining a specific set of properties. + See the comment before each section for more details about how to + use it. --> + + <!-- The VSCT compiler (the tool that translates this file into the binary + format that VisualStudio will consume) has the ability to run a preprocessor + on the vsct file; this preprocessor is (usually) the C++ preprocessor, so + it is possible to define includes and macros with the same syntax used + in C++ files. Using this ability of the compiler here, we include some files + defining some of the constants that we will use inside the file. --> + + <!--This is the file that defines the IDs for all the commands exposed by VisualStudio. --> + <Extern href="stdidcmd.h" /> + + <!--This header contains the command ids for the menus provided by the shell. --> + <Extern href="vsshlids.h" /> + + <!--The Commands section is where commands, menus, and menu groups are defined. + This section uses a Guid to identify the package that provides the command defined inside it. --> + <Commands package="guidVisualStudioExtensionPackage"> + <!-- Inside this section we have different sub-sections: one for the menus, another + for the menu groups, one for the buttons (the actual commands), one for the combos + and the last one for the bitmaps used. Each element is identified by a command id that + is a unique pair of guid and numeric identifier; the guid part of the identifier is usually + called "command set" and is used to group different command inside a logically related + group; your package should define its own command set in order to avoid collisions + with command ids defined by other packages. --> + + <!--Buttons section. --> + <!--This section defines the elements the user can interact with, like a menu command or a button + or combo box in a toolbar. --> + <Buttons> + <!--To define a menu group you have to specify its ID, the parent menu and its display priority. + The command is visible and enabled by default. If you need to change the visibility, status, etc, you can use + the CommandFlag node. + You can add more than one CommandFlag node e.g.: + <CommandFlag>DefaultInvisible</CommandFlag> + <CommandFlag>DynamicVisibility</CommandFlag> + If you do not want an image next to your command, remove the Icon node /> --> + <Button guid="guidVisualStudioExtensionPackageCmdSet" id="cmdidCodeIndexSearchWindowCommand" priority="0x0100" type="Button"> + <Parent guid="guidSHLMainMenu" id="IDG_VS_WNDO_OTRWNDWS1" /> + <Icon guid="guidImages1" id="bmpPicSearch" /> + <Strings> + <ButtonText>Code Index Search</ButtonText> + </Strings> + </Button> + </Buttons> + + <!--The bitmaps section is used to define the bitmaps that are used for the commands.--> + <Bitmaps> + <!-- The bitmap id is defined in a way that is a little bit different from the others: + the declaration starts with a guid for the bitmap strip, then there is the resource id of the + bitmap strip containing the bitmaps and then there are the numeric ids of the elements used + inside a button definition. An important aspect of this declaration is that the element id + must be the actual index (1-based) of the bitmap inside the bitmap strip. --> + <Bitmap guid="guidImages1" href="Resources\CodeIndexSearchWindowCommand.png" usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows, bmpPicStrikethrough" /> + </Bitmaps> + </Commands> + + <Symbols> + <!-- This is the package guid. --> + <GuidSymbol name="guidVisualStudioExtensionPackage" value="{1eaddb39-c1f2-42e2-807d-234d73e8ef2a}" /> + + <!-- This is the guid used to group the menu commands together --> + <GuidSymbol name="guidVisualStudioExtensionPackageCmdSet" value="{c025b4ef-e6ed-42b4-9c22-2d6835421d25}"> + <IDSymbol value="4129" name="cmdidCodeIndexSearchWindowCommand" /> + </GuidSymbol> + + <GuidSymbol name="guidImages" value="{8f96059a-9439-496a-91a0-b937e25c4e41}"> + <IDSymbol name="bmpPic1" value="1" /> + <IDSymbol name="bmpPic2" value="2" /> + <IDSymbol name="bmpPicSearch" value="3" /> + <IDSymbol name="bmpPicX" value="4" /> + <IDSymbol name="bmpPicArrows" value="5" /> + <IDSymbol name="bmpPicStrikethrough" value="6" /> + </GuidSymbol> + + <GuidSymbol value="{3e596c47-5e3e-4915-aff5-dd8a8b1394a9}" name="guidImages1"> + <IDSymbol name="bmpPic1" value="1" /> + <IDSymbol name="bmpPic2" value="2" /> + <IDSymbol name="bmpPicSearch" value="3" /> + <IDSymbol name="bmpPicX" value="4" /> + <IDSymbol name="bmpPicArrows" value="5" /> + <IDSymbol name="bmpPicStrikethrough" value="6" /> + </GuidSymbol> + </Symbols> +</CommandTable> diff --git a/src/CodeIndex.VisualStudioExtension/app.config b/src/CodeIndex.VisualStudioExtension/app.config new file mode 100644 index 0000000..6902a91 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/app.config @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8" ?> +<configuration> + <configSections> + <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > + <section name="CodeIndex.VisualStudioExtension.Properties.CodeIndexSettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" /> + </sectionGroup> + </configSections> + <userSettings> + <CodeIndex.VisualStudioExtension.Properties.CodeIndexSettings> + <setting name="ServiceUrl" serializeAs="String"> + <value>https://codeindex.qhnetdisk.tk/</value> + </setting> + </CodeIndex.VisualStudioExtension.Properties.CodeIndexSettings> + </userSettings> +</configuration> \ No newline at end of file diff --git a/src/CodeIndex.VisualStudioExtension/source.extension.vsixmanifest b/src/CodeIndex.VisualStudioExtension/source.extension.vsixmanifest new file mode 100644 index 0000000..81ee373 --- /dev/null +++ b/src/CodeIndex.VisualStudioExtension/source.extension.vsixmanifest @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011"> + <Metadata> + <Identity Id="CodeIndex.VisualStudioExtension.3fee47f7-831c-4577-8b21-f6505d9699f5" Version="1.0" Language="en-US" Publisher="笑问苍天" /> + <DisplayName>CodeIndex.VisualStudioExtension</DisplayName> + <Description xml:space="preserve">Code Index Search Extension For Visual Studio</Description> + <MoreInfo>https://github.com/qiuhaotc/CodeIndex</MoreInfo> + <Tags>Code full-text search</Tags> + <Preview>true</Preview> + </Metadata> + <Installation> + <InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[16.0, 17.0)" /> + </Installation> + <Dependencies> + <Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="[4.5,)" /> + </Dependencies> + <Prerequisites> + <Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[16.0,17.0)" DisplayName="Visual Studio core editor" /> + </Prerequisites> + <Assets> + <Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" /> + <Asset Type="Microsoft.VisualStudio.ToolboxControl" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" /> + </Assets> +</PackageManifest> diff --git a/src/CodeIndex.sln b/src/CodeIndex.sln index 9cea751..6d8f411 100644 --- a/src/CodeIndex.sln +++ b/src/CodeIndex.sln @@ -26,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{B0519424-9D6 ..\doc\WebServer.png = ..\doc\WebServer.png EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeIndex.VisualStudioExtension", "CodeIndex.VisualStudioExtension\CodeIndex.VisualStudioExtension.csproj", "{ED1D3026-8695-4B9B-9FA9-2D68E28EE850}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -64,6 +66,10 @@ Global {BE1F4C0F-F4FF-43B0-B8F2-2C1F9B446059}.Debug|Any CPU.Build.0 = Debug|Any CPU {BE1F4C0F-F4FF-43B0-B8F2-2C1F9B446059}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE1F4C0F-F4FF-43B0-B8F2-2C1F9B446059}.Release|Any CPU.Build.0 = Release|Any CPU + {ED1D3026-8695-4B9B-9FA9-2D68E28EE850}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED1D3026-8695-4B9B-9FA9-2D68E28EE850}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED1D3026-8695-4B9B-9FA9-2D68E28EE850}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED1D3026-8695-4B9B-9FA9-2D68E28EE850}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE