diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4e95702bc3..7a2a6e50b6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -233,4 +233,14 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/termux/app/TermuxActivity.java b/app/src/main/java/com/termux/app/TermuxActivity.java
index 308d1f0b2b..89323e3cd3 100644
--- a/app/src/main/java/com/termux/app/TermuxActivity.java
+++ b/app/src/main/java/com/termux/app/TermuxActivity.java
@@ -18,6 +18,7 @@
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -39,6 +40,7 @@
import com.termux.shared.data.IntentUtils;
import com.termux.shared.android.PermissionUtils;
import com.termux.shared.data.DataUtils;
+import com.termux.shared.interact.ProcessTextUtils;
import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY;
import com.termux.app.activities.HelpActivity;
@@ -68,6 +70,7 @@
import androidx.viewpager.widget.ViewPager;
import java.util.Arrays;
+import java.util.List;
/**
* A terminal emulator activity.
@@ -189,6 +192,8 @@ public final class TermuxActivity extends AppCompatActivity implements ServiceCo
private static final int CONTEXT_MENU_HELP_ID = 7;
private static final int CONTEXT_MENU_SETTINGS_ID = 8;
private static final int CONTEXT_MENU_REPORT_ID = 9;
+ private static final int CONTEXT_MENU_SUBMENU_PROCESS_TEXT_ID = 11;
+ private static final int CONTEXT_MENU_LAUNCH_EXTERNAL_APP_PROCESS_TEXT_ID = 12;
private static final String ARG_TERMINAL_TOOLBAR_TEXT_INPUT = "terminal_toolbar_text_input";
private static final String ARG_ACTIVITY_RECREATED = "activity_recreated";
@@ -642,8 +647,20 @@ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuIn
menu.add(Menu.NONE, CONTEXT_MENU_SELECT_URL_ID, Menu.NONE, R.string.action_select_url);
menu.add(Menu.NONE, CONTEXT_MENU_SHARE_TRANSCRIPT_ID, Menu.NONE, R.string.action_share_transcript);
- if (!DataUtils.isNullOrEmpty(mTerminalView.getStoredSelectedText()))
+ String selectedText = mTerminalView.getStoredSelectedText();
+ if (!DataUtils.isNullOrEmpty(selectedText)) {
menu.add(Menu.NONE, CONTEXT_MENU_SHARE_SELECTED_TEXT, Menu.NONE, R.string.action_share_selected_text);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ List processTextActivities = ProcessTextUtils.getProcessTextActivities(this, selectedText);
+ if (!processTextActivities.isEmpty()) {
+ SubMenu processTextSubmenu = menu.addSubMenu(Menu.NONE, CONTEXT_MENU_SUBMENU_PROCESS_TEXT_ID, Menu.NONE, R.string.action_process_text);
+ for (ProcessTextUtils.ProcessTextActivityData processTextActivityData : processTextActivities) {
+ processTextSubmenu.add(Menu.NONE, CONTEXT_MENU_LAUNCH_EXTERNAL_APP_PROCESS_TEXT_ID, Menu.NONE, processTextActivityData.label)
+ .setIntent(processTextActivityData.intent);
+ }
+ }
+ }
+ }
if (addAutoFillMenu)
menu.add(Menu.NONE, CONTEXT_MENU_AUTOFILL_ID, Menu.NONE, R.string.action_autofill_password);
menu.add(Menu.NONE, CONTEXT_MENU_RESET_TERMINAL_ID, Menu.NONE, R.string.action_reset_terminal);
@@ -700,6 +717,9 @@ public boolean onContextItemSelected(MenuItem item) {
case CONTEXT_MENU_REPORT_ID:
mTermuxTerminalViewClient.reportIssueFromTranscript();
return true;
+ case CONTEXT_MENU_LAUNCH_EXTERNAL_APP_PROCESS_TEXT_ID:
+ ActivityUtils.startActivity(this, item.getIntent());
+ return true;
default:
return super.onContextItemSelected(item);
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 794d8df3e0..23a4d37f8a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -90,6 +90,8 @@
Generating Report
Add termux debug info to report?
+ Select text processing app…
+
The &TERMUX_STYLING_APP_NAME; Plugin App is not installed.
Install
diff --git a/termux-shared/src/main/java/com/termux/shared/interact/ProcessTextUtils.java b/termux-shared/src/main/java/com/termux/shared/interact/ProcessTextUtils.java
new file mode 100644
index 0000000000..3dcb92cb7c
--- /dev/null
+++ b/termux-shared/src/main/java/com/termux/shared/interact/ProcessTextUtils.java
@@ -0,0 +1,69 @@
+package com.termux.shared.interact;
+
+import android.annotation.TargetApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Build;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProcessTextUtils {
+
+ /**
+ * Data required to interact with an activity that supports the PROCESS_TEXT intent.
+ */
+ public static class ProcessTextActivityData {
+ /**
+ * The label of the external app activity.
+ */
+ public final CharSequence label;
+
+ /**
+ * The intent to launch the activity.
+ */
+ public final Intent intent;
+
+ private ProcessTextActivityData(CharSequence label, Intent intent) {
+ this.label = label;
+ this.intent = intent;
+ }
+ }
+
+ /**
+ * Retrieve a list of activities (including outside of this app) that support the
+ * {@link Intent#ACTION_PROCESS_TEXT} intent action. For each item in the returned
+ * list, its Intent can be used to launch the activity with the given text.
+ *
+ * @param context The context for operations
+ * @param text The text to send in the Intents for the supported activities.
+ * @return a List of {@link ProcessTextActivityData} for supported activities.
+ */
+ @TargetApi(Build.VERSION_CODES.M)
+ public static List getProcessTextActivities(Context context, String text) {
+ PackageManager packageManager = context.getPackageManager();
+ Intent processTextIntent = new Intent(Intent.ACTION_PROCESS_TEXT);
+ processTextIntent.setType("text/plain");
+ List activities = packageManager.queryIntentActivities(processTextIntent, PackageManager.MATCH_ALL);
+ List result = new ArrayList<>();
+ for (ResolveInfo resolveInfo : activities) {
+ CharSequence label = resolveInfo.loadLabel(packageManager);
+ result.add(new ProcessTextActivityData(label, createProcessTextIntentForPackage(resolveInfo.activityInfo, text)));
+ }
+ return result;
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ private static Intent createProcessTextIntentForPackage(ActivityInfo activityInfo, String text) {
+ Intent intent = new Intent(Intent.ACTION_PROCESS_TEXT);
+ intent.setComponent(new ComponentName(activityInfo.packageName, activityInfo.name));
+ intent.setType("text/plain");
+ intent.putExtra(Intent.EXTRA_PROCESS_TEXT, text);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return intent;
+ }
+}