mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-11 08:41:06 +00:00
Compare commits
9 Commits
dev/lhecke
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a84f5354a | ||
|
|
e9855c2109 | ||
|
|
864f1b53f4 | ||
|
|
f8e5bfa09e | ||
|
|
2dc16e43a7 | ||
|
|
32234cafeb | ||
|
|
7b8b60bdef | ||
|
|
43d46dbc99 | ||
|
|
0ec5aef050 |
@@ -237,6 +237,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{89CDCC
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Types.Unit.Tests", "src\types\ut_types\Types.Unit.Tests.vcxproj", "{34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "md4c", "src\dep\md4c\md4c.vcxproj", "{7CAE5851-50D5-4934-8D5E-30361A8A40F3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalControl", "src\cascadia\WpfTerminalControl\WpfTerminalControl.csproj", "{376FE273-6B84-4EB5-8B30-8DE9D21B022C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_TerminalApp", "src\cascadia\ut_app\TerminalApp.UnitTests.vcxproj", "{CA5CAD1A-9333-4D05-B12A-1905CBF112F9}"
|
||||
@@ -1827,6 +1829,36 @@ Global
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.Build.0 = Release|x64
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.Build.0 = Release|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.Build.0 = Debug|x64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.Build.0 = Debug|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.ActiveCfg = Release|x64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.Build.0 = Release|x64
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.ActiveCfg = Release|Win32
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.Build.0 = Release|Win32
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.AuditMode|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.AuditMode|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.AuditMode|x64.ActiveCfg = Debug|Any CPU
|
||||
@@ -2509,6 +2541,7 @@ Global
|
||||
{D3EF7B96-CD5E-47C9-B9A9-136259563033} = {04170EEF-983A-4195-BFEF-2321E5E38A1E}
|
||||
{024052DE-83FB-4653-AEA4-90790D29D5BD} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D} = {61901E80-E97D-4D61-A9BB-E8F2FDA8B40C}
|
||||
{7CAE5851-50D5-4934-8D5E-30361A8A40F3} = {81C352DB-1818-45B7-A284-18E259F1CC87}
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3} = {81C352DB-1818-45B7-A284-18E259F1CC87}
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD} = {4DAF0299-495E-4CD1-A982-9BAC16A45932}
|
||||
{506FD703-BAA7-4F6E-9361-64F550EC8FCA} = {61901E80-E97D-4D61-A9BB-E8F2FDA8B40C}
|
||||
|
||||
6492
oss/md4c/md4c.c
Normal file
6492
oss/md4c/md4c.c
Normal file
File diff suppressed because it is too large
Load Diff
407
oss/md4c/md4c.h
Normal file
407
oss/md4c/md4c.h
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* MD4C: Markdown parser for C
|
||||
* (http://github.com/mity/md4c)
|
||||
*
|
||||
* Copyright (c) 2016-2024 Martin Mitáš
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MD4C_H
|
||||
#define MD4C_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined MD4C_USE_UTF16
|
||||
/* Magic to support UTF-16. Note that in order to use it, you have to define
|
||||
* the macro MD4C_USE_UTF16 both when building MD4C as well as when
|
||||
* including this header in your code. */
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
typedef WCHAR MD_CHAR;
|
||||
#else
|
||||
#error MD4C_USE_UTF16 is only supported on Windows.
|
||||
#endif
|
||||
#else
|
||||
typedef char MD_CHAR;
|
||||
#endif
|
||||
|
||||
typedef unsigned MD_SIZE;
|
||||
typedef unsigned MD_OFFSET;
|
||||
|
||||
|
||||
/* Block represents a part of document hierarchy structure like a paragraph
|
||||
* or list item.
|
||||
*/
|
||||
typedef enum MD_BLOCKTYPE {
|
||||
/* <body>...</body> */
|
||||
MD_BLOCK_DOC = 0,
|
||||
|
||||
/* <blockquote>...</blockquote> */
|
||||
MD_BLOCK_QUOTE,
|
||||
|
||||
/* <ul>...</ul>
|
||||
* Detail: Structure MD_BLOCK_UL_DETAIL. */
|
||||
MD_BLOCK_UL,
|
||||
|
||||
/* <ol>...</ol>
|
||||
* Detail: Structure MD_BLOCK_OL_DETAIL. */
|
||||
MD_BLOCK_OL,
|
||||
|
||||
/* <li>...</li>
|
||||
* Detail: Structure MD_BLOCK_LI_DETAIL. */
|
||||
MD_BLOCK_LI,
|
||||
|
||||
/* <hr> */
|
||||
MD_BLOCK_HR,
|
||||
|
||||
/* <h1>...</h1> (for levels up to 6)
|
||||
* Detail: Structure MD_BLOCK_H_DETAIL. */
|
||||
MD_BLOCK_H,
|
||||
|
||||
/* <pre><code>...</code></pre>
|
||||
* Note the text lines within code blocks are terminated with '\n'
|
||||
* instead of explicit MD_TEXT_BR. */
|
||||
MD_BLOCK_CODE,
|
||||
|
||||
/* Raw HTML block. This itself does not correspond to any particular HTML
|
||||
* tag. The contents of it _is_ raw HTML source intended to be put
|
||||
* in verbatim form to the HTML output. */
|
||||
MD_BLOCK_HTML,
|
||||
|
||||
/* <p>...</p> */
|
||||
MD_BLOCK_P,
|
||||
|
||||
/* <table>...</table> and its contents.
|
||||
* Detail: Structure MD_BLOCK_TABLE_DETAIL (for MD_BLOCK_TABLE),
|
||||
* structure MD_BLOCK_TD_DETAIL (for MD_BLOCK_TH and MD_BLOCK_TD)
|
||||
* Note all of these are used only if extension MD_FLAG_TABLES is enabled. */
|
||||
MD_BLOCK_TABLE,
|
||||
MD_BLOCK_THEAD,
|
||||
MD_BLOCK_TBODY,
|
||||
MD_BLOCK_TR,
|
||||
MD_BLOCK_TH,
|
||||
MD_BLOCK_TD
|
||||
} MD_BLOCKTYPE;
|
||||
|
||||
/* Span represents an in-line piece of a document which should be rendered with
|
||||
* the same font, color and other attributes. A sequence of spans forms a block
|
||||
* like paragraph or list item. */
|
||||
typedef enum MD_SPANTYPE {
|
||||
/* <em>...</em> */
|
||||
MD_SPAN_EM,
|
||||
|
||||
/* <strong>...</strong> */
|
||||
MD_SPAN_STRONG,
|
||||
|
||||
/* <a href="xxx">...</a>
|
||||
* Detail: Structure MD_SPAN_A_DETAIL. */
|
||||
MD_SPAN_A,
|
||||
|
||||
/* <img src="xxx">...</a>
|
||||
* Detail: Structure MD_SPAN_IMG_DETAIL.
|
||||
* Note: Image text can contain nested spans and even nested images.
|
||||
* If rendered into ALT attribute of HTML <IMG> tag, it's responsibility
|
||||
* of the parser to deal with it.
|
||||
*/
|
||||
MD_SPAN_IMG,
|
||||
|
||||
/* <code>...</code> */
|
||||
MD_SPAN_CODE,
|
||||
|
||||
/* <del>...</del>
|
||||
* Note: Recognized only when MD_FLAG_STRIKETHROUGH is enabled.
|
||||
*/
|
||||
MD_SPAN_DEL,
|
||||
|
||||
/* For recognizing inline ($) and display ($$) equations
|
||||
* Note: Recognized only when MD_FLAG_LATEXMATHSPANS is enabled.
|
||||
*/
|
||||
MD_SPAN_LATEXMATH,
|
||||
MD_SPAN_LATEXMATH_DISPLAY,
|
||||
|
||||
/* Wiki links
|
||||
* Note: Recognized only when MD_FLAG_WIKILINKS is enabled.
|
||||
*/
|
||||
MD_SPAN_WIKILINK,
|
||||
|
||||
/* <u>...</u>
|
||||
* Note: Recognized only when MD_FLAG_UNDERLINE is enabled. */
|
||||
MD_SPAN_U
|
||||
} MD_SPANTYPE;
|
||||
|
||||
/* Text is the actual textual contents of span. */
|
||||
typedef enum MD_TEXTTYPE {
|
||||
/* Normal text. */
|
||||
MD_TEXT_NORMAL = 0,
|
||||
|
||||
/* NULL character. CommonMark requires replacing NULL character with
|
||||
* the replacement char U+FFFD, so this allows caller to do that easily. */
|
||||
MD_TEXT_NULLCHAR,
|
||||
|
||||
/* Line breaks.
|
||||
* Note these are not sent from blocks with verbatim output (MD_BLOCK_CODE
|
||||
* or MD_BLOCK_HTML). In such cases, '\n' is part of the text itself. */
|
||||
MD_TEXT_BR, /* <br> (hard break) */
|
||||
MD_TEXT_SOFTBR, /* '\n' in source text where it is not semantically meaningful (soft break) */
|
||||
|
||||
/* Entity.
|
||||
* (a) Named entity, e.g.
|
||||
* (Note MD4C does not have a list of known entities.
|
||||
* Anything matching the regexp /&[A-Za-z][A-Za-z0-9]{1,47};/ is
|
||||
* treated as a named entity.)
|
||||
* (b) Numerical entity, e.g. Ӓ
|
||||
* (c) Hexadecimal entity, e.g. ካ
|
||||
*
|
||||
* As MD4C is mostly encoding agnostic, application gets the verbatim
|
||||
* entity text into the MD_PARSER::text_callback(). */
|
||||
MD_TEXT_ENTITY,
|
||||
|
||||
/* Text in a code block (inside MD_BLOCK_CODE) or inlined code (`code`).
|
||||
* If it is inside MD_BLOCK_CODE, it includes spaces for indentation and
|
||||
* '\n' for new lines. MD_TEXT_BR and MD_TEXT_SOFTBR are not sent for this
|
||||
* kind of text. */
|
||||
MD_TEXT_CODE,
|
||||
|
||||
/* Text is a raw HTML. If it is contents of a raw HTML block (i.e. not
|
||||
* an inline raw HTML), then MD_TEXT_BR and MD_TEXT_SOFTBR are not used.
|
||||
* The text contains verbatim '\n' for the new lines. */
|
||||
MD_TEXT_HTML,
|
||||
|
||||
/* Text is inside an equation. This is processed the same way as inlined code
|
||||
* spans (`code`). */
|
||||
MD_TEXT_LATEXMATH
|
||||
} MD_TEXTTYPE;
|
||||
|
||||
|
||||
/* Alignment enumeration. */
|
||||
typedef enum MD_ALIGN {
|
||||
MD_ALIGN_DEFAULT = 0, /* When unspecified. */
|
||||
MD_ALIGN_LEFT,
|
||||
MD_ALIGN_CENTER,
|
||||
MD_ALIGN_RIGHT
|
||||
} MD_ALIGN;
|
||||
|
||||
|
||||
/* String attribute.
|
||||
*
|
||||
* This wraps strings which are outside of a normal text flow and which are
|
||||
* propagated within various detailed structures, but which still may contain
|
||||
* string portions of different types like e.g. entities.
|
||||
*
|
||||
* So, for example, lets consider this image:
|
||||
*
|
||||
* 
|
||||
*
|
||||
* The image alt text is propagated as a normal text via the MD_PARSER::text()
|
||||
* callback. However, the image title ('foo " bar') is propagated as
|
||||
* MD_ATTRIBUTE in MD_SPAN_IMG_DETAIL::title.
|
||||
*
|
||||
* Then the attribute MD_SPAN_IMG_DETAIL::title shall provide the following:
|
||||
* -- [0]: "foo " (substr_types[0] == MD_TEXT_NORMAL; substr_offsets[0] == 0)
|
||||
* -- [1]: """ (substr_types[1] == MD_TEXT_ENTITY; substr_offsets[1] == 4)
|
||||
* -- [2]: " bar" (substr_types[2] == MD_TEXT_NORMAL; substr_offsets[2] == 10)
|
||||
* -- [3]: (n/a) (n/a ; substr_offsets[3] == 14)
|
||||
*
|
||||
* Note that these invariants are always guaranteed:
|
||||
* -- substr_offsets[0] == 0
|
||||
* -- substr_offsets[LAST+1] == size
|
||||
* -- Currently, only MD_TEXT_NORMAL, MD_TEXT_ENTITY, MD_TEXT_NULLCHAR
|
||||
* substrings can appear. This could change only of the specification
|
||||
* changes.
|
||||
*/
|
||||
typedef struct MD_ATTRIBUTE {
|
||||
const MD_CHAR* text;
|
||||
MD_SIZE size;
|
||||
const MD_TEXTTYPE* substr_types;
|
||||
const MD_OFFSET* substr_offsets;
|
||||
} MD_ATTRIBUTE;
|
||||
|
||||
|
||||
/* Detailed info for MD_BLOCK_UL. */
|
||||
typedef struct MD_BLOCK_UL_DETAIL {
|
||||
int is_tight; /* Non-zero if tight list, zero if loose. */
|
||||
MD_CHAR mark; /* Item bullet character in MarkDown source of the list, e.g. '-', '+', '*'. */
|
||||
} MD_BLOCK_UL_DETAIL;
|
||||
|
||||
/* Detailed info for MD_BLOCK_OL. */
|
||||
typedef struct MD_BLOCK_OL_DETAIL {
|
||||
unsigned start; /* Start index of the ordered list. */
|
||||
int is_tight; /* Non-zero if tight list, zero if loose. */
|
||||
MD_CHAR mark_delimiter; /* Character delimiting the item marks in MarkDown source, e.g. '.' or ')' */
|
||||
} MD_BLOCK_OL_DETAIL;
|
||||
|
||||
/* Detailed info for MD_BLOCK_LI. */
|
||||
typedef struct MD_BLOCK_LI_DETAIL {
|
||||
int is_task; /* Can be non-zero only with MD_FLAG_TASKLISTS */
|
||||
MD_CHAR task_mark; /* If is_task, then one of 'x', 'X' or ' '. Undefined otherwise. */
|
||||
MD_OFFSET task_mark_offset; /* If is_task, then offset in the input of the char between '[' and ']'. */
|
||||
} MD_BLOCK_LI_DETAIL;
|
||||
|
||||
/* Detailed info for MD_BLOCK_H. */
|
||||
typedef struct MD_BLOCK_H_DETAIL {
|
||||
unsigned level; /* Header level (1 - 6) */
|
||||
} MD_BLOCK_H_DETAIL;
|
||||
|
||||
/* Detailed info for MD_BLOCK_CODE. */
|
||||
typedef struct MD_BLOCK_CODE_DETAIL {
|
||||
MD_ATTRIBUTE info;
|
||||
MD_ATTRIBUTE lang;
|
||||
MD_CHAR fence_char; /* The character used for fenced code block; or zero for indented code block. */
|
||||
} MD_BLOCK_CODE_DETAIL;
|
||||
|
||||
/* Detailed info for MD_BLOCK_TABLE. */
|
||||
typedef struct MD_BLOCK_TABLE_DETAIL {
|
||||
unsigned col_count; /* Count of columns in the table. */
|
||||
unsigned head_row_count; /* Count of rows in the table header (currently always 1) */
|
||||
unsigned body_row_count; /* Count of rows in the table body */
|
||||
} MD_BLOCK_TABLE_DETAIL;
|
||||
|
||||
/* Detailed info for MD_BLOCK_TH and MD_BLOCK_TD. */
|
||||
typedef struct MD_BLOCK_TD_DETAIL {
|
||||
MD_ALIGN align;
|
||||
} MD_BLOCK_TD_DETAIL;
|
||||
|
||||
/* Detailed info for MD_SPAN_A. */
|
||||
typedef struct MD_SPAN_A_DETAIL {
|
||||
MD_ATTRIBUTE href;
|
||||
MD_ATTRIBUTE title;
|
||||
int is_autolink; /* nonzero if this is an autolink */
|
||||
} MD_SPAN_A_DETAIL;
|
||||
|
||||
/* Detailed info for MD_SPAN_IMG. */
|
||||
typedef struct MD_SPAN_IMG_DETAIL {
|
||||
MD_ATTRIBUTE src;
|
||||
MD_ATTRIBUTE title;
|
||||
} MD_SPAN_IMG_DETAIL;
|
||||
|
||||
/* Detailed info for MD_SPAN_WIKILINK. */
|
||||
typedef struct MD_SPAN_WIKILINK {
|
||||
MD_ATTRIBUTE target;
|
||||
} MD_SPAN_WIKILINK_DETAIL;
|
||||
|
||||
/* Flags specifying extensions/deviations from CommonMark specification.
|
||||
*
|
||||
* By default (when MD_PARSER::flags == 0), we follow CommonMark specification.
|
||||
* The following flags may allow some extensions or deviations from it.
|
||||
*/
|
||||
#define MD_FLAG_COLLAPSEWHITESPACE 0x0001 /* In MD_TEXT_NORMAL, collapse non-trivial whitespace into single ' ' */
|
||||
#define MD_FLAG_PERMISSIVEATXHEADERS 0x0002 /* Do not require space in ATX headers ( ###header ) */
|
||||
#define MD_FLAG_PERMISSIVEURLAUTOLINKS 0x0004 /* Recognize URLs as autolinks even without '<', '>' */
|
||||
#define MD_FLAG_PERMISSIVEEMAILAUTOLINKS 0x0008 /* Recognize e-mails as autolinks even without '<', '>' and 'mailto:' */
|
||||
#define MD_FLAG_NOINDENTEDCODEBLOCKS 0x0010 /* Disable indented code blocks. (Only fenced code works.) */
|
||||
#define MD_FLAG_NOHTMLBLOCKS 0x0020 /* Disable raw HTML blocks. */
|
||||
#define MD_FLAG_NOHTMLSPANS 0x0040 /* Disable raw HTML (inline). */
|
||||
#define MD_FLAG_TABLES 0x0100 /* Enable tables extension. */
|
||||
#define MD_FLAG_STRIKETHROUGH 0x0200 /* Enable strikethrough extension. */
|
||||
#define MD_FLAG_PERMISSIVEWWWAUTOLINKS 0x0400 /* Enable WWW autolinks (even without any scheme prefix, if they begin with 'www.') */
|
||||
#define MD_FLAG_TASKLISTS 0x0800 /* Enable task list extension. */
|
||||
#define MD_FLAG_LATEXMATHSPANS 0x1000 /* Enable $ and $$ containing LaTeX equations. */
|
||||
#define MD_FLAG_WIKILINKS 0x2000 /* Enable wiki links extension. */
|
||||
#define MD_FLAG_UNDERLINE 0x4000 /* Enable underline extension (and disables '_' for normal emphasis). */
|
||||
#define MD_FLAG_HARD_SOFT_BREAKS 0x8000 /* Force all soft breaks to act as hard breaks. */
|
||||
|
||||
#define MD_FLAG_PERMISSIVEAUTOLINKS (MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS)
|
||||
#define MD_FLAG_NOHTML (MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS)
|
||||
|
||||
/* Convenient sets of flags corresponding to well-known Markdown dialects.
|
||||
*
|
||||
* Note we may only support subset of features of the referred dialect.
|
||||
* The constant just enables those extensions which bring us as close as
|
||||
* possible given what features we implement.
|
||||
*
|
||||
* ABI compatibility note: Meaning of these can change in time as new
|
||||
* extensions, bringing the dialect closer to the original, are implemented.
|
||||
*/
|
||||
#define MD_DIALECT_COMMONMARK 0
|
||||
#define MD_DIALECT_GITHUB (MD_FLAG_PERMISSIVEAUTOLINKS | MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH | MD_FLAG_TASKLISTS)
|
||||
|
||||
/* Parser structure.
|
||||
*/
|
||||
typedef struct MD_PARSER {
|
||||
/* Reserved. Set to zero.
|
||||
*/
|
||||
unsigned abi_version;
|
||||
|
||||
/* Dialect options. Bitmask of MD_FLAG_xxxx values.
|
||||
*/
|
||||
unsigned flags;
|
||||
|
||||
/* Caller-provided rendering callbacks.
|
||||
*
|
||||
* For some block/span types, more detailed information is provided in a
|
||||
* type-specific structure pointed by the argument 'detail'.
|
||||
*
|
||||
* The last argument of all callbacks, 'userdata', is just propagated from
|
||||
* md_parse() and is available for any use by the application.
|
||||
*
|
||||
* Note any strings provided to the callbacks as their arguments or as
|
||||
* members of any detail structure are generally not zero-terminated.
|
||||
* Application has to take the respective size information into account.
|
||||
*
|
||||
* Any rendering callback may abort further parsing of the document by
|
||||
* returning non-zero.
|
||||
*/
|
||||
int (*enter_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
|
||||
int (*leave_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
|
||||
|
||||
int (*enter_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
|
||||
int (*leave_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/);
|
||||
|
||||
int (*text)(MD_TEXTTYPE /*type*/, const MD_CHAR* /*text*/, MD_SIZE /*size*/, void* /*userdata*/);
|
||||
|
||||
/* Debug callback. Optional (may be NULL).
|
||||
*
|
||||
* If provided and something goes wrong, this function gets called.
|
||||
* This is intended for debugging and problem diagnosis for developers;
|
||||
* it is not intended to provide any errors suitable for displaying to an
|
||||
* end user.
|
||||
*/
|
||||
void (*debug_log)(const char* /*msg*/, void* /*userdata*/);
|
||||
|
||||
/* Reserved. Set to NULL.
|
||||
*/
|
||||
void (*syntax)(void);
|
||||
} MD_PARSER;
|
||||
|
||||
|
||||
/* For backward compatibility. Do not use in new code.
|
||||
*/
|
||||
typedef MD_PARSER MD_RENDERER;
|
||||
|
||||
|
||||
/* Parse the Markdown document stored in the string 'text' of size 'size'.
|
||||
* The parser provides callbacks to be called during the parsing so the
|
||||
* caller can render the document on the screen or convert the Markdown
|
||||
* to another format.
|
||||
*
|
||||
* Zero is returned on success. If a runtime error occurs (e.g. a memory
|
||||
* fails), -1 is returned. If the processing is aborted due any callback
|
||||
* returning non-zero, the return value of the callback is returned.
|
||||
*/
|
||||
int md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userdata);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" { */
|
||||
#endif
|
||||
|
||||
#endif /* MD4C_H */
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "TerminalPage.h"
|
||||
#include "ScratchpadContent.h"
|
||||
#include "TasksPaneContent.h"
|
||||
#include "../WinRTUtils/inc/WtExeUtils.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "Utils.h"
|
||||
@@ -1473,4 +1474,25 @@ namespace winrt::TerminalApp::implementation
|
||||
_ShowAboutDialog();
|
||||
args.Handled(true);
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleOpenTasksPane(const IInspectable& sender,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (Feature_ScratchpadPane::IsEnabled())
|
||||
{
|
||||
const auto& scratchPane{ winrt::make_self<TasksPaneContent>() };
|
||||
scratchPane->UpdateSettings(_settings);
|
||||
// This is maybe a little wacky - add our key event handler to the pane
|
||||
// we made. So that we can get actions for keys that the content didn't
|
||||
// handle.
|
||||
scratchPane->GetRoot().KeyDown({ this, &TerminalPage::_KeyDownHandler });
|
||||
|
||||
scratchPane->DispatchCommandRequested({ this, &TerminalPage::_OnDispatchCommandRequested });
|
||||
|
||||
const auto resultPane = std::make_shared<Pane>(*scratchPane);
|
||||
_SplitPane(_senderOrFocusedTab(sender), SplitDirection::Automatic, 0.5f, resultPane);
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
21
src/cascadia/TerminalApp/BasicPaneEvents.h
Normal file
21
src/cascadia/TerminalApp/BasicPaneEvents.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct BasicPaneEvents
|
||||
{
|
||||
til::typed_event<> ConnectionStateChanged;
|
||||
til::typed_event<IPaneContent> CloseRequested;
|
||||
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
|
||||
til::typed_event<IPaneContent> TitleChanged;
|
||||
til::typed_event<IPaneContent> TabColorChanged;
|
||||
til::typed_event<IPaneContent> TaskbarProgressChanged;
|
||||
til::typed_event<IPaneContent> ReadOnlyChanged;
|
||||
til::typed_event<IPaneContent> FocusRequested;
|
||||
|
||||
til::typed_event<winrt::Windows::Foundation::IInspectable, Microsoft::Terminal::Settings::Model::Command> DispatchCommandRequested;
|
||||
};
|
||||
}
|
||||
31
src/cascadia/TerminalApp/CodeBlock.cpp
Normal file
31
src/cascadia/TerminalApp/CodeBlock.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "CodeBlock.h"
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "CodeBlock.g.cpp"
|
||||
#include "RequestRunCommandsArgs.g.cpp"
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
namespace MUX = Microsoft::UI::Xaml;
|
||||
namespace WUX = Windows::UI::Xaml;
|
||||
using IInspectable = Windows::Foundation::IInspectable;
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
CodeBlock::CodeBlock(const winrt::hstring& initialCommandlines) :
|
||||
Commandlines(initialCommandlines)
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
void CodeBlock::_playPressed(const Windows::Foundation::IInspectable&,
|
||||
const Windows::UI::Xaml::Input::TappedRoutedEventArgs&)
|
||||
{
|
||||
auto args = winrt::make_self<RequestRunCommandsArgs>(Commandlines());
|
||||
RequestRunCommands.raise(*this, *args);
|
||||
}
|
||||
}
|
||||
41
src/cascadia/TerminalApp/CodeBlock.h
Normal file
41
src/cascadia/TerminalApp/CodeBlock.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CodeBlock.g.h"
|
||||
#include "RequestRunCommandsArgs.g.h"
|
||||
#include "../../../src/cascadia/inc/cppwinrt_utils.h"
|
||||
#include <til/hash.h>
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct CodeBlock : CodeBlockT<CodeBlock>
|
||||
{
|
||||
CodeBlock(const winrt::hstring& initialCommandlines);
|
||||
|
||||
til::property<winrt::hstring> Commandlines;
|
||||
|
||||
// TODO! this should just be til::property_changed_event but I don't havfe tht commit here
|
||||
til::event<winrt::Windows::UI::Xaml::Data::PropertyChangedEventHandler> PropertyChanged;
|
||||
til::typed_event<TerminalApp::CodeBlock, RequestRunCommandsArgs> RequestRunCommands;
|
||||
|
||||
private:
|
||||
friend struct CodeBlockT<CodeBlock>; // for Xaml to bind events
|
||||
|
||||
void _playPressed(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& e);
|
||||
};
|
||||
|
||||
struct RequestRunCommandsArgs : RequestRunCommandsArgsT<RequestRunCommandsArgs>
|
||||
{
|
||||
RequestRunCommandsArgs(const winrt::hstring& commandlines) :
|
||||
Commandlines{ commandlines } {};
|
||||
|
||||
til::property<winrt::hstring> Commandlines;
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(CodeBlock);
|
||||
}
|
||||
21
src/cascadia/TerminalApp/CodeBlock.idl
Normal file
21
src/cascadia/TerminalApp/CodeBlock.idl
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
runtimeclass RequestRunCommandsArgs
|
||||
{
|
||||
String Commandlines { get;};
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass CodeBlock : Windows.UI.Xaml.Controls.UserControl,
|
||||
Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
CodeBlock(String initialCommandlines);
|
||||
|
||||
String Commandlines { get; set; };
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<CodeBlock, RequestRunCommandsArgs> RequestRunCommands;
|
||||
};
|
||||
|
||||
}
|
||||
170
src/cascadia/TerminalApp/CodeBlock.xaml
Normal file
170
src/cascadia/TerminalApp/CodeBlock.xaml
Normal file
@@ -0,0 +1,170 @@
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
<UserControl x:Class="TerminalApp.CodeBlock"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)"
|
||||
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
d:DesignHeight="256"
|
||||
d:DesignWidth="1024"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
|
||||
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<Color x:Key="BlockBackgroundColor">#f6f8fa</Color>
|
||||
<Color x:Key="BlockBorderColor">#d3d3d3</Color>
|
||||
<Color x:Key="PlayButtonHoveredColor">#257f01</Color>
|
||||
<Color x:Key="PlayButtonNormalColor">#88222222</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<!--<Color x:Key="BlockBackgroundColor">#161b22</Color>-->
|
||||
<Color x:Key="BlockBackgroundColor">#1e1e1e</Color>
|
||||
<Color x:Key="BlockBorderColor">#30363d</Color>
|
||||
<Color x:Key="PlayButtonHoveredColor">#90ef90</Color>
|
||||
<Color x:Key="PlayButtonNormalColor">#8888</Color>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
|
||||
<Style x:Key="PlayButtonTemplate"
|
||||
TargetType="Button">
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Padding" Value="4" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border x:Name="ButtonBaseElement"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Viewbox Width="20"
|
||||
Height="20">
|
||||
<Grid>
|
||||
<FontIcon x:Name="ButtonBackgroundIcon"
|
||||
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
Foreground="{ThemeResource PlayButtonHoveredColor}"
|
||||
Glyph=""
|
||||
Visibility="Collapsed" />
|
||||
<FontIcon x:Name="ButtonOutlineIcon"
|
||||
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
Foreground="{ThemeResource PlayButtonNormalColor}"
|
||||
Glyph="" />
|
||||
<muxc:ProgressRing x:Name="StatusProgress"
|
||||
IsActive="False" />
|
||||
</Grid>
|
||||
<!-- TODO! FontFamily="{ThemeResource SymbolThemeFontFamily}" -->
|
||||
</Viewbox>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
|
||||
<VisualState x:Name="Normal">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Visibility" Value="Collapsed" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Visibility" Value="Visible" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
|
||||
<VisualState x:Name="Disabled" />
|
||||
</VisualStateGroup>
|
||||
|
||||
<VisualStateGroup x:Name="PlayButtonStates">
|
||||
<VisualState x:Name="Ready">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Glyph" Value="" />
|
||||
<Setter Target="ButtonOutlineIcon.Glyph" Value="" />
|
||||
<Setter Target="StatusProgress.IsActive" Value="False" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Running">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Glyph" Value=" " />
|
||||
<Setter Target="ButtonOutlineIcon.Glyph" Value=" " />
|
||||
<Setter Target="StatusProgress.IsActive" Value="True" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="AlreadyRan">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Glyph" Value="" />
|
||||
<Setter Target="ButtonOutlineIcon.Glyph" Value="" />
|
||||
<Setter Target="StatusProgress.IsActive" Value="False" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
</Style>
|
||||
<Style x:Key="CodeBlockLineTemplate"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="FontFamily" Value="Cascadia Code" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button x:Name="RunButton"
|
||||
Grid.Column="0"
|
||||
Margin="0,9,0,0"
|
||||
Padding="0"
|
||||
VerticalAlignment="Top"
|
||||
Style="{StaticResource PlayButtonTemplate}"
|
||||
Tapped="_playPressed" />
|
||||
<Border Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{ThemeResource BlockBackgroundColor}"
|
||||
BorderBrush="{ThemeResource BlockBorderColor}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4">
|
||||
<StackPanel x:Name="CommandsAndOutput">
|
||||
<StackPanel x:Name="CommandLines"
|
||||
Padding="8">
|
||||
<TextBlock FontFamily="Cascadia Code"
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind Commandlines}" />
|
||||
</StackPanel>
|
||||
<StackPanel x:Name="OutputBlockContainer"
|
||||
Visibility="Collapsed">
|
||||
<!-- Put the TermControl here. -->
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -21,11 +21,22 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// This class is a wrapper of PaletteItem, that is used as an item of a filterable list in CommandPalette.
|
||||
// It manages a highlighted text that is computed by matching search filter characters to item name
|
||||
FilteredCommand::FilteredCommand(const winrt::TerminalApp::PaletteItem& item) :
|
||||
_Item(item),
|
||||
_Filter(L""),
|
||||
_Weight(0)
|
||||
FilteredCommand::FilteredCommand(const winrt::TerminalApp::PaletteItem& item)
|
||||
{
|
||||
// Actually implement the ctor in _constructFilteredCommand
|
||||
_constructFilteredCommand(item);
|
||||
}
|
||||
|
||||
// We need to actually implement the ctor in a separate helper. This is
|
||||
// because we have a FilteredTask class which derives from FilteredCommand.
|
||||
// HOWEVER, for cppwinrt ~ r e a s o n s ~, it doesn't actually derive from
|
||||
// FilteredCommand directly, so we can't just use the FilteredCommand ctor
|
||||
// directly in the base class.
|
||||
void FilteredCommand::_constructFilteredCommand(const winrt::TerminalApp::PaletteItem& item)
|
||||
{
|
||||
_Item = item;
|
||||
_Filter = L"";
|
||||
_Weight = 0;
|
||||
_HighlightedName = _computeHighlightedName();
|
||||
|
||||
// Recompute the highlighted name if the item name changes
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace winrt::TerminalApp::implementation
|
||||
FilteredCommand() = default;
|
||||
FilteredCommand(const winrt::TerminalApp::PaletteItem& item);
|
||||
|
||||
void UpdateFilter(const winrt::hstring& filter);
|
||||
virtual void UpdateFilter(const winrt::hstring& filter);
|
||||
|
||||
static int Compare(const winrt::TerminalApp::FilteredCommand& first, const winrt::TerminalApp::FilteredCommand& second);
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace winrt::TerminalApp::implementation
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::TerminalApp::HighlightedText, HighlightedName, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(int, Weight, PropertyChanged.raise);
|
||||
|
||||
protected:
|
||||
void _constructFilteredCommand(const winrt::TerminalApp::PaletteItem& item);
|
||||
|
||||
private:
|
||||
winrt::TerminalApp::HighlightedText _computeHighlightedName();
|
||||
int _computeWeight();
|
||||
|
||||
@@ -6,7 +6,7 @@ import "HighlightedTextControl.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass FilteredCommand : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
[default_interface] unsealed runtimeclass FilteredCommand : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
FilteredCommand();
|
||||
FilteredCommand(PaletteItem item);
|
||||
|
||||
459
src/cascadia/TerminalApp/MarkdownPaneContent.cpp
Normal file
459
src/cascadia/TerminalApp/MarkdownPaneContent.cpp
Normal file
@@ -0,0 +1,459 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "MarkdownPaneContent.h"
|
||||
#include <LibraryResources.h>
|
||||
#include "MarkdownPaneContent.g.cpp"
|
||||
#include "CodeBlock.h"
|
||||
#define MD4C_USE_UTF16
|
||||
#include "..\..\oss\md4c\md4c.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
using namespace winrt::Microsoft::Terminal::Settings;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
namespace MUX = Microsoft::UI::Xaml;
|
||||
namespace WUX = Windows::UI::Xaml;
|
||||
using IInspectable = Windows::Foundation::IInspectable;
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct MyMarkdownData
|
||||
{
|
||||
WUX::Controls::StackPanel root{};
|
||||
implementation::MarkdownPaneContent* page{ nullptr };
|
||||
WUX::Controls::TextBlock current{ nullptr };
|
||||
WUX::Documents::Run currentRun{ nullptr };
|
||||
TerminalApp::CodeBlock currentCodeBlock{ nullptr };
|
||||
};
|
||||
WUX::Controls::TextBlock makeDefaultTextBlock()
|
||||
{
|
||||
WUX::Controls::TextBlock b{};
|
||||
b.IsTextSelectionEnabled(true);
|
||||
b.TextWrapping(WUX::TextWrapping::WrapWholeWords);
|
||||
return b;
|
||||
}
|
||||
int md_parser_enter_block(MD_BLOCKTYPE type, void* detail, void* userdata)
|
||||
{
|
||||
MyMarkdownData* data = reinterpret_cast<MyMarkdownData*>(userdata);
|
||||
switch (type)
|
||||
{
|
||||
case MD_BLOCK_UL:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MD_BLOCK_H:
|
||||
{
|
||||
MD_BLOCK_H_DETAIL* headerDetail = reinterpret_cast<MD_BLOCK_H_DETAIL*>(detail);
|
||||
data->current = makeDefaultTextBlock();
|
||||
const auto fontSize = std::max(16u, 36u - ((headerDetail->level - 1) * 6u));
|
||||
data->current.FontSize(fontSize);
|
||||
data->current.FontWeight(Windows::UI::Text::FontWeights::Bold());
|
||||
WUX::Documents::Run run{};
|
||||
// run.Text(winrtL'#');
|
||||
|
||||
// Immediately add the header block
|
||||
data->root.Children().Append(data->current);
|
||||
|
||||
if (headerDetail->level == 1)
|
||||
{
|
||||
// <Border Height="1" BorderThickness="1" BorderBrush="Red" HorizontalAlignment="Stretch"></Border>
|
||||
WUX::Controls::Border b;
|
||||
b.Height(1);
|
||||
b.BorderThickness(WUX::ThicknessHelper::FromLengths(1, 1, 1, 1));
|
||||
b.BorderBrush(WUX::Media::SolidColorBrush(Windows::UI::Colors::Gray()));
|
||||
b.HorizontalAlignment(WUX::HorizontalAlignment::Stretch);
|
||||
data->root.Children().Append(b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MD_BLOCK_CODE:
|
||||
{
|
||||
MD_BLOCK_CODE_DETAIL* codeDetail = reinterpret_cast<MD_BLOCK_CODE_DETAIL*>(detail);
|
||||
codeDetail;
|
||||
|
||||
data->currentCodeBlock = winrt::make<implementation::CodeBlock>(L"");
|
||||
data->currentCodeBlock.Margin(WUX::ThicknessHelper::FromLengths(8, 8, 8, 8));
|
||||
data->currentCodeBlock.RequestRunCommands({ data->page, &MarkdownPaneContent::_handleRunCommandRequest });
|
||||
|
||||
data->root.Children().Append(data->currentCodeBlock);
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int md_parser_leave_block(MD_BLOCKTYPE type, void* /*detail*/, void* userdata)
|
||||
{
|
||||
MyMarkdownData* data = reinterpret_cast<MyMarkdownData*>(userdata);
|
||||
data;
|
||||
switch (type)
|
||||
{
|
||||
case MD_BLOCK_UL:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MD_BLOCK_H:
|
||||
{
|
||||
// data->root.Children().Append(data->current);
|
||||
data->current = nullptr;
|
||||
break;
|
||||
}
|
||||
case MD_BLOCK_CODE:
|
||||
{
|
||||
// data->root.Children().Append(data->current);
|
||||
data->current = nullptr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int md_parser_enter_span(MD_SPANTYPE type, void* /*detail*/, void* userdata)
|
||||
{
|
||||
MyMarkdownData* data = reinterpret_cast<MyMarkdownData*>(userdata);
|
||||
data;
|
||||
|
||||
if (data->current == nullptr)
|
||||
{
|
||||
data->current = makeDefaultTextBlock();
|
||||
data->root.Children().Append(data->current);
|
||||
}
|
||||
if (data->currentRun == nullptr)
|
||||
{
|
||||
data->currentRun = WUX::Documents::Run();
|
||||
}
|
||||
auto currentRun = data->currentRun;
|
||||
switch (type)
|
||||
{
|
||||
case MD_SPAN_STRONG:
|
||||
{
|
||||
currentRun.FontWeight(Windows::UI::Text::FontWeights::Bold());
|
||||
break;
|
||||
}
|
||||
case MD_SPAN_EM:
|
||||
{
|
||||
currentRun.FontStyle(Windows::UI::Text::FontStyle::Italic);
|
||||
break;
|
||||
}
|
||||
case MD_SPAN_CODE:
|
||||
{
|
||||
currentRun.FontFamily(WUX::Media::FontFamily{ L"Cascadia Code" });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int md_parser_leave_span(MD_SPANTYPE type, void* /*detail*/, void* userdata)
|
||||
{
|
||||
MyMarkdownData* data = reinterpret_cast<MyMarkdownData*>(userdata);
|
||||
switch (type)
|
||||
{
|
||||
case MD_SPAN_EM:
|
||||
case MD_SPAN_STRONG:
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
case MD_SPAN_CODE:
|
||||
{
|
||||
if (const auto& currentRun{ data->currentRun })
|
||||
{
|
||||
// data->current.Inlines().Append(currentRun);
|
||||
// data->currentRun = nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int md_parser_text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userdata)
|
||||
{
|
||||
MyMarkdownData* data = reinterpret_cast<MyMarkdownData*>(userdata);
|
||||
winrt::hstring str{ text, size };
|
||||
switch (type)
|
||||
{
|
||||
case MD_TEXT_BR:
|
||||
case MD_TEXT_SOFTBR:
|
||||
{
|
||||
if (const auto& curr{ data->current })
|
||||
{
|
||||
data->current = makeDefaultTextBlock();
|
||||
data->root.Children().Append(data->current);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MD_TEXT_CODE:
|
||||
{
|
||||
if (str == L"\n")
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (const auto& codeBlock{ data->currentCodeBlock })
|
||||
{
|
||||
// code in a fenced block
|
||||
auto currentText = codeBlock.Commandlines();
|
||||
auto newText = currentText.empty() ? str :
|
||||
currentText + winrt::hstring{ L"\r\n" } + str;
|
||||
codeBlock.Commandlines(newText);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// just normal `code` inline
|
||||
// data->currentRun.Text(str);
|
||||
[[fallthrough]];
|
||||
}
|
||||
}
|
||||
case MD_TEXT_NORMAL:
|
||||
default:
|
||||
{
|
||||
data->currentCodeBlock = nullptr;
|
||||
|
||||
auto run = data->currentRun ? data->currentRun : WUX::Documents::Run{};
|
||||
run.Text(str);
|
||||
if (data->current)
|
||||
{
|
||||
data->current.Inlines().Append(run);
|
||||
}
|
||||
else
|
||||
{
|
||||
WUX::Controls::TextBlock block = makeDefaultTextBlock();
|
||||
block.Inlines().Append(run);
|
||||
data->root.Children().Append(block);
|
||||
data->current = block;
|
||||
}
|
||||
// data->root.Children().Append(block);
|
||||
|
||||
data->currentRun = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parseMarkdown(const winrt::hstring& markdown, MyMarkdownData& data)
|
||||
{
|
||||
MD_PARSER parser{
|
||||
.abi_version = 0,
|
||||
.flags = 0,
|
||||
.enter_block = &md_parser_enter_block,
|
||||
.leave_block = &md_parser_leave_block,
|
||||
.enter_span = &md_parser_enter_span,
|
||||
.leave_span = &md_parser_leave_span,
|
||||
.text = &md_parser_text,
|
||||
};
|
||||
|
||||
const auto result = md_parse(
|
||||
markdown.c_str(),
|
||||
(unsigned)markdown.size(),
|
||||
&parser,
|
||||
&data // user data
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
MarkdownPaneContent::MarkdownPaneContent() :
|
||||
MarkdownPaneContent(L"") {}
|
||||
|
||||
MarkdownPaneContent::MarkdownPaneContent(const winrt::hstring& initialPath)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// auto bg = Resources().Lookup(winrt::box_value(L"PageBackground"));
|
||||
// auto brush = bg.try_as<WUX::Media::Brush>();
|
||||
// Background(brush);
|
||||
|
||||
FilePathInput().Text(initialPath);
|
||||
_filePath = FilePathInput().Text();
|
||||
_loadFile();
|
||||
}
|
||||
|
||||
INewContentArgs MarkdownPaneContent::GetNewTerminalArgs(BuildStartupKind /*kind*/) const
|
||||
{
|
||||
return BaseContentArgs(L"markdown");
|
||||
}
|
||||
|
||||
void MarkdownPaneContent::_clearOldNotebook()
|
||||
{
|
||||
RenderedMarkdown().Children().Clear();
|
||||
}
|
||||
void MarkdownPaneContent::_loadFile()
|
||||
{
|
||||
// TODO! use our til::io file readers
|
||||
|
||||
// Read _filePath, then parse as markdown.
|
||||
const wil::unique_handle file{ CreateFileW(_filePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr) };
|
||||
if (!file)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[32 * 1024];
|
||||
DWORD read = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (!ReadFile(file.get(), &buffer[0], sizeof(buffer), &read, nullptr))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (read < sizeof(buffer))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// BLINDLY TREATING TEXT AS utf-8 (I THINK)
|
||||
std::string markdownContents{ buffer, read };
|
||||
|
||||
Editing(false);
|
||||
PropertyChanged.raise(*this, WUX::Data::PropertyChangedEventArgs{ L"Editing" });
|
||||
FileContents(winrt::to_hstring(markdownContents));
|
||||
PropertyChanged.raise(*this, WUX::Data::PropertyChangedEventArgs{ L"FileContents" });
|
||||
|
||||
_renderFileContents();
|
||||
}
|
||||
void MarkdownPaneContent::_renderFileContents()
|
||||
{
|
||||
// Was the file a .md file?
|
||||
if (_filePath.ends_with(L".md"))
|
||||
{
|
||||
_loadMarkdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
_loadText();
|
||||
}
|
||||
}
|
||||
void MarkdownPaneContent::_loadText()
|
||||
{
|
||||
auto block = WUX::Controls::TextBlock();
|
||||
block.IsTextSelectionEnabled(true);
|
||||
block.FontFamily(WUX::Media::FontFamily{ L"Cascadia Code" });
|
||||
block.Text(FileContents());
|
||||
|
||||
RenderedMarkdown().Children().Append(block);
|
||||
}
|
||||
|
||||
void MarkdownPaneContent::_loadMarkdown()
|
||||
{
|
||||
MyMarkdownData data;
|
||||
data.page = this;
|
||||
|
||||
const auto parseResult = parseMarkdown(FileContents(), data);
|
||||
|
||||
if (0 == parseResult)
|
||||
{
|
||||
RenderedMarkdown().Children().Append(data.root);
|
||||
}
|
||||
}
|
||||
|
||||
void MarkdownPaneContent::_loadTapped(const Windows::Foundation::IInspectable&, const Windows::UI::Xaml::Input::TappedRoutedEventArgs&)
|
||||
{
|
||||
_filePath = FilePathInput().Text();
|
||||
// Does the file exist? if not, bail
|
||||
const wil::unique_handle file{ CreateFileW(_filePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr) };
|
||||
if (!file)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// It does. Clear the old one
|
||||
_clearOldNotebook();
|
||||
_loadFile();
|
||||
}
|
||||
|
||||
void MarkdownPaneContent::_editTapped(const Windows::Foundation::IInspectable&, const Windows::UI::Xaml::Input::TappedRoutedEventArgs&)
|
||||
{
|
||||
if (Editing())
|
||||
{
|
||||
_clearOldNotebook();
|
||||
_renderFileContents();
|
||||
|
||||
EditIcon().Glyph(L"\xe932"); // Label
|
||||
|
||||
_scrollViewer().Visibility(WUX::Visibility::Visible);
|
||||
_editor().Visibility(WUX::Visibility::Collapsed);
|
||||
|
||||
Editing(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditIcon().Glyph(L"\xe890"); // View
|
||||
|
||||
_scrollViewer().Visibility(WUX::Visibility::Collapsed);
|
||||
_editor().Visibility(WUX::Visibility::Visible);
|
||||
|
||||
Editing(true);
|
||||
}
|
||||
PropertyChanged.raise(*this, WUX::Data::PropertyChangedEventArgs{ L"Editing" });
|
||||
}
|
||||
|
||||
void MarkdownPaneContent::_closeTapped(const Windows::Foundation::IInspectable&, const Windows::UI::Xaml::Input::TappedRoutedEventArgs&)
|
||||
{
|
||||
// // Clear the old one
|
||||
// _clearOldNotebook();
|
||||
// _loadFile();
|
||||
CloseRequested.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
void MarkdownPaneContent::_handleRunCommandRequest(const TerminalApp::CodeBlock& sender,
|
||||
const TerminalApp::RequestRunCommandsArgs& request)
|
||||
{
|
||||
auto text = request.Commandlines();
|
||||
sender;
|
||||
text;
|
||||
|
||||
if (const auto& strongControl{ _control.get() })
|
||||
{
|
||||
Model::ActionAndArgs actionAndArgs{ ShortcutAction::SendInput, Model::SendInputArgs{ text + winrt::hstring{ L"\r" } } };
|
||||
|
||||
// By using the last active control as the sender here, the
|
||||
// actiopn dispatch will send this to the active control,
|
||||
// thinking that it is the control that requested this event.
|
||||
DispatchActionRequested.raise(strongControl, actionAndArgs);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma region IPaneContent
|
||||
|
||||
winrt::Windows::UI::Xaml::FrameworkElement MarkdownPaneContent::GetRoot()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
void MarkdownPaneContent::Close()
|
||||
{
|
||||
CloseRequested.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
winrt::hstring MarkdownPaneContent::Icon() const
|
||||
{
|
||||
static constexpr std::wstring_view glyph{ L"\xe70b" }; // QuickNote
|
||||
return winrt::hstring{ glyph };
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
void MarkdownPaneContent::SetLastActiveControl(const Microsoft::Terminal::Control::TermControl& control)
|
||||
{
|
||||
_control = control;
|
||||
}
|
||||
}
|
||||
82
src/cascadia/TerminalApp/MarkdownPaneContent.h
Normal file
82
src/cascadia/TerminalApp/MarkdownPaneContent.h
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MarkdownPaneContent.g.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct MarkdownPaneContent : MarkdownPaneContentT<MarkdownPaneContent>
|
||||
{
|
||||
public:
|
||||
MarkdownPaneContent();
|
||||
MarkdownPaneContent(const winrt::hstring& filePath);
|
||||
|
||||
til::property<bool> Editing{ false };
|
||||
til::property<winrt::hstring> FileContents{ L"" };
|
||||
|
||||
void SetLastActiveControl(const Microsoft::Terminal::Control::TermControl& control);
|
||||
|
||||
// TODO! this should just be til::property_changed_event but I don't have that commit here
|
||||
til::event<winrt::Windows::UI::Xaml::Data::PropertyChangedEventHandler> PropertyChanged;
|
||||
|
||||
#pragma region IPaneContent
|
||||
winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
|
||||
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings&){};
|
||||
|
||||
winrt::Windows::Foundation::Size MinimumSize() { return { 1, 1 }; };
|
||||
void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic) { reason; };
|
||||
void Close();
|
||||
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetNewTerminalArgs(BuildStartupKind kind) const;
|
||||
|
||||
// TODO! lots of strings here and in XAML that need RS_-ifying
|
||||
winrt::hstring Title() { return _filePath; }
|
||||
uint64_t TaskbarState() { return 0; }
|
||||
uint64_t TaskbarProgress() { return 0; }
|
||||
bool ReadOnly() { return false; }
|
||||
winrt::hstring Icon() const;
|
||||
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept { return nullptr; }
|
||||
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush() { return Background(); }
|
||||
|
||||
til::typed_event<> ConnectionStateChanged;
|
||||
til::typed_event<IPaneContent> CloseRequested;
|
||||
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
|
||||
til::typed_event<IPaneContent> TitleChanged;
|
||||
til::typed_event<IPaneContent> TabColorChanged;
|
||||
til::typed_event<IPaneContent> TaskbarProgressChanged;
|
||||
til::typed_event<IPaneContent> ReadOnlyChanged;
|
||||
til::typed_event<IPaneContent> FocusRequested;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
til::typed_event<winrt::Windows::Foundation::IInspectable, Microsoft::Terminal::Settings::Model::ActionAndArgs> DispatchActionRequested;
|
||||
|
||||
void _handleRunCommandRequest(const TerminalApp::CodeBlock& sender,
|
||||
const TerminalApp::RequestRunCommandsArgs& control);
|
||||
|
||||
private:
|
||||
friend struct MarkdownPaneContentT<MarkdownPaneContent>; // for Xaml to bind events
|
||||
|
||||
winrt::hstring _filePath{};
|
||||
// winrt::hstring _fileContents{};
|
||||
|
||||
winrt::weak_ref<Microsoft::Terminal::Control::TermControl> _control{ nullptr };
|
||||
|
||||
void _clearOldNotebook();
|
||||
void _loadFile();
|
||||
void _renderFileContents();
|
||||
void _loadText();
|
||||
void _loadMarkdown();
|
||||
|
||||
void _loadTapped(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& e);
|
||||
void _editTapped(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& e);
|
||||
void _closeTapped(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& e);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(MarkdownPaneContent);
|
||||
}
|
||||
25
src/cascadia/TerminalApp/MarkdownPaneContent.idl
Normal file
25
src/cascadia/TerminalApp/MarkdownPaneContent.idl
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "IPaneContent.idl";
|
||||
import "FilteredCommand.idl";
|
||||
import "CodeBlock.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass MarkdownPaneContent : Windows.UI.Xaml.Controls.UserControl,
|
||||
IPaneContent,
|
||||
Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
MarkdownPaneContent();
|
||||
MarkdownPaneContent(String originalPath);
|
||||
void SetLastActiveControl(Microsoft.Terminal.Control.TermControl control);
|
||||
|
||||
Boolean Editing;
|
||||
String FileContents;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.ActionAndArgs> DispatchActionRequested;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
129
src/cascadia/TerminalApp/MarkdownPaneContent.xaml
Normal file
129
src/cascadia/TerminalApp/MarkdownPaneContent.xaml
Normal file
@@ -0,0 +1,129 @@
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
<UserControl x:Class="TerminalApp.MarkdownPaneContent"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<!-- same as in MainPage, this is SolidBackgroundFillColorTertiary -->
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<Color x:Key="PageBackground">#282828</Color>
|
||||
<Color x:Key="PlayButtonHoveredColor">#90ef90</Color>
|
||||
<Color x:Key="PlayButtonNormalColor">#8888</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<Color x:Key="PageBackground">#F9F9F9</Color>
|
||||
<Color x:Key="PlayButtonHoveredColor">#257f01</Color>
|
||||
<Color x:Key="PlayButtonNormalColor">#88222222</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<!-- Define resources for HighContrast mode here -->
|
||||
<StaticResource x:Key="PageBackground"
|
||||
ResourceKey="SystemColorWindowColorBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid x:Name="Root"
|
||||
Background="{ThemeResource PageBackground}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox x:Name="FilePathInput"
|
||||
Grid.Column="0"
|
||||
Margin="4"
|
||||
PlaceholderText="Enter a path to a markdown file..."
|
||||
Text="Z:\dev\simple-test.md" />
|
||||
<StackPanel Grid.Column="1"
|
||||
Orientation="Horizontal">
|
||||
<Button Margin="4"
|
||||
Tapped="_loadTapped">
|
||||
<FontIcon FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
FontSize="12"
|
||||
Glyph="" />
|
||||
<!-- OpenFile -->
|
||||
</Button>
|
||||
<Button Margin="4"
|
||||
Tapped="_editTapped">
|
||||
<FontIcon x:Name="EditIcon"
|
||||
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
FontSize="12"
|
||||
Glyph="" />
|
||||
<!-- Label -->
|
||||
</Button>
|
||||
<Button Margin="4"
|
||||
Tapped="_closeTapped">
|
||||
<FontIcon FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
FontSize="12"
|
||||
Glyph="" />
|
||||
<!-- ChromeClose -->
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<Grid x:Name="TabContent"
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="0" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid x:Name="InProcContent"
|
||||
Grid.Column="0"
|
||||
Padding="16"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#ff0000" />
|
||||
|
||||
<TextBox x:Name="_editor"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
AcceptsReturn="True"
|
||||
FontFamily="Cascadia Code"
|
||||
IsSpellCheckEnabled="False"
|
||||
Text="{x:Bind FileContents, Mode=TwoWay}"
|
||||
Visibility="{x:Bind Editing}" />
|
||||
|
||||
<ScrollViewer x:Name="_scrollViewer"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
BringIntoViewOnFocusChange="True"
|
||||
IsVerticalScrollChainingEnabled="True">
|
||||
<StackPanel x:Name="RenderedMarkdown"
|
||||
Grid.Column="1"
|
||||
Padding="16"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
Orientation="Vertical" />
|
||||
</ScrollViewer>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -898,4 +898,15 @@
|
||||
<data name="RestartConnectionToolTip" xml:space="preserve">
|
||||
<value>Restart the active pane connection</value>
|
||||
</data>
|
||||
<data name="SnippetPaneTitle.Text" xml:space="preserve">
|
||||
<value>Snippets</value>
|
||||
<comment>Header for a page that includes small snippets of text for the user to enter</comment>
|
||||
</data>
|
||||
<data name="SnippetsFilterBox.PlaceholderText" xml:space="preserve">
|
||||
<value>Filter snippets...</value>
|
||||
<comment>Placeholder text for a text box to filter snippets (on the same page as the 'SnippetPaneTitle')</comment>
|
||||
</data>
|
||||
<data name="SnippetPlayButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Input this command</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
|
||||
#pragma once
|
||||
#include "winrt/TerminalApp.h"
|
||||
#include "BasicPaneEvents.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
class ScratchpadContent : public winrt::implements<ScratchpadContent, IPaneContent>
|
||||
class ScratchpadContent : public winrt::implements<ScratchpadContent, IPaneContent>, public BasicPaneEvents
|
||||
{
|
||||
public:
|
||||
ScratchpadContent();
|
||||
@@ -28,15 +29,8 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::hstring Icon() const;
|
||||
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept { return nullptr; }
|
||||
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();
|
||||
|
||||
til::typed_event<> ConnectionStateChanged;
|
||||
til::typed_event<IPaneContent> CloseRequested;
|
||||
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
|
||||
til::typed_event<IPaneContent> TitleChanged;
|
||||
til::typed_event<IPaneContent> TabColorChanged;
|
||||
til::typed_event<IPaneContent> TaskbarProgressChanged;
|
||||
til::typed_event<IPaneContent> ReadOnlyChanged;
|
||||
til::typed_event<IPaneContent> FocusRequested;
|
||||
|
||||
// See BasicPaneEvents for most generic event definitions
|
||||
|
||||
private:
|
||||
winrt::Windows::UI::Xaml::Controls::Grid _root{ nullptr };
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
#pragma once
|
||||
#include "winrt/TerminalApp.h"
|
||||
#include <LibraryResources.h>
|
||||
#include "BasicPaneEvents.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
class SettingsPaneContent : public winrt::implements<SettingsPaneContent, IPaneContent>
|
||||
class SettingsPaneContent : public winrt::implements<SettingsPaneContent, IPaneContent>, public BasicPaneEvents
|
||||
{
|
||||
public:
|
||||
SettingsPaneContent(winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings settings);
|
||||
@@ -30,14 +31,7 @@ namespace winrt::TerminalApp::implementation
|
||||
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept;
|
||||
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();
|
||||
|
||||
til::typed_event<> ConnectionStateChanged;
|
||||
til::typed_event<IPaneContent> CloseRequested;
|
||||
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
|
||||
til::typed_event<IPaneContent> TitleChanged;
|
||||
til::typed_event<IPaneContent> TabColorChanged;
|
||||
til::typed_event<IPaneContent> TaskbarProgressChanged;
|
||||
til::typed_event<IPaneContent> ReadOnlyChanged;
|
||||
til::typed_event<IPaneContent> FocusRequested;
|
||||
// See BasicPaneEvents for most generic event definitions
|
||||
|
||||
private:
|
||||
winrt::Microsoft::Terminal::Settings::Editor::MainPage _sui{ nullptr };
|
||||
|
||||
@@ -137,6 +137,16 @@ namespace winrt::TerminalApp::implementation
|
||||
// for it. The Title change will be propagated upwards through the tab's
|
||||
// PropertyChanged event handler.
|
||||
newTabImpl->ActivePaneChanged([weakTab, weakThis{ get_weak() }]() {
|
||||
// TODO!
|
||||
//
|
||||
// * Make this a method on TerminalPage.
|
||||
// * Convert ActivePaneChanged to a typed event, so it sends the sender (so we don't need to make all these lambdas)
|
||||
// * Stash the task pane as a member on the Terminal? if one was opened.
|
||||
// * If the tab does have a taskpane, then tell the taskpane the active pane changed
|
||||
//
|
||||
// wait don't do any of that. just do that in TerminalTab directly
|
||||
// before we even raise the event you donkey
|
||||
|
||||
auto page{ weakThis.get() };
|
||||
auto tab{ weakTab.get() };
|
||||
|
||||
|
||||
125
src/cascadia/TerminalApp/TasksPaneContent.cpp
Normal file
125
src/cascadia/TerminalApp/TasksPaneContent.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "TasksPaneContent.h"
|
||||
#include "TasksPaneContent.g.cpp"
|
||||
#include "FilteredTask.g.cpp"
|
||||
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Microsoft::Terminal::Settings;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
namespace WUX = Windows::UI::Xaml;
|
||||
namespace MUX = Microsoft::UI::Xaml;
|
||||
using IInspectable = Windows::Foundation::IInspectable;
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TasksPaneContent::TasksPaneContent()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// // auto res = Windows::UI::Xaml::Application::Current().Resources();
|
||||
// auto bg = Resources().Lookup(winrt::box_value(L"PageBackground"));
|
||||
// Background(bg.try_as<WUX::Media::Brush>());
|
||||
}
|
||||
|
||||
void TasksPaneContent::_updateFilteredCommands()
|
||||
{
|
||||
const auto& queryString = _filterBox().Text();
|
||||
|
||||
// DON'T replace the itemSource here. If you do, it'll un-expand all the
|
||||
// nested items the user has expanded. Instead, just update the filter.
|
||||
// That'll also trigger a PropertyChanged for the Visibility property.
|
||||
for (const auto& t : _allTasks)
|
||||
{
|
||||
t.UpdateFilter(queryString);
|
||||
}
|
||||
}
|
||||
|
||||
void TasksPaneContent::UpdateSettings(const CascadiaSettings& settings)
|
||||
{
|
||||
_settings = settings;
|
||||
|
||||
// You'd think that `FilterToSendInput(queryString)` would work. It
|
||||
// doesn't! That uses the queryString as the current command the user
|
||||
// has typed, then relies on the sxnui to _also_ filter with that
|
||||
// string.
|
||||
|
||||
const auto tasks = _settings.GlobalSettings().ActionMap().FilterToSendInput(L""); // IVector<Model::Command>
|
||||
_allTasks = winrt::single_threaded_observable_vector<TerminalApp::FilteredTask>();
|
||||
for (const auto& t : tasks)
|
||||
{
|
||||
const auto& filtered{ winrt::make<FilteredTask>(t) };
|
||||
_allTasks.Append(filtered);
|
||||
}
|
||||
_treeView().ItemsSource(_allTasks);
|
||||
|
||||
_updateFilteredCommands();
|
||||
}
|
||||
|
||||
void TasksPaneContent::_filterTextChanged(const IInspectable& /*sender*/,
|
||||
const Windows::UI::Xaml::RoutedEventArgs& /*args*/)
|
||||
{
|
||||
_updateFilteredCommands();
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Xaml::FrameworkElement TasksPaneContent::GetRoot()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
winrt::Windows::Foundation::Size TasksPaneContent::MinimumSize()
|
||||
{
|
||||
return { 1, 1 };
|
||||
}
|
||||
void TasksPaneContent::Focus(winrt::Windows::UI::Xaml::FocusState reason)
|
||||
{
|
||||
reason;
|
||||
// _box.Focus(reason);
|
||||
}
|
||||
void TasksPaneContent::Close()
|
||||
{
|
||||
CloseRequested.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
INewContentArgs TasksPaneContent::GetNewTerminalArgs(BuildStartupKind /*kind*/) const
|
||||
{
|
||||
return BaseContentArgs(L"snippets");
|
||||
}
|
||||
|
||||
winrt::hstring TasksPaneContent::Icon() const
|
||||
{
|
||||
static constexpr std::wstring_view glyph{ L"\xe70b" }; // QuickNote
|
||||
return winrt::hstring{ glyph };
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Xaml::Media::Brush TasksPaneContent::BackgroundBrush()
|
||||
{
|
||||
return Background();
|
||||
}
|
||||
|
||||
void TasksPaneContent::SetLastActiveControl(const Microsoft::Terminal::Control::TermControl& control)
|
||||
{
|
||||
_control = control;
|
||||
}
|
||||
|
||||
void TasksPaneContent::_runCommandButtonClicked(const Windows::Foundation::IInspectable& sender,
|
||||
const Windows::UI::Xaml::RoutedEventArgs&)
|
||||
{
|
||||
if (const auto& taskVM{ sender.try_as<WUX::Controls::Button>().DataContext().try_as<FilteredTask>() })
|
||||
{
|
||||
if (const auto& strongControl{ _control.get() })
|
||||
{
|
||||
// By using the last active control as the sender here, the
|
||||
// actiopn dispatch will send this to the active control,
|
||||
// thinking that it is the control that requested this event.
|
||||
DispatchCommandRequested.raise(strongControl, taskVM->Command());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
133
src/cascadia/TerminalApp/TasksPaneContent.h
Normal file
133
src/cascadia/TerminalApp/TasksPaneContent.h
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
#include "TasksPaneContent.g.h"
|
||||
#include "FilteredTask.g.h"
|
||||
#include "BasicPaneEvents.h"
|
||||
#include "FilteredCommand.h"
|
||||
#include "ActionPaletteItem.h"
|
||||
#include <LibraryResources.h>
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct TasksPaneContent : TasksPaneContentT<TasksPaneContent>, BasicPaneEvents
|
||||
{
|
||||
TasksPaneContent();
|
||||
|
||||
winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
|
||||
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
|
||||
|
||||
winrt::Windows::Foundation::Size MinimumSize();
|
||||
void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic);
|
||||
void Close();
|
||||
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetNewTerminalArgs(BuildStartupKind kind) const;
|
||||
|
||||
// TODO! lots of strings here and in XAML that need RS_-ifying
|
||||
winrt::hstring Title() { return RS_(L"SnippetPaneTitle/Text"); }
|
||||
uint64_t TaskbarState() { return 0; }
|
||||
uint64_t TaskbarProgress() { return 0; }
|
||||
bool ReadOnly() { return false; }
|
||||
winrt::hstring Icon() const;
|
||||
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept { return nullptr; }
|
||||
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();
|
||||
|
||||
void SetLastActiveControl(const Microsoft::Terminal::Control::TermControl& control);
|
||||
|
||||
// See BasicPaneEvents for most generic event definitions
|
||||
|
||||
private:
|
||||
friend struct TasksPaneContentT<TasksPaneContent>; // for Xaml to bind events
|
||||
|
||||
winrt::weak_ref<Microsoft::Terminal::Control::TermControl> _control{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings _settings{ nullptr };
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<TerminalApp::FilteredTask> _allTasks{ nullptr };
|
||||
|
||||
void _runCommandButtonClicked(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs&);
|
||||
void _filterTextChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
|
||||
|
||||
void _updateFilteredCommands();
|
||||
};
|
||||
|
||||
struct FilteredTask : FilteredTaskT<FilteredTask, TerminalApp::implementation::FilteredCommand>
|
||||
{
|
||||
FilteredTask() = default;
|
||||
|
||||
FilteredTask(const winrt::Microsoft::Terminal::Settings::Model::Command& command)
|
||||
{
|
||||
_constructFilteredCommand(winrt::make<winrt::TerminalApp::implementation::ActionPaletteItem>(command));
|
||||
_command = command;
|
||||
|
||||
// The Children() method must always return a non-null vector
|
||||
_children = winrt::single_threaded_observable_vector<TerminalApp::FilteredTask>();
|
||||
if (_command.HasNestedCommands())
|
||||
{
|
||||
for (const auto& [_, child] : _command.NestedCommands())
|
||||
{
|
||||
auto vm{ winrt::make<FilteredTask>(child) };
|
||||
_children.Append(vm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateFilter(const winrt::hstring& filter) override
|
||||
{
|
||||
TerminalApp::implementation::FilteredCommand::UpdateFilter(filter);
|
||||
for (const auto& c : _children)
|
||||
{
|
||||
c.UpdateFilter(filter);
|
||||
}
|
||||
|
||||
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Visibility" });
|
||||
}
|
||||
|
||||
winrt::hstring Input()
|
||||
{
|
||||
if (const auto& actionItem{ _Item.try_as<winrt::TerminalApp::ActionPaletteItem>() })
|
||||
{
|
||||
if (const auto& command{ actionItem.Command() })
|
||||
{
|
||||
if (const auto& sendInput{ command.ActionAndArgs().Args().try_as<winrt::Microsoft::Terminal::Settings::Model::SendInputArgs>() })
|
||||
{
|
||||
return sendInput.Input();
|
||||
}
|
||||
}
|
||||
}
|
||||
return L"";
|
||||
};
|
||||
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<TerminalApp::FilteredTask> Children() { return _children; }
|
||||
bool HasChildren() { return _children.Size() > 0; }
|
||||
winrt::Microsoft::Terminal::Settings::Model::Command Command() { return _command; }
|
||||
|
||||
// Used to control if this item is visible in the TreeView. Turns out,
|
||||
// TreeView is in fact sane enough to remove items entirely if they're
|
||||
// Collapsed.
|
||||
winrt::Windows::UI::Xaml::Visibility Visibility()
|
||||
{
|
||||
// Is there no filter, or do we match it?
|
||||
if (_Filter.empty() || _Weight > 0)
|
||||
{
|
||||
return winrt::Windows::UI::Xaml::Visibility::Visible;
|
||||
}
|
||||
// If we don't match, maybe one of our children does
|
||||
auto totalWeight = _Weight;
|
||||
for (const auto& c : _children)
|
||||
{
|
||||
totalWeight += c.Weight();
|
||||
}
|
||||
|
||||
return totalWeight > 0 ? winrt::Windows::UI::Xaml::Visibility::Visible : winrt::Windows::UI::Xaml::Visibility::Collapsed;
|
||||
};
|
||||
|
||||
private:
|
||||
winrt::Microsoft::Terminal::Settings::Model::Command _command{ nullptr };
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<TerminalApp::FilteredTask> _children{ nullptr };
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(TasksPaneContent);
|
||||
}
|
||||
253
src/cascadia/TerminalApp/TasksPaneContent.xaml
Normal file
253
src/cascadia/TerminalApp/TasksPaneContent.xaml
Normal file
@@ -0,0 +1,253 @@
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
<UserControl x:Class="TerminalApp.TasksPaneContent"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:SettingsModel="using:Microsoft.Terminal.Settings.Model"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:model="using:Microsoft.Terminal.Settings.Model"
|
||||
xmlns:mtu="using:Microsoft.Terminal.UI"
|
||||
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||
AllowFocusOnInteraction="True"
|
||||
IsTabStop="True"
|
||||
TabNavigation="Cycle"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
|
||||
<Style x:Key="PlayButtonTemplate"
|
||||
TargetType="Button">
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Padding" Value="4" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border x:Name="ButtonBaseElement"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Viewbox Width="20"
|
||||
Height="20">
|
||||
<Grid>
|
||||
<FontIcon x:Name="ButtonBackgroundIcon"
|
||||
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
Foreground="{ThemeResource PlayButtonHoveredColor}"
|
||||
Glyph=""
|
||||
Visibility="Collapsed" />
|
||||
<FontIcon x:Name="ButtonOutlineIcon"
|
||||
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
Foreground="{ThemeResource PlayButtonNormalColor}"
|
||||
Glyph="" />
|
||||
</Grid>
|
||||
<!-- TODO! FontFamily="{ThemeResource SymbolThemeFontFamily}" -->
|
||||
</Viewbox>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
|
||||
<VisualState x:Name="Normal">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Visibility" Value="Collapsed" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Visibility" Value="Visible" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Disabled" />
|
||||
</VisualStateGroup>
|
||||
|
||||
<VisualStateGroup x:Name="PlayButtonStates">
|
||||
<VisualState x:Name="Ready">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Glyph" Value="" />
|
||||
<Setter Target="ButtonOutlineIcon.Glyph" Value="" />
|
||||
<Setter Target="StatusProgress.IsActive" Value="False" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<!--
|
||||
<VisualState x:Name="Running">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Glyph" Value=" " />
|
||||
<Setter Target="ButtonOutlineIcon.Glyph" Value=" " />
|
||||
<Setter Target="StatusProgress.IsActive" Value="True" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="AlreadyRan">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Glyph" Value="" />
|
||||
<Setter Target="ButtonOutlineIcon.Glyph" Value="" />
|
||||
<Setter Target="StatusProgress.IsActive" Value="False" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>-->
|
||||
</VisualStateGroup>
|
||||
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
</Style>
|
||||
|
||||
<DataTemplate x:Key="TaskItemTemplate"
|
||||
x:DataType="local:FilteredTask">
|
||||
<mux:TreeViewItem x:Name="rootItem"
|
||||
ItemsSource="{x:Bind Children}"
|
||||
Visibility="{x:Bind Visibility, Mode=OneWay}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ContentPresenter Grid.Column="0">
|
||||
<IconSourceElement Width="16"
|
||||
Height="16"
|
||||
IconSource="{x:Bind mtu:IconPathConverter.IconSourceWUX(Item.Icon), Mode=OneTime}"
|
||||
Visibility="Collapsed" />
|
||||
</ContentPresenter>
|
||||
|
||||
<Button x:Uid="SnippetPlayButton"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="1"
|
||||
Grid.Column="0"
|
||||
Margin="-28,0,0,0"
|
||||
Padding="3"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent"
|
||||
Click="_runCommandButtonClicked"
|
||||
Style="{StaticResource PlayButtonTemplate}"
|
||||
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(HasChildren), Mode=OneWay}">
|
||||
|
||||
<Button.Content>
|
||||
<FontIcon FontFamily="Segoe Fluent Icons, Segoe MDL2 Assets"
|
||||
FontSize="12"
|
||||
Glyph="" />
|
||||
<!--
|
||||
xE768 is Play, which is just an outline.
|
||||
xF5B0 is PlaySolid, also a good option. Seemed
|
||||
better to have a lightweight outline though
|
||||
-->
|
||||
</Button.Content>
|
||||
|
||||
<Button.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<SolidColorBrush x:Key="ButtonBackground"
|
||||
Color="{ThemeResource SystemColorButtonFaceColor}" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPressed"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForeground"
|
||||
Color="{ThemeResource SystemColorButtonTextColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
|
||||
<local:HighlightedTextControl Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}" />
|
||||
<TextBlock Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="12,0,0,6"
|
||||
FontFamily="Cascadia Mono, Consolas"
|
||||
IsTextSelectionEnabled="True"
|
||||
Style="{ThemeResource BodyTextBlockStyle}"
|
||||
Text="{x:Bind Input}"
|
||||
Visibility="{Binding ElementName=rootItem, Path=IsSelected}" />
|
||||
</Grid>
|
||||
</mux:TreeViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<!-- same as in MainPage, this is SolidBackgroundFillColorTertiary -->
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<Color x:Key="PageBackground">#282828</Color>
|
||||
<Color x:Key="PlayButtonHoveredColor">#90ef90</Color>
|
||||
<Color x:Key="PlayButtonNormalColor">#8888</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<Color x:Key="PageBackground">#F9F9F9</Color>
|
||||
<Color x:Key="PlayButtonHoveredColor">#257f01</Color>
|
||||
<Color x:Key="PlayButtonNormalColor">#88222222</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<!-- Define resources for HighContrast mode here -->
|
||||
<StaticResource x:Key="PageBackground"
|
||||
ResourceKey="SystemColorWindowColorBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Background="{ThemeResource PageBackground}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock x:Name="_title"
|
||||
x:Uid="SnippetPaneTitle"
|
||||
Grid.Row="0"
|
||||
Margin="4"
|
||||
FontSize="24" />
|
||||
|
||||
<TextBox x:Name="_filterBox"
|
||||
x:Uid="SnippetsFilterBox"
|
||||
Grid.Row="1"
|
||||
Margin="8,0,8,8"
|
||||
TextChanged="_filterTextChanged" />
|
||||
|
||||
<mux:TreeView x:Name="_treeView"
|
||||
Grid.Row="2"
|
||||
CanDragItems="False"
|
||||
CanReorderItems="False"
|
||||
ItemTemplate="{StaticResource TaskItemTemplate}" />
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -71,6 +71,15 @@
|
||||
<Page Include="SuggestionsControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="TasksPaneContent.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="CodeBlock.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="MarkdownPaneContent.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<!-- ========================= Headers ======================== -->
|
||||
<ItemGroup>
|
||||
@@ -161,6 +170,9 @@
|
||||
<ClInclude Include="ScratchpadContent.h">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TasksPaneContent.h">
|
||||
<DependentUpon>TasksPaneContent.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SettingsPaneContent.h">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
@@ -171,6 +183,12 @@
|
||||
<ClInclude Include="SuggestionsControl.h">
|
||||
<DependentUpon>SuggestionsControl.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CodeBlock.h">
|
||||
<DependentUpon>CodeBlock.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MarkdownPaneContent.h">
|
||||
<DependentUpon>MarkdownPaneContent.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<!-- ========================= Cpp Files ======================== -->
|
||||
<ItemGroup>
|
||||
@@ -274,6 +292,9 @@
|
||||
<ClCompile Include="ScratchpadContent.cpp">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TasksPaneContent.cpp">
|
||||
<DependentUpon>TasksPaneContent.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SettingsPaneContent.cpp">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
@@ -285,6 +306,14 @@
|
||||
<ClCompile Include="SuggestionsControl.cpp">
|
||||
<DependentUpon>SuggestionsControl.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CodeBlock.cpp">
|
||||
<DependentUpon>CodeBlock.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MarkdownPaneContent.cpp">
|
||||
<DependentUpon>MarkdownPaneContent.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<!-- ========================= idl Files ======================== -->
|
||||
<ItemGroup>
|
||||
@@ -352,8 +381,19 @@
|
||||
</Midl>
|
||||
<Midl Include="FilteredCommand.idl" />
|
||||
<Midl Include="IPaneContent.idl" />
|
||||
<Midl Include="TerminalPaneContent.idl" />
|
||||
<Midl Include="TerminalPaneContent.idl" >
|
||||
<DependentUpon>TaskPaneContent.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="TerminalSettingsCache.idl" />
|
||||
<Midl Include="CodeBlock.idl">
|
||||
<DependentUpon>CodeBlock.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="MarkdownPaneContent.idl">
|
||||
<DependentUpon>MarkdownPaneContent.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
</ItemGroup>
|
||||
<!-- ========================= Misc Files ======================== -->
|
||||
<ItemGroup>
|
||||
@@ -373,6 +413,9 @@
|
||||
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\dep\md4c\md4c.vcxproj">
|
||||
<Project>{7CAE5851-50D5-4934-8D5E-30361A8A40F3}</Project>
|
||||
</ProjectReference>
|
||||
<!-- For whatever reason, we can't include the TerminalControl and
|
||||
TerminalSettings projects' winmds via project references. So we'll have to
|
||||
manually include the winmds as References below
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "DebugTapConnection.h"
|
||||
#include "SettingsPaneContent.h"
|
||||
#include "ScratchpadContent.h"
|
||||
#include "TasksPaneContent.h"
|
||||
#include "MarkdownPaneContent.h"
|
||||
#include "TabRowControl.h"
|
||||
#include "Utils.h"
|
||||
|
||||
@@ -454,10 +456,10 @@ namespace winrt::TerminalApp::implementation
|
||||
// - command - command to dispatch
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_OnDispatchCommandRequested(const IInspectable& /*sender*/, const Microsoft::Terminal::Settings::Model::Command& command)
|
||||
void TerminalPage::_OnDispatchCommandRequested(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::Command& command)
|
||||
{
|
||||
const auto& actionAndArgs = command.ActionAndArgs();
|
||||
_actionDispatch->DoAction(actionAndArgs);
|
||||
_actionDispatch->DoAction(sender, actionAndArgs);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -3177,6 +3179,73 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
content = _makeSettingsContent();
|
||||
}
|
||||
else if (paneType == L"snippets")
|
||||
{
|
||||
const auto& tasksContent{ winrt::make_self<TasksPaneContent>() };
|
||||
tasksContent->UpdateSettings(_settings);
|
||||
tasksContent->GetRoot().KeyDown({ this, &TerminalPage::_KeyDownHandler });
|
||||
tasksContent->DispatchCommandRequested({ this, &TerminalPage::_OnDispatchCommandRequested });
|
||||
|
||||
content = *tasksContent;
|
||||
}
|
||||
else if (paneType == L"markdown")
|
||||
{
|
||||
|
||||
// if (Feature_ScratchpadPane::IsEnabled())
|
||||
// {
|
||||
// winrt::hstring filePath = L"";
|
||||
// if (args)
|
||||
// {
|
||||
// if (const auto& realArgs = args.ActionArgs().try_as<OpenMarkdownPaneArgs>())
|
||||
// {
|
||||
// // Use the CWD of the Terminal to evaluate this path, like a
|
||||
// // startingDirectory. This lets the `wtd open` command work
|
||||
// // on relative file paths.
|
||||
|
||||
// filePath = _evaluatePathForCwd(realArgs.Path());
|
||||
// }
|
||||
// }
|
||||
|
||||
// const auto& scratchPane{ winrt::make_self<MarkdownPaneContent>(filePath) };
|
||||
// scratchPane->UpdateSettings(_settings);
|
||||
// // This is maybe a little wacky - add our key event handler to the pane
|
||||
// // we made. So that we can get actions for keys that the content didn't
|
||||
// // handle.
|
||||
// scratchPane->GetRoot().KeyDown({ this, &TerminalPage::_KeyDownHandler });
|
||||
|
||||
// // scratchPane->DispatchCommandRequested({ this, &TerminalPage::_OnDispatchCommandRequested });
|
||||
// scratchPane->DispatchActionRequested([weak = get_weak()](const auto& sender, const auto& actionAndArgs) {
|
||||
// if (const auto& page{ weak.get() })
|
||||
// {
|
||||
// page->_actionDispatch->DoAction(sender, actionAndArgs);
|
||||
// }
|
||||
// });
|
||||
|
||||
// const auto resultPane = std::make_shared<Pane>(*scratchPane);
|
||||
// _SplitPane(_senderOrFocusedTab(sender), SplitDirection::Automatic, 0.5f, resultPane);
|
||||
// args.Handled(true);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const auto& tasksContent{ winrt::make_self<MarkdownPaneContent>(L"") };
|
||||
tasksContent->UpdateSettings(_settings);
|
||||
tasksContent->GetRoot().KeyDown({ this, &TerminalPage::_KeyDownHandler });
|
||||
|
||||
// This one doesn't use DispatchCommand, because we don't create
|
||||
// Command's freely at runtime like we do with just plain old actions.
|
||||
tasksContent->DispatchActionRequested([weak = get_weak()](const auto& sender, const auto& actionAndArgs) {
|
||||
if (const auto& page{ weak.get() })
|
||||
{
|
||||
page->_actionDispatch->DoAction(sender, actionAndArgs);
|
||||
}
|
||||
});
|
||||
|
||||
content = *tasksContent;
|
||||
}
|
||||
|
||||
assert(content);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
#include "TerminalPaneContent.g.h"
|
||||
#include "BellEventArgs.g.h"
|
||||
#include "BasicPaneEvents.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
@@ -16,7 +17,7 @@ namespace winrt::TerminalApp::implementation
|
||||
til::property<bool> FlashTaskbar;
|
||||
};
|
||||
|
||||
struct TerminalPaneContent : TerminalPaneContentT<TerminalPaneContent>
|
||||
struct TerminalPaneContent : TerminalPaneContentT<TerminalPaneContent>, BasicPaneEvents
|
||||
{
|
||||
TerminalPaneContent(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
const TerminalApp::TerminalSettingsCache& cache,
|
||||
@@ -51,14 +52,8 @@ namespace winrt::TerminalApp::implementation
|
||||
Windows::Foundation::Size GridUnitSize();
|
||||
|
||||
til::typed_event<TerminalApp::TerminalPaneContent, winrt::Windows::Foundation::IInspectable> RestartTerminalRequested;
|
||||
til::typed_event<> ConnectionStateChanged;
|
||||
til::typed_event<IPaneContent> CloseRequested;
|
||||
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
|
||||
til::typed_event<IPaneContent> TitleChanged;
|
||||
til::typed_event<IPaneContent> TabColorChanged;
|
||||
til::typed_event<IPaneContent> TaskbarProgressChanged;
|
||||
til::typed_event<IPaneContent> ReadOnlyChanged;
|
||||
til::typed_event<IPaneContent> FocusRequested;
|
||||
|
||||
// See BasicPaneEvents for most generic event definitions
|
||||
|
||||
private:
|
||||
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import "IPaneContent.idl";
|
||||
import "TerminalSettingsCache.idl";
|
||||
import "FilteredCommand.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
@@ -16,4 +17,21 @@ namespace TerminalApp
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<TerminalPaneContent, Object> RestartTerminalRequested;
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass FilteredTask : TerminalApp.FilteredCommand
|
||||
{
|
||||
String Input{ get; };
|
||||
Windows.Foundation.Collections.IObservableVector<FilteredTask> Children { get; };
|
||||
Boolean HasChildren { get; };
|
||||
Windows.UI.Xaml.Visibility Visibility { get; };
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass TasksPaneContent : Windows.UI.Xaml.Controls.UserControl, IPaneContent
|
||||
{
|
||||
TasksPaneContent();
|
||||
void SetLastActiveControl(Microsoft.Terminal.Control.TermControl control);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.Command> DispatchCommandRequested;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1249,6 +1249,22 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
// Raise our own ActivePaneChanged event.
|
||||
ActivePaneChanged.raise();
|
||||
|
||||
const auto content{ pane->GetContent() };
|
||||
if (const auto termContent{ content.try_as<winrt::TerminalApp::TerminalPaneContent>() })
|
||||
{
|
||||
const auto& termControl{ termContent.GetTermControl() };
|
||||
_rootPane->WalkTree([termControl](const auto& p) {
|
||||
if (const auto& taskPane{ p->GetContent().try_as<TasksPaneContent>() })
|
||||
{
|
||||
taskPane.SetLastActiveControl(termControl);
|
||||
}
|
||||
else if (const auto& taskPane{ p->GetContent().try_as<MarkdownPaneContent>() })
|
||||
{
|
||||
taskPane.SetLastActiveControl(termControl);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -98,6 +98,7 @@ static constexpr std::string_view RestartConnectionKey{ "restartConnection" };
|
||||
static constexpr std::string_view ToggleBroadcastInputKey{ "toggleBroadcastInput" };
|
||||
static constexpr std::string_view OpenScratchpadKey{ "experimental.openScratchpad" };
|
||||
static constexpr std::string_view OpenAboutKey{ "openAbout" };
|
||||
static constexpr std::string_view OpenTasksPaneKey{ "experimental.openTasks" };
|
||||
|
||||
static constexpr std::string_view ActionKey{ "action" };
|
||||
|
||||
@@ -434,6 +435,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{ ShortcutAction::ToggleBroadcastInput, RS_(L"ToggleBroadcastInputCommandKey") },
|
||||
{ ShortcutAction::OpenScratchpad, RS_(L"OpenScratchpadKey") },
|
||||
{ ShortcutAction::OpenAbout, RS_(L"OpenAboutCommandKey") },
|
||||
{ ShortcutAction::OpenTasksPane, RS_(L"OpenTasksPaneCommandKey") },
|
||||
};
|
||||
}();
|
||||
|
||||
|
||||
@@ -928,6 +928,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
|
||||
BASIC_FACTORY(SetTabColorArgs);
|
||||
BASIC_FACTORY(RenameTabArgs);
|
||||
BASIC_FACTORY(SwapPaneArgs);
|
||||
BASIC_FACTORY(SendInputArgs);
|
||||
BASIC_FACTORY(SplitPaneArgs);
|
||||
BASIC_FACTORY(SetFocusModeArgs);
|
||||
BASIC_FACTORY(SetFullScreenArgs);
|
||||
|
||||
@@ -225,6 +225,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
|
||||
[default_interface] runtimeclass SendInputArgs : IActionArgs
|
||||
{
|
||||
SendInputArgs(String input);
|
||||
String Input { get; };
|
||||
};
|
||||
|
||||
|
||||
@@ -964,17 +964,27 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
cmdImpl.copy_from(winrt::get_self<implementation::Command>(command));
|
||||
|
||||
const auto inArgs{ command.ActionAndArgs().Args().try_as<Model::SendInputArgs>() };
|
||||
|
||||
const auto inputString{ (std::wstring_view)(inArgs ? inArgs.Input() : L"") };
|
||||
auto args = winrt::make_self<SendInputArgs>(
|
||||
winrt::hstring{ fmt::format(FMT_COMPILE(L"{:\x7f^{}}{}"),
|
||||
L"",
|
||||
numBackspaces,
|
||||
(std::wstring_view)(inArgs ? inArgs.Input() : L"")) });
|
||||
inputString) });
|
||||
Model::ActionAndArgs actionAndArgs{ ShortcutAction::SendInput, *args };
|
||||
|
||||
auto copy = cmdImpl->Copy();
|
||||
copy->ActionAndArgs(actionAndArgs);
|
||||
|
||||
if (!copy->HasName())
|
||||
{
|
||||
// Here, we want to manually generate a send input name, but
|
||||
// without visualizing space and backspace
|
||||
//
|
||||
// TODO! Do we want to include `Send Input: ` in the generated
|
||||
// string? I think it looks better without it tbh
|
||||
copy->Name(winrt::hstring{ til::visualize_nonspace_control_codes(std::wstring{ inputString }) });
|
||||
}
|
||||
|
||||
return *copy;
|
||||
};
|
||||
|
||||
|
||||
@@ -111,7 +111,8 @@
|
||||
ON_ALL_ACTIONS(RestartConnection) \
|
||||
ON_ALL_ACTIONS(ToggleBroadcastInput) \
|
||||
ON_ALL_ACTIONS(OpenScratchpad) \
|
||||
ON_ALL_ACTIONS(OpenAbout)
|
||||
ON_ALL_ACTIONS(OpenAbout) \
|
||||
ON_ALL_ACTIONS(OpenTasksPane)
|
||||
|
||||
#define ALL_SHORTCUT_ACTIONS_WITH_ARGS \
|
||||
ON_ALL_ACTIONS_WITH_ARGS(AdjustFontSize) \
|
||||
|
||||
@@ -727,4 +727,8 @@
|
||||
<value>Open about dialog</value>
|
||||
<comment>This will open the "about" dialog, to display version info and other documentation</comment>
|
||||
</data>
|
||||
</root>
|
||||
<data name="OpenTasksPaneCommandKey" xml:space="preserve">
|
||||
<value>Open tasks pane</value>
|
||||
<comment>This will open a pane with a list of the users's saved commands in it</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -447,6 +447,7 @@
|
||||
{ "command": "quit", "id": "Terminal.Quit" },
|
||||
{ "command": "restoreLastClosed", "id": "Terminal.RestoreLastClosed" },
|
||||
{ "command": "openAbout", "id": "Terminal.OpenAboutDialog" },
|
||||
{ "command": "experimental.openTasks", "id": "Terminal.OpenTasks" },
|
||||
|
||||
// Tab Management
|
||||
// "command": "closeTab" is unbound by default.
|
||||
|
||||
@@ -133,7 +133,7 @@ public: \
|
||||
_##name = value; \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
protected: \
|
||||
type _##name{ __VA_ARGS__ };
|
||||
|
||||
// Use this macro to quickly implement both the getter and setter for an
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
private: \
|
||||
protected: \
|
||||
type _##name{ __VA_ARGS__ }; \
|
||||
void _set##name(const type& value) \
|
||||
{ \
|
||||
|
||||
32
src/dep/md4c/md4c.vcxproj
Normal file
32
src/dep/md4c/md4c.vcxproj
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{7cae5851-50d5-4934-8d5e-30361a8a40f3}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>md4c</RootNamespace>
|
||||
<ProjectName>md4c</ProjectName>
|
||||
<TargetName>md4c</TargetName>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\oss\md4c;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<DisableSpecificWarnings>4242;4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<TreatSpecificWarningsAsErrors>4189;4100;4389</TreatSpecificWarningsAsErrors>
|
||||
<PreprocessorDefinitions>MD4C_USE_UTF16;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(SolutionDir)oss/md4c/md4c.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(SolutionDir)oss/md4c/md4c.h" />
|
||||
</ItemGroup>
|
||||
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
|
||||
<Import Project="$(SolutionDir)src\common.build.post.props" />
|
||||
</Project>
|
||||
@@ -24,6 +24,26 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
}
|
||||
return str;
|
||||
}
|
||||
_TIL_INLINEPREFIX std::wstring visualize_nonspace_control_codes(std::wstring str) noexcept
|
||||
{
|
||||
for (auto& ch : str)
|
||||
{
|
||||
// NOT backspace!
|
||||
if (ch < 0x20 && ch != 0x08)
|
||||
{
|
||||
ch += 0x2400;
|
||||
}
|
||||
// else if (ch == 0x20)
|
||||
// {
|
||||
// ch = 0x2423; // replace space with ␣
|
||||
// }
|
||||
else if (ch == 0x7f)
|
||||
{
|
||||
ch = 0x2421; // replace del with ␡
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
_TIL_INLINEPREFIX std::wstring visualize_control_codes(std::wstring_view str)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user