feat(userspace/apps/usr): stub implementation for mdview

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
EnderIce2 2025-03-10 01:12:10 +00:00
parent 95cc190b54
commit cc81facf50
No known key found for this signature in database
GPG Key ID: 2EE20AF089811A5A
5 changed files with 899 additions and 1 deletions

View File

@ -18,7 +18,8 @@
"userspace/libs/libm",
"devcontainer",
"userspace/libs",
"userspace/apps/test"
"userspace/apps/test",
"userspace/apps/usr"
]
}
}

View File

@ -0,0 +1,9 @@
MAKE_TARGETS := build clean
DIRECTORIES := $(sort $(dir $(wildcard ./*/)))
.PHONY: $(MAKE_TARGETS) $(DIRECTORIES)
$(MAKE_TARGETS): $(DIRECTORIES)
$(DIRECTORIES):
$(MAKE) -C $@ $(MAKECMDGOALS)

View File

@ -0,0 +1,33 @@
default:
$(error Do not run this Makefile directly!)
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
OBJ = $(S_SOURCES:.S=.o) $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o)
FILENAME = $(notdir $(shell pwd))
WARNCFLAG = -Wall -Wextra
build: $(FILENAME).elf
cp $(FILENAME).elf $(WORKSPACE_DIR)/out/usr/bin/$(FILENAME)
$(FILENAME).elf: $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(SYSROOT) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CXX) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
clean:
rm -f $(OBJ) $(FILENAME).elf

View File

@ -0,0 +1,419 @@
/*
This file is part of Fennix Userspace.
Fennix Userspace is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Userspace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
#define ANSI_COLOR_YELLOW "\x1b[33m"
#define ANSI_COLOR_BLUE "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN "\x1b[36m"
#define ANSI_COLOR_WHITE "\x1b[37m"
#define ANSI_COLOR_BLACK "\x1b[30m"
#define ANSI_COLOR_RESET "\x1b[0m"
#define ANSI_BG_BLACK "\x1b[40m"
#define ANSI_BG_RED "\x1b[41m"
#define ANSI_BG_GREEN "\x1b[42m"
#define ANSI_BG_YELLOW "\x1b[43m"
#define ANSI_BG_BLUE "\x1b[44m"
#define ANSI_BG_MAGENTA "\x1b[45m"
#define ANSI_BG_CYAN "\x1b[46m"
#define ANSI_BG_GRAY "\x1b[47m"
#define ANSI_BG_DARK_GRAY "\x1b[100m"
#define ANSI_BOLD "\x1b[1m"
#define ANSI_UNDERLINE "\x1b[4m"
#define ANSI_STRIKETHROUGH "\x1b[9m"
#define ANSI_HIGHLIGHT "\x1b[43m"
void print_horizontal_rule()
{
int width;
struct winsize ws;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
width = ws.ws_col;
for (int i = 0; i < width - 2; i++)
printf("-");
}
void print_admonition(const char *type, const char *title, const char *content)
{
if (strcmp(type, "warning") == 0)
{
printf(ANSI_BG_YELLOW);
printf(ANSI_COLOR_BLACK);
printf("! Warning: %s %s\n", title, content);
}
else if (strcmp(type, "note") == 0)
{
printf(ANSI_BG_BLUE);
printf(ANSI_COLOR_WHITE);
printf("i Note: %s %s\n", title, content);
}
else if (strcmp(type, "tip") == 0)
{
printf(ANSI_BG_GREEN);
printf(ANSI_COLOR_WHITE);
printf("? Tip: %s %s\n", title, content);
}
else if (strcmp(type, "important") == 0)
{
printf(ANSI_BG_RED);
printf(ANSI_COLOR_BLACK);
printf("! Important: %s %s\n", title, content);
}
else if (strcmp(type, "caution") == 0)
{
printf(ANSI_BG_MAGENTA);
printf(ANSI_COLOR_WHITE);
printf("! Caution: %s %s\n", title, content);
}
else if (strcmp(type, "danger") == 0)
{
printf(ANSI_BG_RED);
printf(ANSI_COLOR_BLACK);
printf("! Danger: %s %s\n", title, content);
}
printf(ANSI_COLOR_RESET);
}
void print_formatted_text(const char *text)
{
bool bold = false;
bool underline = false;
bool inline_code = false;
bool strikethrough = false;
bool highlight = false;
for (int i = 0; text[i] != '\0'; ++i)
{
if (strncmp(&text[i], "!!!", 3) == 0)
{
char admonition_type[20] = "";
char admonition_title[256] = "";
int type_start = i + 4;
int type_end = -1;
int title_start = -1;
int title_end = -1;
int content_start = -1;
for (int j = type_start; text[j] != '\0' && text[j] != ' ' && text[j] != '"'; ++j)
{
type_end = j;
}
if (type_end != -1)
{
strncpy(admonition_type, &text[type_start], type_end - type_start + 1);
admonition_type[type_end - type_start + 1] = '\0';
i = type_end + 1;
}
if (text[i] == ' ' && text[i + 1] == '"')
{
title_start = i + 2;
for (int j = title_start; text[j] != '\0' && text[j] != '"'; ++j)
{
title_end = j;
}
if (title_end != -1)
{
strncpy(admonition_title, &text[title_start], title_end - title_start + 1);
admonition_title[title_end - title_start + 1] = '\0';
i = title_end + 1;
}
}
content_start = i + 1;
print_admonition(admonition_type, admonition_title, text + content_start);
return;
}
if (text[i] == '`')
{
if (!inline_code)
{
printf(ANSI_BG_MAGENTA);
printf(ANSI_UNDERLINE);
printf(ANSI_BOLD);
inline_code = true;
}
else
{
printf(ANSI_COLOR_RESET);
inline_code = false;
}
}
else if (text[i] == '*' && text[i + 1] == '*')
{
if (!bold)
{
printf(ANSI_BOLD);
bold = true;
i++;
}
else
{
printf(ANSI_COLOR_RESET);
bold = false;
i++;
}
}
else if (text[i] == '_' && text[i + 1] == '_')
{
if (!underline)
{
printf(ANSI_UNDERLINE);
underline = true;
i++;
}
else
{
printf(ANSI_COLOR_RESET);
underline = false;
i++;
}
}
else if (text[i] == '~' && text[i + 1] == '~')
{
if (!strikethrough)
{
printf(ANSI_STRIKETHROUGH);
strikethrough = true;
i++;
}
else
{
printf(ANSI_COLOR_RESET);
strikethrough = false;
i++;
}
}
else if (text[i] == '=' && text[i + 1] == '=')
{
if (!highlight)
{
printf(ANSI_HIGHLIGHT);
highlight = true;
i++;
}
else
{
printf(ANSI_COLOR_RESET);
highlight = false;
i++;
}
}
else if (text[i] == '[')
{
int start_link_text = i + 1;
int end_link_text = -1;
int start_link_url = -1;
int end_link_url = -1;
for (int j = start_link_text; text[j] != '\0'; ++j)
{
if (text[j] == ']')
{
end_link_text = j;
if (text[j + 1] == '(')
{
start_link_url = j + 2;
for (int k = start_link_url; text[k] != '\0'; ++k)
{
if (text[k] == ')')
{
end_link_url = k;
break;
}
}
}
break;
}
}
if (end_link_text != -1 && start_link_url != -1 && end_link_url != -1)
{
char link_text[256];
strncpy(link_text, &text[start_link_text], end_link_text - start_link_text);
link_text[end_link_text - start_link_text] = '\0';
char link_url[256];
strncpy(link_url, &text[start_link_url], end_link_url - start_link_url);
link_url[end_link_url - start_link_url] = '\0';
printf(ANSI_UNDERLINE);
printf(link_text);
printf(ANSI_COLOR_RESET);
printf("(%s)", link_url);
i = end_link_url;
continue;
}
}
else if (text[i] == '<')
{
while (text[i] != '\0' && text[i] != '>')
{
i++;
}
if (text[i] == '>')
{
continue;
}
}
else if (strncmp(&text[i], "---\n", 4) == 0 || strncmp(&text[i], "***\n", 4) == 0 || strncmp(&text[i], "_________________\n", 18) == 0)
{
print_horizontal_rule();
i += 2;
continue;
}
else if (strncmp(&text[i], "- [x] ", 6) == 0)
{
printf("[X] ");
i += 5;
continue;
}
else if (strncmp(&text[i], "- [ ] ", 6) == 0)
{
printf("[ ] ");
i += 5;
continue;
}
else
{
printf("%c", text[i]);
}
}
printf(ANSI_COLOR_RESET);
}
void process_markdown_file(const char *filename)
{
FILE *file = fopen(filename, "r");
if (file == NULL)
{
perror("fopen");
return;
}
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, file)) != -1)
{
if (strncmp(line, "# ", 2) == 0)
{
printf(ANSI_BOLD);
printf(ANSI_UNDERLINE);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "## ", 3) == 0)
{
printf(ANSI_BOLD);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "### ", 4) == 0)
{
printf(ANSI_UNDERLINE);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "#### ", 5) == 0)
{
printf(ANSI_BOLD);
printf(ANSI_UNDERLINE);
printf(ANSI_COLOR_RED);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "##### ", 6) == 0)
{
printf(ANSI_BOLD);
printf(ANSI_COLOR_MAGENTA);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "###### ", 7) == 0)
{
printf(ANSI_UNDERLINE);
printf(ANSI_COLOR_BLUE);
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "```", 3) == 0)
{
printf(ANSI_BG_DARK_GRAY);
printf(ANSI_COLOR_WHITE);
printf("%s", line);
while ((read = getline(&line, &len, file)) != -1 && strncmp(line, "```", 3) != 0)
{
printf("%s", line);
}
printf("%s", line);
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, "> ", 2) == 0 && strncmp(line, ">> ", 3) != 0)
{
printf(ANSI_COLOR_WHITE);
printf(ANSI_BG_GRAY " " ANSI_BG_DARK_GRAY "%s", line + (strncmp(line, ">>", 2) == 0 ? 2 : 1));
printf(ANSI_COLOR_RESET);
}
else if (strncmp(line, ">\n", 2) == 0)
{
printf(ANSI_COLOR_WHITE);
printf(ANSI_BG_GRAY " \n");
printf(ANSI_COLOR_RESET);
}
else
{
print_formatted_text(line);
}
}
fclose(file);
if (line)
free(line);
}
void print_usage()
{
printf("Usage: mdview <markdown_file>\n");
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "mdview: invalid arguments\n");
print_usage();
exit(EXIT_FAILURE);
}
process_markdown_file(argv[1]);
return 0;
}

View File

@ -0,0 +1,436 @@
## Admonitions
> :warning: **Warning:** This is a warning.
> :memo: **Note:** This is a note.
> :bulb: **Tip:** This is a tip.
## GitHub Admonitions
> [!NOTE]
> This is a note.
> [!TIP]
> This is a tip.
> [!IMPORTANT]
> This is important.
> [!WARNING]
> This is a warning.
> [!CAUTION]
> This is a caution.
## python-markdown Admonitions
!!! note "This is a note."
Hello World!
!!! danger "This is a danger."
Hello World!
!!! important "This is important."
Hello World!
!!! warning "This is a warning."
Hello World!
!!! caution "This is a caution."
Hello World!
[The section below is an excerpt of the original.](https://www.markdownguide.org/cheat-sheet/)
The original content is licensed under a CC BY-SA 4.0 license. The original content can be found at the link above.
## Headings
# Heading level 1
## Heading level 2
### Heading level 3
#### Heading level 4
##### Heading level 5
###### Heading level 6
## Alternate Syntax
Heading level 1
===============
Heading level 2
---------------
---
## Paragraphs
I really like using Markdown.
I think I'll use it to format all of my documents from now on.
---
## Line Breaks
This is the first line.
And this is the second line.
---
## Emphasis
I just love **bold text**.
I just love __bold text__.
Love**is**bold
Italicized text is the *cat's meow*.
Italicized text is the _cat's meow_.
A*cat*meow
This text is ***really important***.
This text is ___really important___.
This text is __*really important*__.
This text is **_really important_**.
This is really***very***important text.
---
## Blockquotes
> Dorothy followed her through many of the beautiful rooms in her castle.
> Dorothy followed her through many of the beautiful rooms in her castle.
>
> The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood.
> Dorothy followed her through many of the beautiful rooms in her castle.
>
>> The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood.
> #### The quarterly results look great!
>
> - Revenue was off the chart.
> - Profits were higher than ever.
>
> *Everything* is going according to **plan**.
---
## Lists
List 1
1. First item
2. Second item
3. Third item
4. Fourth item
List 2
1. First item
1. Second item
1. Third item
1. Fourth item
List 3
1. First item
8. Second item
3. Third item
5. Fourth item
List 4
1. First item
2. Second item
3. Third item
1. Indented item
2. Indented item
4. Fourth item
List 5
- First item
- Second item
- Third item
- Fourth item
List 6
* First item
* Second item
* Third item
* Fourth item
List 7
+ First item
+ Second item
+ Third item
+ Fourth item
List 8
- First item
- Second item
- Third item
- Indented item
- Indented item
- Fourth item
List 9
- 1968\. A great year!
- I think 1969 was second best.
---
## Paragraphs
* This is the first list item.
* Here's the second list item.
I need to add another paragraph below the second list item.
* And here's the third list item.
* This is the first list item.
* Here's the second list item.
> A blockquote would look great below the second list item.
* And here's the third list item.
---
## Code Blocks
1. Open the file.
2. Find the following code block on line 21:
<html>
<head>
<title>Test</title>
</head>
3. Update the title to match the name of your website.
---
## Images
1. Open the file containing the Linux mascot.
2. Marvel at its beauty.
![Tux, the Linux mascot](https://mdg.imgix.net/assets/images/tux.png)
3. Close the file.
---
## Code
At the command prompt, type `nano`.
``Use `code` in your Markdown file.``
<html>
<head>
</head>
</html>
---
## Horizontal Rules
***
---
_________________
---
## Links
My favorite search engine is [Duck Duck Go](https://duckduckgo.com).
My favorite search engine is [Duck Duck Go](https://duckduckgo.com "The best search engine for privacy").
<https://www.markdownguide.org>
<fake@example.com>
I love supporting the **[EFF](https://eff.org)**.
This is the *[Markdown Guide](https://www.markdownguide.org)*.
See the section on [`code`](#code).
In a hole in the ground there lived a hobbit. Not a nasty, dirty, wet hole, filled with the ends
of worms and an oozy smell, nor yet a dry, bare, sandy hole with nothing in it to sit down on or to
eat: it was a [hobbit-hole][1], and that means comfort.
[1]: <https://en.wikipedia.org/wiki/Hobbit#Lifestyle> "Hobbit lifestyles"
---
## Escaping Characters
\* Without the backslash, this would be a bullet in an unordered list.
\\ test
\` test
\* test
\_ test
\{ test
\} test
\[ test
\] test
\< test
\> test
\( test
\) test
\# test
\+ test
\- test
\. test
\! test
\| test
---
## HTML
This **word** is bold. This <em>word</em> is italic.
## Tables
| Syntax | Description |
| ----------- | ----------- |
| Header | Title |
| Paragraph | Text |
| Syntax | Description |
| --- | ----------- |
| Header | Title |
| Paragraph | Text |
| Syntax | Description | Test Text |
| :--- | :----: | ---: |
| Header | Title | Here's this |
| Paragraph | Text | And more |
---
## Fenced Code Blocks
```
{
"firstName": "John",
"lastName": "Smith",
"age": 25
}
```
```json
{
"firstName": "John",
"lastName": "Smith",
"age": 25
}
```
---
## Footnotes
Here's a simple footnote,[^1] and here's a longer one.[^bignote]
[^1]: This is the first footnote.
[^bignote]: Here's one with multiple paragraphs and code.
Indent paragraphs to include them in the footnote.
`{ my code }`
Add as many paragraphs as you like.
---
## Heading IDs
# Heading level 1 {#custom-id}
## Heading level 2 {#custom-id}
### Heading level 3 {#custom-id}
#### Heading level 4 {#custom-id}
##### Heading level 5 {#custom-id}
###### Heading level 6 {#custom-id}
---
## Strikethrough
~~The world is flat.~~ We now know that the world is round.
---
## Task Lists
- [x] Write the press release
- [ ] Update the website
- [ ] Contact the media
---
## Emoji
Gone camping! :tent: Be back soon.
That is so funny! :joy:
---
## Highlight
I need to highlight these ==very important words==.
---
## Subscript and Superscript
H~2~O
X^2^
---
## Disabling Automatic URL Linking
`http://www.example.com`