Skip to content

Commit 3248543

Browse files
committed
Added trim-trailing-whitespace command (SpartanJ/ecode#667).
Added `delete-to-start-of-line` command (SpartanJ/ecode#668). Added OpenRouter support to the AI Assistant.
1 parent 5f66600 commit 3248543

File tree

5 files changed

+80
-3
lines changed

5 files changed

+80
-3
lines changed

.ecode/project_build.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@
406406
"eepp-linux-ninja": {
407407
"build": [
408408
{
409-
"args": "--disable-static-build --with-text-shaper ninja",
409+
"args": "--disable-static-build --with-text-shaper --with-debug-symbols ninja",
410410
"command": "premake5",
411411
"working_dir": "${project_root}"
412412
},

bin/assets/plugins/aiassistant.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,48 @@
375375
"tool_calling": true
376376
}
377377
]
378+
},
379+
"openrouter": {
380+
"api_url": "https://openrouter.ai/api/v1/chat/completions",
381+
"display_name": "OpenRouter",
382+
"models": [
383+
{
384+
"name": "x-ai/grok-4-fast:free",
385+
"display_name": "xAI: Grok 4 Fast (free)"
386+
},
387+
{
388+
"name": "deepseek/deepseek-chat-v3.1:free",
389+
"display_name": "DeepSeek: DeepSeek V3.1 (free)"
390+
},
391+
{
392+
"name": "x-ai/grok-code-fast-1",
393+
"display_name": "xAI: Grok Code Fast 1"
394+
},
395+
{
396+
"name": "anthropic/claude-sonnet-4",
397+
"display_name": "Anthropic: Claude Sonnet 4"
398+
},
399+
{
400+
"name": "google/gemini-2.5-flash",
401+
"display_name": "Google: Gemini 2.5 Flash"
402+
},
403+
{
404+
"name": "deepseek/deepseek-chat-v3-0324",
405+
"display_name": "DeepSeek: DeepSeek V3 0324"
406+
},
407+
{
408+
"name": "google/gemini-2.5-pro",
409+
"display_name": "Google: Gemini 2.5 Pro"
410+
},
411+
{
412+
"name": "openai/gpt-5",
413+
"display_name": "OpenAI: GPT-5"
414+
},
415+
{
416+
"name": "google/gemini-2.5-flash-lite",
417+
"display_name": "Google: Gemini 2.5 Flash Lite"
418+
}
419+
]
378420
}
379421
}
380422
}

include/eepp/ui/doc/textdocument.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ class EE_API TextDocument {
239239

240240
TextPosition positionOffset( TextPosition position, TextPosition offset ) const;
241241

242-
bool replaceLine( const Int64& lineNum, const String& text );
242+
bool replaceLine( Int64 lineNum, const String& text );
243243

244244
bool replaceCurrentLine( const String& text );
245245

@@ -357,6 +357,8 @@ class EE_API TextDocument {
357357

358358
void deleteToNextChar();
359359

360+
void deleteToStartOfLine();
361+
360362
void deleteToEndOfLine();
361363

362364
void deleteToPreviousWord();
@@ -705,6 +707,8 @@ class EE_API TextDocument {
705707

706708
void fromBase64();
707709

710+
void trimTrailingWhitespace();
711+
708712
protected:
709713
friend class TextUndoStack;
710714
friend class FoldRangeService;

src/eepp/ui/doc/textdocument.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1567,7 +1567,7 @@ TextPosition TextDocument::positionOffset( TextPosition position, TextPosition o
15671567
return sanitizePosition( position + offset );
15681568
}
15691569

1570-
bool TextDocument::replaceLine( const Int64& lineNum, const String& text ) {
1570+
bool TextDocument::replaceLine( Int64 lineNum, const String& text ) {
15711571
if ( lineNum >= 0 && lineNum < (Int64)linesCount() ) {
15721572
TextRange oldSelection = getSelection();
15731573
setSelection( { startOfLine( { lineNum, 0 } ), endOfLine( { lineNum, 0 } ) } );
@@ -2200,6 +2200,12 @@ void TextDocument::deleteToNextChar() {
22002200
mergeSelection();
22012201
}
22022202

2203+
void TextDocument::deleteToStartOfLine() {
2204+
for ( size_t i = 0; i < mSelection.size(); ++i )
2205+
deleteTo( i, startOfLine( getSelectionIndex( i ).start() ) );
2206+
mergeSelection();
2207+
}
2208+
22032209
void TextDocument::deleteToEndOfLine() {
22042210
for ( size_t i = 0; i < mSelection.size(); ++i )
22052211
deleteTo( i, endOfLine( getSelectionIndex( i ).start() ) );
@@ -4111,6 +4117,21 @@ void TextDocument::fromBase64() {
41114117
}
41124118
}
41134119

4120+
void TextDocument::trimTrailingWhitespace() {
4121+
BoolScopedOpOptional op( !mDoingTextInput, mDoingTextInput, true );
4122+
for ( size_t i = 0; i < linesCount(); i++ ) {
4123+
safeLineOp( i, [&]( TextDocumentLine& op ) {
4124+
if ( op.size() > 1 && ( op[op.size() - 2] == ' ' || op[op.size() - 2] == '\t' ) ) {
4125+
String text( op.getText() );
4126+
text.pop_back(); // Remove '\n'
4127+
while ( !text.empty() && ( text.back() == ' ' || text.back() == '\t' ) )
4128+
text.pop_back();
4129+
replaceLine( i, text );
4130+
}
4131+
} );
4132+
}
4133+
}
4134+
41144135
void TextDocument::initializeCommands() {
41154136
mCommands["reset"] = [this] { reset(); };
41164137
mCommands["save"] = [this] { save(); };
@@ -4119,6 +4140,7 @@ void TextDocument::initializeCommands() {
41194140
mCommands["delete-to-next-word"] = [this] { deleteToNextWord(); };
41204141
mCommands["delete-to-next-char"] = [this] { deleteToNextChar(); };
41214142
mCommands["delete-current-line"] = [this] { deleteCurrentLine(); };
4143+
mCommands["delete-to-start-of-line"] = [this] { deleteToStartOfLine(); };
41224144
mCommands["delete-to-end-of-line"] = [this] { deleteToEndOfLine(); };
41234145
mCommands["delete-selection"] = [this] { deleteSelection(); };
41244146
mCommands["delete-word"] = [this] { deleteWord(); };
@@ -4174,6 +4196,7 @@ void TextDocument::initializeCommands() {
41744196
mCommands["unescape"] = [this] { unescape(); };
41754197
mCommands["to-base64"] = [this] { toBase64(); };
41764198
mCommands["from-base64"] = [this] { fromBase64(); };
4199+
mCommands["trim-trailing-whitespace"] = [this] { trimTrailingWhitespace(); };
41774200

41784201
if ( TEXT_DOCUMENT_COMMANDS.empty() ) {
41794202
for ( const auto& [cmd, _] : mCommands )

src/tools/ecode/plugins/aiassistant/aiassistantplugin.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,11 @@ void AIAssistantPlugin::loadAIAssistantConfig( const std::string& path, bool upd
328328
else if ( updateConfigFile )
329329
config["perplexity_api_key"] = mApiKeys["perplexity"];
330330

331+
if ( config.contains( "openrouter_api_key" ) )
332+
mApiKeys["openrouter"] = config.value( "openrouter_api_key", "" );
333+
else if ( updateConfigFile )
334+
config["openrouter_api_key"] = mApiKeys["openrouter"];
335+
331336
}
332337

333338
if ( mKeyBindings.empty() ) {
@@ -511,7 +516,10 @@ std::optional<std::string> AIAssistantPlugin::getApiKeyFromProvider( const std::
511516
ret = getenv( "GITHUB_API_KEY" );
512517
} else if ( provider == "perplexity" ) {
513518
ret = getenv( "PERPLEXITY_API_KEY" );
519+
} else if ( provider == "openrouter" ) {
520+
ret = getenv( "OPENROUTER_API_KEY" );
514521
}
522+
515523
if ( ret )
516524
return std::string{ ret };
517525

0 commit comments

Comments
 (0)